Added suggestions. Updated prompt and response format.
Browse files
app.py
CHANGED
@@ -5,6 +5,7 @@ import math
|
|
5 |
import json
|
6 |
import time
|
7 |
import re
|
|
|
8 |
from botocore.client import Config
|
9 |
|
10 |
kb_id = os.getenv('KNOWLEDGE_BASE_ID')
|
@@ -15,7 +16,7 @@ initial_message = os.getenv('INITIAL_MESSAGE')
|
|
15 |
|
16 |
# "amazon.titan-text-express-v1"
|
17 |
# "amazon.titan-text-premier-v1:0"
|
18 |
-
amazon_model_id = "amazon.titan-text-
|
19 |
|
20 |
bedrock_config = Config(connect_timeout=120, read_timeout=120, retries={'max_attempts': 0})
|
21 |
bedrock_client = boto3.client(
|
@@ -58,11 +59,28 @@ def get_contexts(retrievalResults):
|
|
58 |
return contexts
|
59 |
|
60 |
def clean_text(text):
|
61 |
-
return re.sub(r"(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
|
63 |
def get_answer(query, history, temperature, top_p, max_token_count):
|
64 |
contexts = ""
|
65 |
-
unique_article_ids = []
|
66 |
max_words = math.floor(max_token_count*0.75)
|
67 |
|
68 |
retrievalResults, retrieve_execution_time = retrieve(query)
|
@@ -70,14 +88,14 @@ def get_answer(query, history, temperature, top_p, max_token_count):
|
|
70 |
|
71 |
if highest_score > 0.45:
|
72 |
contexts = get_contexts(retrievalResults)
|
73 |
-
|
74 |
for result in retrievalResults:
|
75 |
article_id = result['metadata'].get('article_id')
|
76 |
if article_id not in unique_article_ids:
|
77 |
unique_article_ids.append(article_id)
|
78 |
if len(unique_article_ids) == 3:
|
79 |
break
|
80 |
-
|
81 |
PROMPT_TEMPLATE = f"""
|
82 |
System: You are an intelligent assistant helping users understand and navigate website functionalities.
|
83 |
Your goal is to provide clear, accurate, and contextually relevant answers based on the information provided.
|
@@ -109,10 +127,11 @@ def get_answer(query, history, temperature, top_p, max_token_count):
|
|
109 |
|
110 |
Additionally, only if there is sufficient remaining token capacity, provide 2 or 3 related questions that the user might want to ask next based on the topic.
|
111 |
If possible, use the following structure for these suggested questions:
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
|
|
116 |
|
117 |
Ensure these suggested questions are brief, relevant, and encourage further exploration on the topic.
|
118 |
Assistant:
|
@@ -128,7 +147,7 @@ def get_answer(query, history, temperature, top_p, max_token_count):
|
|
128 |
})
|
129 |
|
130 |
kwargs = {
|
131 |
-
"modelId":
|
132 |
"contentType": "application/json",
|
133 |
"accept": "*/*",
|
134 |
"body": body
|
@@ -144,19 +163,28 @@ def get_answer(query, history, temperature, top_p, max_token_count):
|
|
144 |
response_body = json.loads(response.get('body').read())
|
145 |
response_text = response_body['results'][0]['outputText']
|
146 |
|
|
|
|
|
147 |
if unique_article_ids:
|
148 |
article_urls_text = "\n\nFor more information, follow the links provided:\n" + "\n".join(
|
149 |
-
f"
|
150 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
151 |
|
152 |
prompt_and_time = f"""
|
153 |
Prompt:
|
154 |
{PROMPT_TEMPLATE}
|
155 |
-
|
156 |
Retrieve execution time: {retrieve_execution_time} seconds
|
157 |
Invoke model execution time: {invoke_model_time} seconds
|
158 |
"""
|
159 |
-
return response_text, prompt_and_time
|
160 |
|
161 |
def format_chat_history(chat_history):
|
162 |
prompt = ""
|
@@ -170,23 +198,32 @@ def respond(message, chat_history, temperature=0.9, top_p=0.6, max_token_count=5
|
|
170 |
formatted_history = format_chat_history(chat_history[-4:])
|
171 |
chat_history.append([message, ""])
|
172 |
|
173 |
-
stream, prompt_and_time = get_answer(message, formatted_history, temperature, top_p, max_token_count)
|
174 |
-
|
175 |
for idx, text_token in enumerate(stream):
|
176 |
if idx == 0 and text_token.startswith(" "):
|
177 |
text_token = text_token[1:]
|
178 |
|
179 |
chat_history[-1][1] += text_token
|
180 |
-
yield "", chat_history, prompt_and_time
|
181 |
|
182 |
def clear_chat_history():
|
183 |
return '', []
|
184 |
|
185 |
def main():
|
186 |
-
with gr.Blocks(
|
187 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
188 |
|
189 |
-
msg = gr.Textbox(label="Question"
|
190 |
|
191 |
with gr.Accordion(label="Advanced options", open=False):
|
192 |
temperature = gr.Slider(label="Temperature", minimum=0.1, maximum=1, value=0.6, step=0.1)
|
@@ -194,12 +231,37 @@ def main():
|
|
194 |
max_token_count = gr.Slider(label="Max token count", minimum=1, maximum=1024, value=400, step=10)
|
195 |
prompt_and_time = gr.Textbox(label="Prompt and Time", interactive=False)
|
196 |
|
197 |
-
btn = gr.Button("Submit"
|
198 |
-
clear = gr.Button("Clear
|
199 |
|
200 |
-
btn.click(
|
201 |
-
|
|
|
|
|
|
|
202 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
203 |
clear.click(clear_chat_history, outputs=[msg, chatbot, prompt_and_time])
|
204 |
|
205 |
demo.queue().launch()
|
|
|
5 |
import json
|
6 |
import time
|
7 |
import re
|
8 |
+
import xml.etree.ElementTree as ET
|
9 |
from botocore.client import Config
|
10 |
|
11 |
kb_id = os.getenv('KNOWLEDGE_BASE_ID')
|
|
|
16 |
|
17 |
# "amazon.titan-text-express-v1"
|
18 |
# "amazon.titan-text-premier-v1:0"
|
19 |
+
amazon_model_id = "amazon.titan-text-premier-v1:0"
|
20 |
|
21 |
bedrock_config = Config(connect_timeout=120, read_timeout=120, retries={'max_attempts': 0})
|
22 |
bedrock_client = boto3.client(
|
|
|
59 |
return contexts
|
60 |
|
61 |
def clean_text(text):
|
62 |
+
return re.sub(r"(For more information, follow the links provided:).*", "", text, flags=re.DOTALL)
|
63 |
+
|
64 |
+
def parse_suggestions(response):
|
65 |
+
start_tag = "<SGs>"
|
66 |
+
end_tag = "</SGs>"
|
67 |
+
|
68 |
+
start_index = response.find(start_tag)
|
69 |
+
end_index = response.find(end_tag) + len(end_tag)
|
70 |
+
|
71 |
+
if start_index == -1 or end_index == -1:
|
72 |
+
return []
|
73 |
+
|
74 |
+
suggestions_xml = response[start_index:end_index]
|
75 |
+
|
76 |
+
root = ET.fromstring(suggestions_xml)
|
77 |
+
suggestions = [suggestion.text for suggestion in root.findall('SG')]
|
78 |
+
|
79 |
+
return suggestions
|
80 |
|
81 |
def get_answer(query, history, temperature, top_p, max_token_count):
|
82 |
contexts = ""
|
83 |
+
unique_article_ids = []
|
84 |
max_words = math.floor(max_token_count*0.75)
|
85 |
|
86 |
retrievalResults, retrieve_execution_time = retrieve(query)
|
|
|
88 |
|
89 |
if highest_score > 0.45:
|
90 |
contexts = get_contexts(retrievalResults)
|
91 |
+
|
92 |
for result in retrievalResults:
|
93 |
article_id = result['metadata'].get('article_id')
|
94 |
if article_id not in unique_article_ids:
|
95 |
unique_article_ids.append(article_id)
|
96 |
if len(unique_article_ids) == 3:
|
97 |
break
|
98 |
+
|
99 |
PROMPT_TEMPLATE = f"""
|
100 |
System: You are an intelligent assistant helping users understand and navigate website functionalities.
|
101 |
Your goal is to provide clear, accurate, and contextually relevant answers based on the information provided.
|
|
|
127 |
|
128 |
Additionally, only if there is sufficient remaining token capacity, provide 2 or 3 related questions that the user might want to ask next based on the topic.
|
129 |
If possible, use the following structure for these suggested questions:
|
130 |
+
<SGs>
|
131 |
+
<SG>First related question</SG>
|
132 |
+
<SG>Second related question</SG>
|
133 |
+
<SG>Third related question</SG>
|
134 |
+
</SGs>
|
135 |
|
136 |
Ensure these suggested questions are brief, relevant, and encourage further exploration on the topic.
|
137 |
Assistant:
|
|
|
147 |
})
|
148 |
|
149 |
kwargs = {
|
150 |
+
"modelId": amazon_model_id,
|
151 |
"contentType": "application/json",
|
152 |
"accept": "*/*",
|
153 |
"body": body
|
|
|
163 |
response_body = json.loads(response.get('body').read())
|
164 |
response_text = response_body['results'][0]['outputText']
|
165 |
|
166 |
+
suggestions = parse_suggestions(response_text)
|
167 |
+
|
168 |
if unique_article_ids:
|
169 |
article_urls_text = "\n\nFor more information, follow the links provided:\n" + "\n".join(
|
170 |
+
f"— https://knowledge.operativeiq.com/articles/{article_id}" for article_id in unique_article_ids)
|
171 |
+
|
172 |
+
response_json = {
|
173 |
+
"response_text": response_text.split('<SGs>')[0].strip(),
|
174 |
+
"suggestions": suggestions,
|
175 |
+
"article_urls": article_urls_text
|
176 |
+
}
|
177 |
+
|
178 |
+
# response_json_str = json.dumps(response_json, indent=4)
|
179 |
+
# print("Response Json:\n", response_json_str)
|
180 |
|
181 |
prompt_and_time = f"""
|
182 |
Prompt:
|
183 |
{PROMPT_TEMPLATE}
|
|
|
184 |
Retrieve execution time: {retrieve_execution_time} seconds
|
185 |
Invoke model execution time: {invoke_model_time} seconds
|
186 |
"""
|
187 |
+
return response_json["response_text"] + response_json["article_urls"], prompt_and_time, response_json["suggestions"]
|
188 |
|
189 |
def format_chat_history(chat_history):
|
190 |
prompt = ""
|
|
|
198 |
formatted_history = format_chat_history(chat_history[-4:])
|
199 |
chat_history.append([message, ""])
|
200 |
|
201 |
+
stream, prompt_and_time, suggestions = get_answer(message, formatted_history, temperature, top_p, max_token_count)
|
202 |
+
|
203 |
for idx, text_token in enumerate(stream):
|
204 |
if idx == 0 and text_token.startswith(" "):
|
205 |
text_token = text_token[1:]
|
206 |
|
207 |
chat_history[-1][1] += text_token
|
208 |
+
yield "", chat_history, prompt_and_time, suggestions[0], suggestions[1], suggestions[2]
|
209 |
|
210 |
def clear_chat_history():
|
211 |
return '', []
|
212 |
|
213 |
def main():
|
214 |
+
with gr.Blocks(css="""
|
215 |
+
.suggestion-button {
|
216 |
+
font-size: 14.5px;
|
217 |
+
}
|
218 |
+
""") as demo:
|
219 |
+
chatbot = gr.Chatbot([[None, initial_message]], height=600)
|
220 |
+
|
221 |
+
with gr.Row():
|
222 |
+
suggestion1 = gr.Button("How to edit RFID crew badge?", elem_classes="suggestion-button")
|
223 |
+
suggestion2 = gr.Button("What types of RFID tags exist?", elem_classes="suggestion-button")
|
224 |
+
suggestion3 = gr.Button("Is it possible to delete a facility?", elem_classes="suggestion-button")
|
225 |
|
226 |
+
msg = gr.Textbox(label="Question")
|
227 |
|
228 |
with gr.Accordion(label="Advanced options", open=False):
|
229 |
temperature = gr.Slider(label="Temperature", minimum=0.1, maximum=1, value=0.6, step=0.1)
|
|
|
231 |
max_token_count = gr.Slider(label="Max token count", minimum=1, maximum=1024, value=400, step=10)
|
232 |
prompt_and_time = gr.Textbox(label="Prompt and Time", interactive=False)
|
233 |
|
234 |
+
btn = gr.Button("Submit")
|
235 |
+
clear = gr.Button("Clear history")
|
236 |
|
237 |
+
btn.click(
|
238 |
+
respond,
|
239 |
+
inputs=[msg, chatbot, temperature, top_p, max_token_count],
|
240 |
+
outputs=[msg, chatbot, prompt_and_time, suggestion1, suggestion2, suggestion3]
|
241 |
+
)
|
242 |
|
243 |
+
suggestion1.click(lambda s: s, inputs=suggestion1, outputs=msg).then(
|
244 |
+
respond,
|
245 |
+
inputs=[msg, chatbot, temperature, top_p, max_token_count],
|
246 |
+
outputs=[msg, chatbot, prompt_and_time, suggestion1, suggestion2, suggestion3]
|
247 |
+
)
|
248 |
+
suggestion2.click(lambda s: s, inputs=suggestion2, outputs=msg).then(
|
249 |
+
respond,
|
250 |
+
inputs=[msg, chatbot, temperature, top_p, max_token_count],
|
251 |
+
outputs=[msg, chatbot, prompt_and_time, suggestion1, suggestion2, suggestion3]
|
252 |
+
)
|
253 |
+
suggestion3.click(lambda s: s, inputs=suggestion3, outputs=msg).then(
|
254 |
+
respond,
|
255 |
+
inputs=[msg, chatbot, temperature, top_p, max_token_count],
|
256 |
+
outputs=[msg, chatbot, prompt_and_time, suggestion1, suggestion2, suggestion3]
|
257 |
+
)
|
258 |
+
|
259 |
+
msg.submit(
|
260 |
+
respond,
|
261 |
+
inputs=[msg, chatbot, temperature, top_p, max_token_count],
|
262 |
+
outputs=[msg, chatbot, prompt_and_time, suggestion1, suggestion2, suggestion3]
|
263 |
+
)
|
264 |
+
|
265 |
clear.click(clear_chat_history, outputs=[msg, chatbot, prompt_and_time])
|
266 |
|
267 |
demo.queue().launch()
|