Spaces:
Running
Running
File size: 7,842 Bytes
ac8a60b 8434471 ac8a60b 8434471 ac8a60b 8434471 ac8a60b 8434471 ac8a60b 8434471 ac8a60b 8434471 ac8a60b 8434471 ac8a60b 8434471 ac8a60b b580d80 8434471 b580d80 ac8a60b 8434471 ac8a60b 8434471 ac8a60b 8434471 ac8a60b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
import sqlite3
import streamlit as st
from pydantic import BaseModel, Field
from llama_index.core.tools import FunctionTool
import time
db_path = "./database/mock_qna.sqlite"
qna_question_description = """
Use this tool to extract the chapter number from the body of input text,
thereafter, chapter number will be used as a filtering criteria for
extracting the right questions set from database.
The format of the function argument looks as follow:
It should be in the format with `Chapter_` as prefix.
Example 1: `Chapter_1` for first chapter
Example 2: For chapter 12 of the textbook, you should return `Chapter_12`
Example 3: `Chapter_5` for fifth chapter
Thereafter, the chapter_n argument will be passed to the function for Q&A question retrieval.
"""
qna_answer_description = """
Use this tool to trigger the evaluation of user's provided input with the
correct answer of the Q&A question asked. When user provides answer to the
question asked, they can reply in natural language or giving the alphabet
symbol of which selected answer they think it's most reasonable.
The format of the function argument `user_selected_answer` looks as follow:
It should be in the format with character such as A, B, C and D.
Example 1: User's answer is `a`, it means choice `A`.
Example 2: User's answer is contextually closer to 3rd answer choice, it means `C`.
Example 3: User says last is the answer, it means `D`.
Thereafter, the `user_selected_answer` argument will be passed to the
function for Q&A question evaluation.
"""
class Question_Model(BaseModel):
chapter_n: str = \
Field(...,
pattern=r'^Chapter_\d*$',
description=(
"which chapter to extract, the format of this function argumet"
"is with `Chapter_` as prefix concatenated with chapter number"
"in integer. For example, `Chapter_2`, `Chapter_10`."
"if no chapter number specified or user requested for random question"
"or user has no preference over which chapter of textbook to be tested"
"return `Chapter_0`"
)
)
class Answer_Model(BaseModel):
user_selected_answer: str = \
Field(...,
pattern=r'^[ABCD]$',
description=(
"which answer choice `A`, `B`, `C`, `D`"
"user selected. The return format should be"
"in single character such as A, B, C and D."
"if user's answer is contextually closer to a "
"particular answer choice, return the corresponding"
"alphabet A, B, C or D for the answer "
"is closest."
))
def get_qna_question(chapter_n: str) -> str:
"""
Use this tool to extract the chapter number from the body of input text,
thereafter, chapter number will be used as a filtering criteria for
extracting the right questions set from database.
The format of the function argument looks as follow:
It should be in the format with `Chapter_` as prefix.
Example 1: `Chapter_1` for first chapter
Example 2: For chapter 12 of the textbook, you should return `Chapter_12`
Example 3: `Chapter_5` for fifth chapter
Thereafter, the chapter_n argument will be passed to the function for Q&A question retrieval.
Once the question is retrieved from database, be reminded to ask user the question.
"""
con = sqlite3.connect(db_path)
cur = con.cursor()
filter_clause = "WHERE a.id IS NULL" if chapter_n == "Chapter_0" else f"WHERE a.id IS NULL AND chapter='{chapter_n}'"
sql_string = """SELECT q.id, question, option_1, option_2, option_3, option_4, q.correct_answer
FROM qna_tbl q LEFT JOIN answer_tbl a
ON q.id = a.id
""" + filter_clause
res = cur.execute(sql_string)
result = res.fetchone()
id = result[0]
question = result[1]
option_1 = result[2]
option_2 = result[3]
option_3 = result[4]
option_4 = result[5]
c_answer = result[6]
qna_str = "Question: \n" + \
"========= \n" + \
question.replace("\\n", "\n") + "\n" + \
"A) " + option_1 + "\n" + \
"B) " + option_2 + "\n" + \
"C) " + option_3 + "\n" + \
"D) " + option_4
st.session_state.question_id = id
st.session_state.qna_answer = c_answer
con.close()
return qna_str
def evaluate_qna_answer(user_selected_answer: str) -> str:
"""
Use this tool to trigger the evaluation of user's provided input with the
correct answer of the Q&A question asked. When user provides answer to the
question asked, they can reply in natural language or giving the alphabet
symbol of which selected answer they think it's most reasonable.
The format of the function argument `user_selected_answer` looks as follow:
It should be in the format with character such as A, B, C and D.
Example 1: User's answer is `a`, it means choice `A`.
Example 2: User's answer is contextually closer to 3rd answer choice, it means `C`.
Example 3: User says last is the answer, it means `D`.
Thereafter, the `user_selected_answer` argument will be passed to the
function for Q&A question evaluation.
"""
answer_mapping = {
"A": 1,
"B": 2,
"C": 3,
"D": 4
}
num_mapping = dict((v,k) for k,v in answer_mapping.items())
user_answer_numeric = answer_mapping.get(user_selected_answer, None)
if user_answer_numeric is None:
raise Exception(f"User's answer can't be found: {user_selected_answer}")
question_id = st.session_state.question_id
qna_answer = st.session_state.qna_answer
qna_answer_alphabet = num_mapping[qna_answer]
con = sqlite3.connect(db_path)
cur = con.cursor()
sql_string = f"""INSERT INTO answer_tbl
VALUES ({question_id}, {qna_answer}, {user_answer_numeric})
"""
res = cur.execute(sql_string)
con.commit()
con.close()
if qna_answer == user_answer_numeric:
st.toast('Hooray!', icon='π')
time.sleep(0.3)
st.toast('Hooray!', icon='π')
time.sleep(0.3)
st.toast('Hooray!', icon='π')
st.balloons()
else:
st.toast('Omg..', icon='π
')
time.sleep(0.3)
st.toast('Omg..', icon='π
')
time.sleep(0.3)
st.toast('Omg..', icon='π
')
st.snow()
qna_answer_response = (
f"Your selected answer is `{user_selected_answer}`, "
f"but the actual answer is `{qna_answer_alphabet}`. "
)
return qna_answer_response
get_qna_question_tool = FunctionTool.from_defaults(
fn=get_qna_question,
name="Extract_Question",
description=qna_question_description,
fn_schema=Question_Model
)
evaluate_qna_answer_tool = FunctionTool.from_defaults(
fn=evaluate_qna_answer,
name="Evaluate_Answer",
description=qna_answer_description,
fn_schema=Answer_Model
) |