neke-leo commited on
Commit
8d8fbe9
1 Parent(s): 988bf9f

ENH: Update bot

Browse files
.gitignore CHANGED
@@ -1,3 +1,6 @@
1
  # ignore old_files folder
2
  old_files
3
- audio
 
 
 
 
1
  # ignore old_files folder
2
  old_files
3
+ audio
4
+ conversations
5
+ # ignore pyc files
6
+ *.pyc
app.py CHANGED
@@ -1,16 +1,26 @@
 
 
 
 
 
 
 
 
 
1
  import os
2
 
3
  import openai
4
 
5
  from audio_utils import text_to_speech, text_to_speech_polly
 
6
  from openai_utils import get_embedding, whisper_transcription
7
  from vector_db import LanceVectorDb, QnA
8
 
9
  db = LanceVectorDb("qna_db")
10
-
11
  OPENAI_KEY = os.environ["OPENAI_KEY"]
12
  openai.api_key = OPENAI_KEY
13
 
 
14
  if len(db.table.to_pandas()) == 0:
15
  print("Empty db, trying to load qna's from json file")
16
  try:
@@ -19,6 +29,7 @@ if len(db.table.to_pandas()) == 0:
19
  except Exception as exception:
20
  raise Exception("Failed to initialize db from json file") from exception
21
 
 
22
  import os
23
 
24
 
@@ -29,53 +40,103 @@ def ensure_dir(directory):
29
 
30
  ensure_dir("audio")
31
 
 
 
32
  from langdetect import detect
33
 
34
- GENERAL_SYSTEM_PROMPT = (
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  "You are a question answering assistant.\n"
36
- "You answer questions from users based on information in our database provided as context.\n"
37
- "You respond in one, maximum two sentences.\n"
38
- "You use only the information in the context. If the information is not in the context, you tell the user that you don't know.\n"
39
  "You answer in the language that the question was asked in.\n"
40
  "You speak german and english.\n"
41
  )
42
 
 
43
 
44
- def bot_respond(user_query, chat_messages: list):
45
- embedding = get_embedding(user_query)
46
 
47
- qnas = db.get_qna(embedding, lang="en", limit=3)
48
- print("Total_qnas:", len(qnas), [qna.score for qna in qnas])
49
- qnas = [qna for qna in qnas if qna.score < 0.45]
50
- print("Filtered_qnas:", len(qnas))
51
- context_prompt = f"The user said: {user_query}\n\n"
52
-
53
- if len(qnas) > 0:
54
- example_questions = ""
55
- for qna in qnas:
56
- example_questions += (
57
- f"For question: '{qna.question}'\n" f"The answer is: '{qna.answer}'\n"
58
- )
59
-
60
- context_prompt += (
61
- f"Context information from our database:\n{example_questions}"
62
- "If the user hasn't provided some of the necessary information for answering the question, you can ask the user for it.\n"
63
- )
 
 
 
64
 
65
- print(context_prompt)
66
- chat_messages.append({"role": "user", "content": context_prompt})
 
 
 
 
 
 
 
 
 
 
 
67
 
68
  completion = openai.ChatCompletion.create(
69
- model="gpt-3.5-turbo",
70
- messages=chat_messages,
71
  )
72
- text = completion.choices[0].message.content
73
 
74
- chat_messages.pop()
75
- chat_messages.append({"role": "user", "content": user_query})
76
- chat_messages.append({"role": "assistant", "content": text})
 
 
 
 
 
 
 
 
 
 
 
 
 
77
 
78
- return text, context_prompt
 
 
79
 
80
 
81
  import random
@@ -90,14 +151,17 @@ def display_history(conversation):
90
  return conversation_string
91
 
92
 
93
- def handle_audiofile(audio_filepath: str, chat_messages: list):
94
  user_question = whisper_transcription(audio_filepath)
95
  print("Transcription", user_question)
96
 
97
- bot_response_text, context_prompt = bot_respond(user_question, chat_messages)
98
 
99
- lang = detect(bot_response_text)
100
- print("Detected language:", lang, "for text:", bot_response_text)
 
 
 
101
 
102
  if lang not in ["en", "de"]:
103
  lang = "en"
@@ -111,9 +175,9 @@ def handle_audiofile(audio_filepath: str, chat_messages: list):
111
  return (
112
  user_question,
113
  bot_response_text,
114
- chat_messages,
115
  context_prompt,
116
- display_history(chat_messages),
117
  output_filepath,
118
  )
119
 
@@ -122,7 +186,11 @@ import gradio as gr
122
 
123
  with gr.Blocks() as demo:
124
  # initialize the state that will be used to store the chat messages
125
- chat_messages = gr.State([{"role": "system", "content": GENERAL_SYSTEM_PROMPT}])
 
 
 
 
126
 
127
  with gr.Row():
128
  audio_input = gr.Audio(source="microphone", type="filepath", format="mp3")
@@ -133,7 +201,9 @@ with gr.Blocks() as demo:
133
  assistant_answer = gr.Textbox(label="PhoneBot Answer")
134
 
135
  with gr.Row():
136
- context_info = gr.Textbox(label="Provided context")
 
 
137
  conversation_history = gr.Textbox(label="Conversation history")
138
 
139
  # when the audio input is stopped, run the transcribe function
 
1
+ import json
2
+ import os
3
+
4
+ with open("env.json") as f:
5
+ env_vars = json.load(f)
6
+
7
+ for k, v in env_vars.items():
8
+ os.environ[k] = v
9
+
10
  import os
11
 
12
  import openai
13
 
14
  from audio_utils import text_to_speech, text_to_speech_polly
15
+ from openai_prompts import contextualize_question
16
  from openai_utils import get_embedding, whisper_transcription
17
  from vector_db import LanceVectorDb, QnA
18
 
19
  db = LanceVectorDb("qna_db")
 
20
  OPENAI_KEY = os.environ["OPENAI_KEY"]
21
  openai.api_key = OPENAI_KEY
22
 
23
+
24
  if len(db.table.to_pandas()) == 0:
25
  print("Empty db, trying to load qna's from json file")
26
  try:
 
29
  except Exception as exception:
30
  raise Exception("Failed to initialize db from json file") from exception
31
 
32
+
33
  import os
34
 
35
 
 
40
 
41
  ensure_dir("audio")
42
 
43
+ import random
44
+
45
  from langdetect import detect
46
 
47
+
48
+ def red(text):
49
+ return f'\x1b[31m"{text}"\x1b[0m'
50
+
51
+
52
+ def query_database(prompt: str):
53
+ print("Querying database for question:", prompt)
54
+ embedding = get_embedding(prompt)
55
+ qnas = db.get_qna(embedding, lang="en", limit=3)
56
+ print("Total_qnas:", len(qnas), [qna.score for qna in qnas])
57
+ qnas = [qna for qna in qnas if qna.score < 0.49]
58
+ print("Filtered_qnas:", len(qnas))
59
+ return qnas
60
+
61
+
62
+ available_functions = {
63
+ "query_database": query_database,
64
+ }
65
+
66
+ conversation_folder = f"conversations/{random.randint(0, 10000)}"
67
+ ensure_dir(conversation_folder)
68
+
69
+ SYSTEM_PROMPT = (
70
  "You are a question answering assistant.\n"
71
+ "You answer questions from users delimited by tripple dashes --- based on information in our database provided as context.\n"
72
+ "The context informtion in delimited by tripple backticks ```\n"
73
+ "You try to be concise and offer the most relevant information.\n"
74
  "You answer in the language that the question was asked in.\n"
75
  "You speak german and english.\n"
76
  )
77
 
78
+ step = 0
79
 
 
 
80
 
81
+ def context_format(qnas):
82
+ context = "Context:\n\n```"
83
+ for qna in qnas:
84
+ context += f"For question: {qna.question}\nThe answer is: {qna.answer}\n"
85
+ context += "```"
86
+ return context
87
+
88
+
89
+ def bot_respond(user_query, history: list):
90
+ global step
91
+
92
+ chat_messages = history["chat_messages"]
93
+
94
+ user_query = contextualize_question(user_query, chat_messages)
95
+
96
+ path = os.path.join(conversation_folder, f"step_{step}_qna.json")
97
+
98
+ qnas = query_database(user_query)
99
+
100
+ prompt = f"The user said: ---{user_query}---\n\n"
101
 
102
+ context = context_format(qnas)
103
+ prompt += context
104
+
105
+ qna_messages = [
106
+ {
107
+ "role": "assistant",
108
+ "content": SYSTEM_PROMPT,
109
+ },
110
+ {
111
+ "role": "user",
112
+ "content": prompt,
113
+ },
114
+ ]
115
 
116
  completion = openai.ChatCompletion.create(
117
+ model="gpt-3.5-turbo", messages=qna_messages, temperature=0
 
118
  )
 
119
 
120
+ response_message = completion["choices"][0]["message"]
121
+ bot_response = response_message.content
122
+
123
+ path = os.path.join(conversation_folder, f"step_{step}_qna.json")
124
+
125
+ with open(path, "w") as f:
126
+ json.dump(
127
+ {
128
+ "chat_messages": chat_messages,
129
+ "response": response_message.content,
130
+ },
131
+ f,
132
+ indent=4,
133
+ )
134
+
135
+ chat_messages.append({"role": "assistant", "content": bot_response})
136
 
137
+ step += 1
138
+
139
+ return bot_response, prompt
140
 
141
 
142
  import random
 
151
  return conversation_string
152
 
153
 
154
+ def handle_audiofile(audio_filepath: str, history: list):
155
  user_question = whisper_transcription(audio_filepath)
156
  print("Transcription", user_question)
157
 
158
+ bot_response_text, context_prompt = bot_respond(user_question, history)
159
 
160
+ if bot_response_text:
161
+ lang = detect(bot_response_text)
162
+ print("Detected language:", lang, "for text:", bot_response_text)
163
+ else:
164
+ lang = "en"
165
 
166
  if lang not in ["en", "de"]:
167
  lang = "en"
 
175
  return (
176
  user_question,
177
  bot_response_text,
178
+ history,
179
  context_prompt,
180
+ display_history(history["chat_messages"]),
181
  output_filepath,
182
  )
183
 
 
186
 
187
  with gr.Blocks() as demo:
188
  # initialize the state that will be used to store the chat messages
189
+ chat_messages = gr.State(
190
+ {
191
+ "chat_messages": [{"role": "system", "content": SYSTEM_PROMPT}],
192
+ }
193
+ )
194
 
195
  with gr.Row():
196
  audio_input = gr.Audio(source="microphone", type="filepath", format="mp3")
 
201
  assistant_answer = gr.Textbox(label="PhoneBot Answer")
202
 
203
  with gr.Row():
204
+ context_info = gr.Textbox(
205
+ label="Context provided to the bot + additional infos for debugging"
206
+ )
207
  conversation_history = gr.Textbox(label="Conversation history")
208
 
209
  # when the audio input is stopped, run the transcribe function
bot_gradio.ipynb CHANGED
@@ -2,7 +2,22 @@
2
  "cells": [
3
  {
4
  "cell_type": "code",
5
- "execution_count": null,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  "metadata": {},
7
  "outputs": [],
8
  "source": [
@@ -10,16 +25,17 @@
10
  "from vector_db import LanceVectorDb, QnA\n",
11
  "from openai_utils import get_embedding, whisper_transcription\n",
12
  "from audio_utils import text_to_speech, text_to_speech_polly\n",
 
13
  "import os\n",
14
  "\n",
15
  "db = LanceVectorDb(\"qna_db\")\n",
16
- "OPENAI_KEY = os.environ.get[\"OPENAI_KEY\"]\n",
17
  "openai.api_key = OPENAI_KEY"
18
  ]
19
  },
20
  {
21
  "cell_type": "code",
22
- "execution_count": null,
23
  "metadata": {},
24
  "outputs": [],
25
  "source": [
@@ -34,96 +50,153 @@
34
  },
35
  {
36
  "cell_type": "code",
37
- "execution_count": null,
38
  "metadata": {},
39
  "outputs": [],
40
  "source": [
41
  "import os\n",
42
  "\n",
 
43
  "def ensure_dir(directory):\n",
44
  " if not os.path.exists(directory):\n",
45
  " os.makedirs(directory)\n",
46
  "\n",
 
47
  "ensure_dir(\"audio\")"
48
  ]
49
  },
50
  {
51
  "cell_type": "code",
52
- "execution_count": null,
53
  "metadata": {},
54
  "outputs": [],
55
  "source": [
56
  "from langdetect import detect\n",
 
 
 
 
 
57
  "\n",
58
- "GENERAL_SYSTEM_PROMPT = (\n",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  " \"You are a question answering assistant.\\n\"\n",
60
- " \"You answer questions from users based on information in our database provided as context.\\n\"\n",
61
- " \"You respond in one, maximum two sentences.\\n\"\n",
62
- " \"You use only the information in the context. If the information is not in the context, you tell the user that you don't know.\\n\"\n",
63
  " \"You answer in the language that the question was asked in.\\n\"\n",
64
  " \"You speak german and english.\\n\"\n",
65
  ")\n",
66
  "\n",
67
- "def bot_respond(user_query, chat_messages: list):\n",
68
- " embedding = get_embedding(user_query)\n",
69
  "\n",
70
- " qnas = db.get_qna(embedding, lang=\"en\", limit=3)\n",
71
- " print(\"Total_qnas:\", len(qnas), [qna.score for qna in qnas])\n",
72
- " qnas = [qna for qna in qnas if qna.score < 0.45]\n",
73
- " print(\"Filtered_qnas:\", len(qnas))\n",
74
- " context_prompt = f\"The user said: {user_query}\\n\\n\"\n",
75
- "\n",
76
- " if len(qnas) > 0:\n",
77
- " example_questions = \"\"\n",
78
- " for qna in qnas:\n",
79
- " example_questions += (\n",
80
- " f\"For question: '{qna.question}'\\n\"\n",
81
- " f\"The answer is: '{qna.answer}'\\n\"\n",
82
- " )\n",
83
- "\n",
84
- " context_prompt += (\n",
85
- " f\"Context information from our database:\\n{example_questions}\"\n",
86
- " \"If the user hasn't provided some of the necessary information for answering the question, you can ask the user for it.\\n\"\n",
87
- " )\n",
 
88
  "\n",
89
- " print(context_prompt)\n",
90
- " chat_messages.append({\"role\": \"user\", \"content\": context_prompt})\n",
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  "\n",
92
  " completion = openai.ChatCompletion.create(\n",
93
- " model=\"gpt-3.5-turbo\",\n",
94
- " messages=chat_messages,\n",
95
  " )\n",
96
- " text = completion.choices[0].message.content\n",
97
  "\n",
98
- " chat_messages.pop()\n",
99
- " chat_messages.append({\"role\": \"user\", \"content\": user_query})\n",
100
- " chat_messages.append({\"role\": \"system\", \"content\": text})\n",
 
 
 
 
 
 
 
 
 
 
 
101
  "\n",
102
- " return text, context_prompt\n"
 
 
 
 
103
  ]
104
  },
105
  {
106
  "cell_type": "code",
107
- "execution_count": null,
108
  "metadata": {},
109
  "outputs": [],
110
  "source": [
111
  "import random\n",
112
  "\n",
 
113
  "def display_history(conversation):\n",
114
  " conversation_string = \"\"\n",
115
  " for message in conversation:\n",
116
- " conversation_string += f\"<<{message['role']}>>:\\n{message['content']}\\n<<{message['role']}>>\\n\\n\"\n",
 
 
117
  " return conversation_string\n",
118
  "\n",
119
- "def handle_audiofile(audio_filepath: str, chat_messages: list):\n",
 
120
  " user_question = whisper_transcription(audio_filepath)\n",
121
  " print(\"Transcription\", user_question)\n",
122
  "\n",
123
- " bot_response_text, context_prompt = bot_respond(user_question, chat_messages)\n",
124
  "\n",
125
- " lang = detect(bot_response_text)\n",
126
- " print(\"Detected language:\", lang, \"for text:\", bot_response_text)\n",
 
 
 
127
  "\n",
128
  " if lang not in [\"en\", \"de\"]:\n",
129
  " lang = \"en\"\n",
@@ -134,41 +207,94 @@
134
  " context_prompt += f\"<<tts language>> : {lang}\\n\"\n",
135
  " context_prompt += f\"<<tts text>> : {bot_response_text}\\n\"\n",
136
  "\n",
137
- " return user_question, bot_response_text, chat_messages, context_prompt, display_history(chat_messages), output_filepath"
 
 
 
 
 
 
 
138
  ]
139
  },
140
  {
141
  "cell_type": "code",
142
- "execution_count": null,
143
  "metadata": {},
144
- "outputs": [],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  "source": [
146
  "import gradio as gr\n",
147
  "\n",
148
  "\n",
149
  "with gr.Blocks() as demo:\n",
150
  " # initialize the state that will be used to store the chat messages\n",
151
- " chat_messages = gr.State([{\"role\": \"system\", \"content\": GENERAL_SYSTEM_PROMPT}])\n",
 
 
 
 
152
  "\n",
153
  " with gr.Row():\n",
154
  " audio_input = gr.Audio(source=\"microphone\", type=\"filepath\", format=\"mp3\")\n",
155
  " # autoplay=True => run the output audio file automatically\n",
156
- " output_audio = gr.Audio(\n",
157
- " label=\"PhoneBot Answer TTS\", autoplay=True\n",
158
- " )\n",
159
  " with gr.Row():\n",
160
  " user_query_textbox = gr.Textbox(label=\"User Query\")\n",
161
  " assistant_answer = gr.Textbox(label=\"PhoneBot Answer\")\n",
162
  "\n",
163
  " with gr.Row():\n",
164
- " context_info = gr.Textbox(label=\"Context provided to the bot + additional infos for debugging\")\n",
 
 
165
  " conversation_history = gr.Textbox(label=\"Conversation history\")\n",
166
  "\n",
167
  " # when the audio input is stopped, run the transcribe function\n",
168
  " audio_input.stop_recording(\n",
169
  " handle_audiofile,\n",
170
  " inputs=[audio_input, chat_messages],\n",
171
- " outputs=[user_query_textbox, assistant_answer, chat_messages, context_info, conversation_history, output_audio],\n",
 
 
 
 
 
 
 
172
  " )\n",
173
  "\n",
174
  "demo.launch(share=True, inbrowser=True, inline=False)"
@@ -176,34 +302,16 @@
176
  },
177
  {
178
  "cell_type": "code",
179
- "execution_count": 1,
180
  "metadata": {},
181
  "outputs": [],
182
  "source": [
183
  "import json\n",
 
184
  "with open(\"all_questions.json\", encoding=\"utf-8\") as f:\n",
185
  " all_questions = json.load(f)[\"qna\"]"
186
  ]
187
  },
188
- {
189
- "cell_type": "code",
190
- "execution_count": 2,
191
- "metadata": {},
192
- "outputs": [],
193
- "source": [
194
- "all_questions = [{\"question\": qna[\"question\"], \"answer\": qna[\"answer\"]} for qna in all_questions]"
195
- ]
196
- },
197
- {
198
- "cell_type": "code",
199
- "execution_count": 5,
200
- "metadata": {},
201
- "outputs": [],
202
- "source": [
203
- "with open(\"test.json\", \"w\", encoding=\"utf-8\") as f:\n",
204
- " json.dump(all_questions, f, indent=4, ensure_ascii=False)"
205
- ]
206
- },
207
  {
208
  "cell_type": "code",
209
  "execution_count": null,
@@ -215,22 +323,23 @@
215
  },
216
  {
217
  "cell_type": "code",
218
- "execution_count": null,
219
  "metadata": {},
220
  "outputs": [],
221
  "source": [
222
- "functions = [{\n",
223
- " \"name\": \"get_answer\",\n",
224
- " \"description\": \"Get answer from the bot\",\n",
225
- " \"parameters\": [\n",
226
- " \n",
227
- "\n",
228
- "}]\n",
229
- "\n",
230
- "openai.ChatCompletion.create(\n",
231
- " model=\"gpt-3.5-turbo\",\n",
232
- " functions=[\"get_answer\"],\n",
233
- ")"
 
234
  ]
235
  }
236
  ],
 
2
  "cells": [
3
  {
4
  "cell_type": "code",
5
+ "execution_count": 11,
6
+ "metadata": {},
7
+ "outputs": [],
8
+ "source": [
9
+ "import json, os\n",
10
+ "\n",
11
+ "with open(\"env.json\") as f:\n",
12
+ " env_vars = json.load(f)\n",
13
+ "\n",
14
+ "for k, v in env_vars.items():\n",
15
+ " os.environ[k] = v\n"
16
+ ]
17
+ },
18
+ {
19
+ "cell_type": "code",
20
+ "execution_count": 12,
21
  "metadata": {},
22
  "outputs": [],
23
  "source": [
 
25
  "from vector_db import LanceVectorDb, QnA\n",
26
  "from openai_utils import get_embedding, whisper_transcription\n",
27
  "from audio_utils import text_to_speech, text_to_speech_polly\n",
28
+ "from openai_prompts import contextualize_question\n",
29
  "import os\n",
30
  "\n",
31
  "db = LanceVectorDb(\"qna_db\")\n",
32
+ "OPENAI_KEY = os.environ[\"OPENAI_KEY\"]\n",
33
  "openai.api_key = OPENAI_KEY"
34
  ]
35
  },
36
  {
37
  "cell_type": "code",
38
+ "execution_count": 13,
39
  "metadata": {},
40
  "outputs": [],
41
  "source": [
 
50
  },
51
  {
52
  "cell_type": "code",
53
+ "execution_count": 14,
54
  "metadata": {},
55
  "outputs": [],
56
  "source": [
57
  "import os\n",
58
  "\n",
59
+ "\n",
60
  "def ensure_dir(directory):\n",
61
  " if not os.path.exists(directory):\n",
62
  " os.makedirs(directory)\n",
63
  "\n",
64
+ "\n",
65
  "ensure_dir(\"audio\")"
66
  ]
67
  },
68
  {
69
  "cell_type": "code",
70
+ "execution_count": 25,
71
  "metadata": {},
72
  "outputs": [],
73
  "source": [
74
  "from langdetect import detect\n",
75
+ "import random\n",
76
+ "\n",
77
+ "def red(text):\n",
78
+ " return f'\\x1b[31m\"{text}\"\\x1b[0m'\n",
79
+ "\n",
80
  "\n",
81
+ "def query_database(prompt: str):\n",
82
+ " print(\"Querying database for question:\", prompt)\n",
83
+ " embedding = get_embedding(prompt)\n",
84
+ " qnas = db.get_qna(embedding, lang=\"en\", limit=3)\n",
85
+ " print(\"Total_qnas:\", len(qnas), [qna.score for qna in qnas])\n",
86
+ " qnas = [qna for qna in qnas if qna.score < 0.49]\n",
87
+ " print(\"Filtered_qnas:\", len(qnas))\n",
88
+ " return qnas\n",
89
+ "\n",
90
+ "\n",
91
+ "available_functions = {\n",
92
+ " \"query_database\": query_database,\n",
93
+ "}\n",
94
+ "\n",
95
+ "conversation_folder = f\"conversations/{random.randint(0, 10000)}\"\n",
96
+ "ensure_dir(conversation_folder)\n",
97
+ "\n",
98
+ "SYSTEM_PROMPT = (\n",
99
  " \"You are a question answering assistant.\\n\"\n",
100
+ " \"You answer questions from users delimited by tripple dashes --- based on information in our database provided as context.\\n\"\n",
101
+ " \"The context informtion in delimited by tripple backticks ```\\n\"\n",
102
+ " \"You try to be concise and offer the most relevant information.\\n\"\n",
103
  " \"You answer in the language that the question was asked in.\\n\"\n",
104
  " \"You speak german and english.\\n\"\n",
105
  ")\n",
106
  "\n",
107
+ "step = 0\n",
 
108
  "\n",
109
+ "def context_format(qnas):\n",
110
+ " context = \"Context:\\n\\n```\"\n",
111
+ " for qna in qnas:\n",
112
+ " context += f\"For question: {qna.question}\\nThe answer is: {qna.answer}\\n\"\n",
113
+ " context += \"```\"\n",
114
+ " return context\n",
115
+ "\n",
116
+ "\n",
117
+ "def bot_respond(user_query, history: list):\n",
118
+ " global step\n",
119
+ "\n",
120
+ " chat_messages = history[\"chat_messages\"]\n",
121
+ "\n",
122
+ " user_query = contextualize_question(user_query, chat_messages)\n",
123
+ "\n",
124
+ " path = os.path.join(conversation_folder, f\"step_{step}_qna.json\")\n",
125
+ "\n",
126
+ "\n",
127
+ " qnas = query_database(user_query)\n",
128
  "\n",
129
+ " prompt = f\"The user said: ---{user_query}---\\n\\n\"\n",
130
+ "\n",
131
+ " context = context_format(qnas)\n",
132
+ " prompt += context\n",
133
+ "\n",
134
+ " qna_messages = [\n",
135
+ " {\n",
136
+ " \"role\": \"assistant\",\n",
137
+ " \"content\": SYSTEM_PROMPT,\n",
138
+ " },\n",
139
+ " {\n",
140
+ " \"role\": \"user\",\n",
141
+ " \"content\": prompt,\n",
142
+ " },\n",
143
+ " ]\n",
144
  "\n",
145
  " completion = openai.ChatCompletion.create(\n",
146
+ " model=\"gpt-3.5-turbo\", messages=qna_messages, temperature=0\n",
 
147
  " )\n",
 
148
  "\n",
149
+ " response_message = completion[\"choices\"][0][\"message\"]\n",
150
+ " bot_response = response_message.content\n",
151
+ "\n",
152
+ " path = os.path.join(conversation_folder, f\"step_{step}_qna.json\")\n",
153
+ "\n",
154
+ " with open(path, \"w\") as f:\n",
155
+ " json.dump(\n",
156
+ " {\n",
157
+ " \"chat_messages\": chat_messages,\n",
158
+ " \"response\": response_message.content,\n",
159
+ " },\n",
160
+ " f,\n",
161
+ " indent=4,\n",
162
+ " )\n",
163
  "\n",
164
+ " chat_messages.append({\"role\": \"assistant\", \"content\": bot_response})\n",
165
+ "\n",
166
+ " step += 1\n",
167
+ "\n",
168
+ " return bot_response, prompt"
169
  ]
170
  },
171
  {
172
  "cell_type": "code",
173
+ "execution_count": 26,
174
  "metadata": {},
175
  "outputs": [],
176
  "source": [
177
  "import random\n",
178
  "\n",
179
+ "\n",
180
  "def display_history(conversation):\n",
181
  " conversation_string = \"\"\n",
182
  " for message in conversation:\n",
183
+ " conversation_string += (\n",
184
+ " f\"<<{message['role']}>>:\\n{message['content']}\\n<<{message['role']}>>\\n\\n\"\n",
185
+ " )\n",
186
  " return conversation_string\n",
187
  "\n",
188
+ "\n",
189
+ "def handle_audiofile(audio_filepath: str, history: list):\n",
190
  " user_question = whisper_transcription(audio_filepath)\n",
191
  " print(\"Transcription\", user_question)\n",
192
  "\n",
193
+ " bot_response_text, context_prompt = bot_respond(user_question, history)\n",
194
  "\n",
195
+ " if bot_response_text:\n",
196
+ " lang = detect(bot_response_text)\n",
197
+ " print(\"Detected language:\", lang, \"for text:\", bot_response_text)\n",
198
+ " else:\n",
199
+ " lang = \"en\"\n",
200
  "\n",
201
  " if lang not in [\"en\", \"de\"]:\n",
202
  " lang = \"en\"\n",
 
207
  " context_prompt += f\"<<tts language>> : {lang}\\n\"\n",
208
  " context_prompt += f\"<<tts text>> : {bot_response_text}\\n\"\n",
209
  "\n",
210
+ " return (\n",
211
+ " user_question,\n",
212
+ " bot_response_text,\n",
213
+ " history,\n",
214
+ " context_prompt,\n",
215
+ " display_history(history[\"chat_messages\"]),\n",
216
+ " output_filepath,\n",
217
+ " )"
218
  ]
219
  },
220
  {
221
  "cell_type": "code",
222
+ "execution_count": 27,
223
  "metadata": {},
224
+ "outputs": [
225
+ {
226
+ "name": "stdout",
227
+ "output_type": "stream",
228
+ "text": [
229
+ "Running on local URL: http://127.0.0.1:7880\n",
230
+ "Running on public URL: https://80ddf0a828a1240987.gradio.live\n",
231
+ "\n",
232
+ "This share link expires in 72 hours. For free permanent hosting and GPU upgrades, run `gradio deploy` from Terminal to deploy to Spaces (https://huggingface.co/spaces)\n"
233
+ ]
234
+ },
235
+ {
236
+ "data": {
237
+ "text/plain": []
238
+ },
239
+ "execution_count": 27,
240
+ "metadata": {},
241
+ "output_type": "execute_result"
242
+ },
243
+ {
244
+ "name": "stdout",
245
+ "output_type": "stream",
246
+ "text": [
247
+ "Transcription What locations are available for measurement?\n",
248
+ "Querying database for question: What locations are available for measurement?\n",
249
+ "Total_qnas: 3 [0.43219417333602905, 0.43802204728126526, 0.4490761160850525]\n",
250
+ "Filtered_qnas: 3\n",
251
+ "Detected language: en for text: The available locations for measurement are Salzburg and Hallein. In Salzburg, there is an underground car park and individual parking spaces available. The Salzburg location is also easily accessible by O-Bus. In Hallein, there are plenty of parking spaces directly in front of the building.\n",
252
+ "Transcription How much time does the measurement take?\n",
253
+ "Querying database for question: How much time does the measurement at each location take?\n",
254
+ "Total_qnas: 3 [0.3830512762069702, 0.383282870054245, 0.38819530606269836]\n",
255
+ "Filtered_qnas: 3\n",
256
+ "Detected language: en for text: The measurement at each location takes about 5-15 minutes, depending on the question and number of examination areas.\n"
257
+ ]
258
+ }
259
+ ],
260
  "source": [
261
  "import gradio as gr\n",
262
  "\n",
263
  "\n",
264
  "with gr.Blocks() as demo:\n",
265
  " # initialize the state that will be used to store the chat messages\n",
266
+ " chat_messages = gr.State(\n",
267
+ " {\n",
268
+ " \"chat_messages\": [{\"role\": \"system\", \"content\": SYSTEM_PROMPT}],\n",
269
+ " }\n",
270
+ " )\n",
271
  "\n",
272
  " with gr.Row():\n",
273
  " audio_input = gr.Audio(source=\"microphone\", type=\"filepath\", format=\"mp3\")\n",
274
  " # autoplay=True => run the output audio file automatically\n",
275
+ " output_audio = gr.Audio(label=\"PhoneBot Answer TTS\", autoplay=True)\n",
 
 
276
  " with gr.Row():\n",
277
  " user_query_textbox = gr.Textbox(label=\"User Query\")\n",
278
  " assistant_answer = gr.Textbox(label=\"PhoneBot Answer\")\n",
279
  "\n",
280
  " with gr.Row():\n",
281
+ " context_info = gr.Textbox(\n",
282
+ " label=\"Context provided to the bot + additional infos for debugging\"\n",
283
+ " )\n",
284
  " conversation_history = gr.Textbox(label=\"Conversation history\")\n",
285
  "\n",
286
  " # when the audio input is stopped, run the transcribe function\n",
287
  " audio_input.stop_recording(\n",
288
  " handle_audiofile,\n",
289
  " inputs=[audio_input, chat_messages],\n",
290
+ " outputs=[\n",
291
+ " user_query_textbox,\n",
292
+ " assistant_answer,\n",
293
+ " chat_messages,\n",
294
+ " context_info,\n",
295
+ " conversation_history,\n",
296
+ " output_audio,\n",
297
+ " ],\n",
298
  " )\n",
299
  "\n",
300
  "demo.launch(share=True, inbrowser=True, inline=False)"
 
302
  },
303
  {
304
  "cell_type": "code",
305
+ "execution_count": 109,
306
  "metadata": {},
307
  "outputs": [],
308
  "source": [
309
  "import json\n",
310
+ "\n",
311
  "with open(\"all_questions.json\", encoding=\"utf-8\") as f:\n",
312
  " all_questions = json.load(f)[\"qna\"]"
313
  ]
314
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
315
  {
316
  "cell_type": "code",
317
  "execution_count": null,
 
323
  },
324
  {
325
  "cell_type": "code",
326
+ "execution_count": 7,
327
  "metadata": {},
328
  "outputs": [],
329
  "source": [
330
+ "from genson import SchemaBuilder\n",
331
+ "import json\n",
332
+ "\n",
333
+ "builder = SchemaBuilder()\n",
334
+ "obj = {\n",
335
+ " \"response_type\": \"Which city do you want to book an appointment in?\",\n",
336
+ " \"content\": \"The user wants to book an appointment\",\n",
337
+ "}\n",
338
+ "builder.add_object(obj)\n",
339
+ "\n",
340
+ "schema = builder.to_schema()\n",
341
+ "schema.pop(\"$schema\")\n",
342
+ "schema_str = json.dumps(schema, indent=4)"
343
  ]
344
  }
345
  ],
openai_prompts/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .contextualize import contextualize_question
openai_prompts/contextualize.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+
3
+ import openai
4
+
5
+ functions = [
6
+ {
7
+ "name": "with_context",
8
+ "description": "Updates the question with context from the conversation to make it more clear, adds details, replaces general words like 'there', 'that', pronouns with the values mentioned in conversation.",
9
+ "parameters": {
10
+ "type": "object",
11
+ "properties": {
12
+ "contextualized_question": {
13
+ "type": "string",
14
+ "description": "The contextualized question",
15
+ }
16
+ },
17
+ "required": ["contextualized_question"],
18
+ },
19
+ }
20
+ ]
21
+
22
+
23
+ def contextualize_question(user_query: str, messages: list[str]):
24
+ prompt = (
25
+ f"The user said: {user_query}\n\n"
26
+ "If the user is asking a question, make sure you contextualize it using the replies exchanged before, add details to the question.\n"
27
+ "The previous messages are:\n"
28
+ )
29
+
30
+ messages_for_context = messages[1:]
31
+ for message in messages_for_context:
32
+ prompt += f"<<{message['role']}>>{message['content']}<<{message['role']}>>\n"
33
+
34
+ res = openai.ChatCompletion.create(
35
+ model="gpt-3.5-turbo",
36
+ messages=[
37
+ {
38
+ "role": "system",
39
+ "content": "You are a helpful assistant adds context to vague questions.",
40
+ },
41
+ {"role": "user", "content": prompt},
42
+ ],
43
+ functions=functions,
44
+ function_call={"name": "with_context"}, # force the function to be called
45
+ temperature=0.2,
46
+ )
47
+
48
+ try:
49
+ arguments = res["choices"][0]["message"]["function_call"]["arguments"]
50
+
51
+ result_data = json.loads(arguments)
52
+
53
+ return result_data["contextualized_question"]
54
+ except Exception as error:
55
+ print(error)
56
+ return last_reply