Artem0729 commited on
Commit
b69c947
·
verified ·
1 Parent(s): 16ae71c

Upload 15 files

Browse files

Change UI and upadte a feature of chatbot

Files changed (11) hide show
  1. .env +4 -0
  2. .gitattributes +1 -0
  3. .gitignore +0 -1
  4. app.py +42 -26
  5. bot.jpg +0 -0
  6. bot.png +0 -0
  7. chatbot.png +3 -0
  8. embed.py +2 -0
  9. message.png +0 -0
  10. requirements.txt +0 -1
  11. templete.py +295 -0
.env ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ OPENAI_API_KEY = sk-proj-euivvx6yKpJTOIaTwh38T3BlbkFJCpaKmUwwhXuf17uPOjW2
2
+
3
+ PINECONE_API_KEY = f08e0670-b935-4099-b99e-11929e771159
4
+ PINECONE_INDEX = mediate
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ chatbot.png filter=lfs diff=lfs merge=lfs -text
.gitignore CHANGED
@@ -1,2 +1 @@
1
- .env
2
  test.csv
 
 
1
  test.csv
app.py CHANGED
@@ -61,7 +61,7 @@ class MediatorRetriever(BaseRetriever):
61
  response = openai_client.chat.completions.create(
62
  model="gpt-4-1106-preview",
63
  messages=[
64
- {"role": "system", "content": "You are a professional mediation field searcher. Your role is to extract information about mediators from user's message. but you have to provivder serveral mediators not one. If there are no mediators in the specific city, then it should return mediators from the state."},
65
  {"role": "user", "content": message}
66
  ],
67
  functions=tools,
@@ -78,9 +78,7 @@ class MediatorRetriever(BaseRetriever):
78
  if new_message:
79
  yield {"search_status" : True, "data" : new_message}
80
 
81
- def _get_relevant_documents(
82
- self, query: str, *, run_manager: CallbackManagerForRetrieverRun
83
- ) -> List[Document]:
84
  """Sync implementations for retriever."""
85
  matching_documents = []
86
  message = ""
@@ -172,7 +170,7 @@ class MediatorRetriever(BaseRetriever):
172
  )
173
  try:
174
  number_str = response.choices[0].message.tool_calls[0].function.arguments
175
- mediator_num = json.loads(number_str)['mediator']
176
  except:
177
  mediator_num = 3
178
 
@@ -254,7 +252,7 @@ class MediatorRetriever(BaseRetriever):
254
  memory = ConversationBufferMemory(memory_key="chat_history", input_key="human_input")
255
  chain = load_qa_chain(chat_openai, chain_type="stuff", prompt=prompt, memory=memory)
256
 
257
- output = chain(
258
  {"input_documents": matching_documents, "human_input": query},
259
  return_only_outputs=False
260
  )
@@ -304,20 +302,12 @@ js_code = """
304
  border-radius: 0px;
305
  }
306
 
307
- #component-2 {
308
- background: #006666;
309
- border-radius: 9px;
310
- padding-top: 1%;
311
- }
312
-
313
  #component-4 h1 {
314
  color: white;
315
  }
316
 
317
  #component-6 {
318
- margin-top: -2.2%;
319
- border-top-left-radius: 0px;
320
- border-top-right-radius: 0px;
321
  }
322
 
323
  #component-9 {
@@ -336,19 +326,44 @@ js_code = """
336
  display: none !important;
337
  }
338
 
 
 
 
 
339
  #custom-btn {
340
- right: 3%;
341
- bottom: 1%;
342
- color: white;
343
- text-align: center;
344
- background: #006666;
345
  border-radius: 50%;
346
- position: fixed;
347
- height: 85px;
348
- width: 4.5%;
349
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
350
  </style>
351
  <script>
 
 
 
 
 
 
 
 
 
 
 
 
352
  function autoScroll() {
353
  const chatbox = document.querySelector('.bubble-wrap');
354
  if (chatbox) {
@@ -357,6 +372,8 @@ js_code = """
357
  }
358
 
359
  setTimeout(() => {
 
 
360
  const userInputBox = document.querySelector('textarea.scroll-hide');
361
  userInputBox?.addEventListener('keypress', autoScroll, false);
362
  }, 2000);
@@ -376,8 +393,7 @@ with gr.Blocks(head=js_code) as demo:
376
 
377
  # Add an event listener to the button
378
  with gr.Column(elem_id="center"):
379
- toggle_button = gr.Button("Chat", elem_id="custom-btn")
380
- toggle_button.click(toggle_chatbox, inputs=[], outputs=chatbox_container)
381
 
382
  if __name__ == "__main__":
383
- demo.launch(debug=True)
 
61
  response = openai_client.chat.completions.create(
62
  model="gpt-4-1106-preview",
63
  messages=[
64
+ {"role": "system", "content": "You are a professional mediation field searcher. Your role is to extract information about mediators from user's message. but you have to provide several mediators not one. If there are no mediators in the specific city, then it should return mediators from the state."},
65
  {"role": "user", "content": message}
66
  ],
67
  functions=tools,
 
78
  if new_message:
79
  yield {"search_status" : True, "data" : new_message}
80
 
81
+ def _get_relevant_documents(self, query: str, *, run_manager: CallbackManagerForRetrieverRun) -> List[Document]:
 
 
82
  """Sync implementations for retriever."""
83
  matching_documents = []
84
  message = ""
 
170
  )
171
  try:
172
  number_str = response.choices[0].message.tool_calls[0].function.arguments
173
+ mediator_num = max(int(json.loads(number_str)['mediator']), 3)
174
  except:
175
  mediator_num = 3
176
 
 
252
  memory = ConversationBufferMemory(memory_key="chat_history", input_key="human_input")
253
  chain = load_qa_chain(chat_openai, chain_type="stuff", prompt=prompt, memory=memory)
254
 
255
+ output = chain.invoke(
256
  {"input_documents": matching_documents, "human_input": query},
257
  return_only_outputs=False
258
  )
 
302
  border-radius: 0px;
303
  }
304
 
 
 
 
 
 
 
305
  #component-4 h1 {
306
  color: white;
307
  }
308
 
309
  #component-6 {
310
+ margin-top: 0%;
 
 
311
  }
312
 
313
  #component-9 {
 
326
  display: none !important;
327
  }
328
 
329
+ #message-btn {
330
+ float: inline-end;
331
+ }
332
+
333
  #custom-btn {
334
+ width: 80px;
335
+ height: 80px;
336
+ cursor: pointer;
 
 
337
  border-radius: 50%;
338
+ background: #006666;
 
 
339
  }
340
+
341
+ #component-2 {
342
+ background-image: linear-gradient(#006666, white, white);
343
+ border-radius: 9px;
344
+ padding-top: 1%;
345
+ height: 707px;
346
+ opacity: 0;
347
+ transform: scaleY(0); /* Start with scaleY 0 */
348
+ transform-origin: bottom; /* Transform origin at bottom */
349
+ transition: transform 0.5s ease-out, opacity 0.5s ease-out;
350
+ overflow: hidden;
351
+ }
352
+
353
  </style>
354
  <script>
355
+ function toggleChatbox() {
356
+ const chatbox = document.getElementById('component-2');
357
+ if (chatbox.style.transform === 'scaleY(0)') {
358
+ chatbox.style.transform = 'scaleY(1)';
359
+ chatbox.style.opacity = '1';
360
+ } else {
361
+ chatbox.style.transform = 'scaleY(0)';
362
+ chatbox.style.opacity = '0';
363
+ }
364
+ }
365
+
366
+
367
  function autoScroll() {
368
  const chatbox = document.querySelector('.bubble-wrap');
369
  if (chatbox) {
 
372
  }
373
 
374
  setTimeout(() => {
375
+ chat_bot = document.getElementById('custom-btn');
376
+ document.getElementById('custom-btn').addEventListener('click', toggleChatbox);
377
  const userInputBox = document.querySelector('textarea.scroll-hide');
378
  userInputBox?.addEventListener('keypress', autoScroll, false);
379
  }, 2000);
 
393
 
394
  # Add an event listener to the button
395
  with gr.Column(elem_id="center"):
396
+ toggle_button = gr.HTML(f'<button src="/file=message.png" id="message-btn"/><img style="display: inline;" src="/file=message.png" id="custom-btn"/><button>')
 
397
 
398
  if __name__ == "__main__":
399
+ demo.launch(debug=True, allowed_paths=["./"])
bot.jpg CHANGED
bot.png ADDED
chatbot.png ADDED

Git LFS Details

  • SHA256: 61e2bcfb15e6d008327b08b5e2354b7db5e3022d81f5c51778a97e70ec3f0cd5
  • Pointer size: 132 Bytes
  • Size of remote file: 6.31 MB
embed.py CHANGED
@@ -40,6 +40,7 @@ def summarize(text):
40
 
41
  stuff_chain = StuffDocumentsChain(llm_chain=llm_chain, document_variable_name="text")
42
  return stuff_chain.invoke([Document(page_content=text)])
 
43
 
44
  class MetaDataCSVLoader(BaseLoader):
45
  def __init__(
@@ -116,6 +117,7 @@ if csv_file_uploaded is not None:
116
  new_content += f"{content}: {datum.metadata[content]}\n"
117
 
118
  datum.page_content = new_content
 
119
  PineconeVectorStore.from_documents(data, embeddings, index_name=pinecone_index)
120
 
121
  save_file_to_folder(csv_file_uploaded)
 
40
 
41
  stuff_chain = StuffDocumentsChain(llm_chain=llm_chain, document_variable_name="text")
42
  return stuff_chain.invoke([Document(page_content=text)])
43
+ return stuff_chain.invoke([Document(page_content=text)])
44
 
45
  class MetaDataCSVLoader(BaseLoader):
46
  def __init__(
 
117
  new_content += f"{content}: {datum.metadata[content]}\n"
118
 
119
  datum.page_content = new_content
120
+ # datum.metadata['mediator Biography'] = summarize(datum.metadata['mediator Biography'])
121
  PineconeVectorStore.from_documents(data, embeddings, index_name=pinecone_index)
122
 
123
  save_file_to_folder(csv_file_uploaded)
message.png ADDED
requirements.txt CHANGED
@@ -5,4 +5,3 @@ langchain-pinecone==0.0.3
5
  langchain-openai==0.0.8
6
  python-dotenv==1.0.0
7
  bs4==0.0.2
8
- langchainhub==0.1.20
 
5
  langchain-openai==0.0.8
6
  python-dotenv==1.0.0
7
  bs4==0.0.2
 
templete.py ADDED
@@ -0,0 +1,295 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import List
2
+ from langchain_core.callbacks import CallbackManagerForRetrieverRun
3
+ from langchain_core.documents import Document
4
+ from langchain_core.retrievers import BaseRetriever
5
+ from extract import extract_list
6
+ from openai import OpenAI
7
+ from pinecone import Pinecone
8
+ from langchain_openai import OpenAIEmbeddings, ChatOpenAI
9
+ from langchain.chains.question_answering import load_qa_chain
10
+ from langchain.memory import ConversationBufferMemory
11
+ from langchain.prompts import PromptTemplate
12
+
13
+ import os, json, random
14
+ from dotenv import load_dotenv
15
+ import gradio as gr
16
+
17
+ load_dotenv()
18
+ openai_api_key = os.getenv("OPENAI_API_KEY")
19
+ pinecone_index = os.getenv("PINECONE_INDEX")
20
+ pinecone_api_key = os.getenv("PINECONE_API_KEY")
21
+
22
+ openai_client = OpenAI(api_key=openai_api_key)
23
+
24
+ practice_list = ', '.join(extract_list())
25
+
26
+ description = "Extract mediator's practice field that user want to search. Available mediator practice fields are " + practice_list
27
+ metadata_list = ['fullname', 'mediator profile on mediate.com', 'mediator Biography', 'mediator state']
28
+ metadata_value = ['Name', "Profile", "Biography", "State"]
29
+
30
+ class MediatorRetriever(BaseRetriever):
31
+ def getMetadata(self, message):
32
+ tools = [
33
+ {
34
+ "type": "function",
35
+ "name": "get_info",
36
+ "description": "Extract the information of mediator.",
37
+ "parameters": {
38
+ "type": "object",
39
+ "properties": {
40
+ "mediator country": {
41
+ "type": "string",
42
+ "description": "Extract mediator's country that user wants to search."
43
+ },
44
+ "mediator city": {
45
+ "type": "string",
46
+ "description": "Extract mediator's city that user wants to search."
47
+ },
48
+ "mediator state": {
49
+ "type": "string",
50
+ "description": "Extract mediator's state that user wants to search. If both mediator city and mediator state are possible, please extract as mediator state."
51
+ },
52
+ "mediator areas of practice": {
53
+ "type": "array",
54
+ "description": description,
55
+ "enum": extract_list()
56
+ }
57
+ }
58
+ }
59
+ }
60
+ ]
61
+
62
+ response = openai_client.chat.completions.create(
63
+ model="gpt-4-1106-preview",
64
+ messages=[
65
+ {"role": "system", "content": "You are a professional mediation field searcher. Your role is to extract information about mediators from user's message. but you have to provide several mediators not one. If there are no mediators in the specific city, then it should return mediators from the state."},
66
+ {"role": "user", "content": message}
67
+ ],
68
+ functions=tools,
69
+ stream=True
70
+ )
71
+ new_message = ""
72
+ for chunk in response:
73
+ delta = chunk.choices[0].delta
74
+ if delta and delta.content:
75
+ yield {"search_status" : False, "data" : delta.content}
76
+ elif delta and delta.function_call:
77
+ new_message += delta.function_call.arguments
78
+
79
+ if new_message:
80
+ yield {"search_status" : True, "data" : new_message}
81
+
82
+ def _get_relevant_documents(self, query: str, *, run_manager: CallbackManagerForRetrieverRun) -> List[Document]:
83
+ """Sync implementations for retriever."""
84
+ matching_documents = []
85
+ message = ""
86
+ metaData = self.getMetadata(query)
87
+ for data in metaData:
88
+ if data['data'] is None:
89
+ break
90
+
91
+ search_status = data['search_status']
92
+ if search_status == True:
93
+ metadata = json.loads(data['data'])
94
+ practice_data = ""
95
+ try:
96
+ if 'mediator areas of practice' in metadata:
97
+ practice_data = metadata['mediator areas of practice']
98
+ del metadata['mediator areas of practice']
99
+ elif 'mediator practice field' in metadata:
100
+ practice_data = metadata['mediator practice field']
101
+ del metadata['mediator practice field']
102
+
103
+ except:
104
+ practice_data = ""
105
+
106
+ if "mediator city" in metadata:
107
+ try:
108
+ del metadata['mediator state']
109
+ del metadata['mediator country']
110
+ except:
111
+ pass
112
+ if not practice_data:
113
+ response = openai_client.chat.completions.create(
114
+ model="gpt-4-1106-preview",
115
+ messages=[
116
+ {"role": "system", "content": "Generate a message asking the user about the conflict to better match them with a mediator."},
117
+ {"role": "user", "content": query}
118
+ ],
119
+ stream=True
120
+ )
121
+
122
+ for chunk in response:
123
+ delta = chunk.choices[0].delta
124
+ if delta and delta.content:
125
+ message += delta.content
126
+ yield {"message": message}
127
+
128
+ elif not any(k in metadata for k in ['mediator country', 'mediator state', 'mediator city']):
129
+ response = openai_client.chat.completions.create(
130
+ model="gpt-4-1106-preview",
131
+ messages=[
132
+ {"role": "system", "content": "Generate a message asking the user for their location to find mediators in their area."},
133
+ {"role": "user", "content": query}
134
+ ],
135
+ stream=True
136
+ )
137
+
138
+ for chunk in response:
139
+ delta = chunk.choices[0].delta
140
+ if delta and delta.content:
141
+ message += delta.content
142
+ yield {"message": message}
143
+ else:
144
+ tools = [
145
+ {
146
+ "type": "function",
147
+ "name": "mediator_search",
148
+ "description": "Extract how many mediators the user wants to search.",
149
+ "parameters": {
150
+ "type": "object",
151
+ "properties": {
152
+ "mediator": {
153
+ "type": "number",
154
+ "description": "The number of mediators that the user wants to search. If the user asks for a list of mediators, it means the user wants to search at least 3 mediators. If the user's message doesn't have information about the number of mediators, you have to respond with at least 3.",
155
+ "default": 3
156
+ }
157
+ },
158
+ "required": ["mediator"]
159
+ }
160
+ }
161
+ ]
162
+
163
+ response = openai_client.chat.completions.create(
164
+ model="gpt-4-1106-preview",
165
+ messages=[
166
+ {"role": "system", "content": "Please extract how many mediators users want to search."},
167
+ {"role": "user", "content": query}
168
+ ],
169
+ functions=tools,
170
+ stream=True
171
+ )
172
+ try:
173
+ number_str = response.choices[0].message.tool_calls[0].function.arguments
174
+ mediator_num = max(int(json.loads(number_str)['mediator']), 3)
175
+ except:
176
+ mediator_num = 3
177
+
178
+ template = """"""
179
+ prompt = "You are a professional mediator information analyzer. You have to analyze the following mediators based on the user's message. You shouldn't write the mediator's information again. You shouldn't write the mediators in context as the excellent choice or ideal candidate. You have to analyze the mediators at once. Please respond with no more than 300 characters."
180
+ end = """Context: {context}
181
+ Chat history: {chat_history}
182
+ Human: {human_input}
183
+ Your Response as Chatbot:"""
184
+
185
+ template += prompt + end
186
+
187
+ prompt = PromptTemplate(
188
+ input_variables=["chat_history", "human_input", "context"],
189
+ template=template
190
+ )
191
+
192
+ pc = Pinecone(api_key=pinecone_api_key)
193
+
194
+ embeddings = OpenAIEmbeddings(api_key=openai_api_key)
195
+
196
+ index = pc.Index(pinecone_index)
197
+
198
+ results = index.query(
199
+ vector=embeddings.embed_query(query),
200
+ top_k=5,
201
+ filter=metadata,
202
+ include_metadata=True
203
+ )
204
+
205
+ if (not results['matches']) and 'mediator state' in metadata:
206
+ del metadata['mediator city']
207
+ results = index.query(
208
+ vector=embeddings.embed_query(query),
209
+ top_k=5,
210
+ filter=metadata,
211
+ include_metadata=True
212
+ )
213
+
214
+ new_data = []
215
+ for result in results['matches']:
216
+ data = {}
217
+ for metadata_key in metadata_list:
218
+ data[metadata_key] = result['metadata'].get(metadata_key, "N/A")
219
+
220
+ if practice_data in result['metadata'].get('mediator areas of practice', []):
221
+ new_data.append(data)
222
+
223
+ random.shuffle(new_data)
224
+
225
+ if new_data:
226
+ if practice_data and mediator_num == 1:
227
+ message += f"I have located a mediator who specializes in {practice_data}. Here are their details:\n\n"
228
+ elif practice_data and mediator_num > 1:
229
+ message += f"I have located mediators who specialize in {practice_data}. Here are their details:\n\n"
230
+ elif not practice_data and mediator_num == 1:
231
+ message += f"I have located a mediator. Here are their details:\n\n"
232
+ elif not practice_data and mediator_num > 1:
233
+ message += f"I have located mediators. Here are their details:\n\n"
234
+
235
+ for index, new_datum in enumerate(new_data):
236
+ if index < mediator_num:
237
+ content = ""
238
+
239
+ for metadata_index, metadata_key in enumerate(metadata_list):
240
+ value = new_datum[metadata_key]
241
+ content += f"<b>{metadata_value[metadata_index]}</b>: {value if value else 'N/A'} \n"
242
+ message += f"<b>{metadata_value[metadata_index]}</b>: {value if value else 'N/A'} \n"
243
+
244
+ message += "\n\n"
245
+ new_doc = Document(page_content=content)
246
+ matching_documents.append(new_doc)
247
+ else:
248
+ break
249
+
250
+ memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
251
+ chat_openai = ChatOpenAI(temperature=0, openai_api_key=openai_api_key)
252
+ chain = load_qa_chain(chat_openai, chain_type="stuff", memory=memory, prompt=prompt)
253
+ search_result = chain.run(input_documents=matching_documents, human_input=query)
254
+
255
+ message += search_result
256
+ yield {"documents": matching_documents, "message": message}
257
+
258
+ else:
259
+ message += data['data']
260
+
261
+ yield {"documents": matching_documents, "message": message}
262
+
263
+ retriever = MediatorRetriever()
264
+
265
+ def search(query, history):
266
+ try:
267
+ response = retriever.stream({"input": query, "chat_history": history})
268
+ for chunks in response:
269
+ for chunk in chunks:
270
+ if 'documents' in chunk:
271
+ history.extend([{"role": "user", "content": query}, {"role": "assistant", "content": chunk['message']}])
272
+ yield chunk['message']
273
+ except StopAsyncIteration:
274
+ print("Async iteration ended unexpectedly")
275
+ except Exception as e:
276
+ print(f"An error occurred: {e}")
277
+ yield f"An error occurred: {e}"
278
+
279
+ with gr.Blocks() as demo:
280
+ chatbot = gr.Chatbot()
281
+ msg = gr.Textbox()
282
+ clear = gr.Button("Clear")
283
+
284
+ history = gr.State([])
285
+
286
+ def respond(message, chat_history):
287
+ chat_history = chat_history or []
288
+ bot_message = search(message, chat_history)
289
+ chat_history.append((message, bot_message))
290
+ return "", chat_history
291
+
292
+ msg.submit(respond, [msg, history], [msg, chatbot])
293
+ clear.click(lambda: None, None, chatbot, queue=False)
294
+
295
+ demo.launch()