devve1 commited on
Commit
ebed8ce
1 Parent(s): d054933

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +87 -68
app.py CHANGED
@@ -95,7 +95,7 @@ def transform_query(query: str) -> str:
95
  """
96
  return f'Represent this sentence for searching relevant passages: {query}'
97
 
98
- def query_hybrid_search(query: str, client: QdrantClient, collection_name: str, query_embeddings, sparse_embeddings):
99
  return client.query_points(
100
  collection_name=collection_name,
101
  prefetch=[
@@ -121,7 +121,7 @@ def build_prompt_conv():
121
  },
122
  {
123
  'role': 'user',
124
- 'content': f"""Generate a short, single-sentence summary of the user's intent or topic based on their question, capturing the main focus of what they want to discuss. Do NOT cite the user.
125
 
126
  Question : {st.session_state.user_input}
127
  """
@@ -228,59 +228,74 @@ def self_knowledge(query: str):
228
  Question: {{ query }}
229
  """
230
 
231
- def main(query: str, client: QdrantClient, collection_name: str, llm, dense_model: AsyncEmbeddingEngine, sparse_model: SparseTextEmbedding, past_messages: str):
232
- dense_embeddings, tokens_count = asyncio.run(embed_text(dense_model[0], transform_query(query)))
 
 
 
 
 
 
 
233
  sparse_embeddings = list(sparse_model.query_embed(query))[0].as_object()
234
 
235
  s = time.time()
236
- scored_points = query_hybrid_search(query, client, collection_name, dense_embeddings, sparse_embeddings).points
237
- print(f'Score : {scored_points[0]}')
238
- docs = [(scored_point.payload['text'], scored_point.payload['metadata']) for scored_point in scored_points]
239
- contents, metadatas = [list(t) for t in zip(*docs)]
240
-
241
- context = "\n".join(contents)
242
- print(f'Context : \n + {context}')
243
 
244
- regex = build_regex_from_schema(schema, r"[\n ]?")
245
- gen_text = outlines.generate.regex(llm, regex)
246
 
247
- gen_choice = outlines.generate.choice(llm, choices=['Yes', 'No'])
248
- prompt = route_llm(context, query)
249
- action = gen_choice(prompt, max_tokens=2, sampling_params=SamplingParams(temperature=0))
250
- print(f'Choice: {action}')
251
-
252
- if action == 'Yes':
253
- filtered_metadatas = {
254
- value
255
- for metadata in metadatas
256
- if 'url' in metadata
257
- for value in [metadata['url']]
258
- }
259
- result_metadatas = "\n\n".join(f'{value}' for value in filtered_metadatas)
260
 
261
- prompt = answer_with_context(context, query)
262
- answer = json.loads(gen_text(prompt, max_tokens=300, sampling_params=SamplingParams(temperature=0)))['answer']
263
- answer = f"{answer}\n\n\nSource(s) :\n\n{result_metadatas}"
 
 
 
 
264
 
265
- if st.session_state.initialized == False:
266
- answer = f'Documents Based :\n\n{answer}'
267
- else:
268
- gen_choice = outlines.generate.choice(llm, choices=['Domain-Specific Question', 'General Question'])
269
- prompt = question_type_prompt(query)
270
- action = gen_choice(prompt, max_tokens=3, sampling_params=SamplingParams(temperature=0))
271
- print(f'Choice 2: {action}')
272
- if action == 'General Question':
273
- prompt = open_query_prompt(past_messages, query)
274
- answer = json.loads(gen_text(prompt, max_tokens=300, sampling_params=SamplingParams(temperature=0.6, top_p=0.9, top_k=10)))['answer']
 
 
 
 
 
 
 
 
 
 
 
 
275
  else:
276
- print(f'GLOBAL STATE : {st.session_state.initialized}')
277
- if st.session_state.initialized == True:
278
- prompt = idk(query)
279
- answer = json.loads(gen_text(prompt, max_tokens=128, sampling_params=SamplingParams(temperature=0.6, top_p=0.9, top_k=10)))['answer']
280
- else:
281
- prompt = self_knowledge(query)
 
282
  answer = json.loads(gen_text(prompt, max_tokens=300, sampling_params=SamplingParams(temperature=0.6, top_p=0.9, top_k=10)))['answer']
283
- answer = f'Internal Knowledge :\n\n{answer}'
 
 
 
 
 
 
 
284
 
285
  torch.cuda.empty_cache()
286
 
@@ -577,28 +592,11 @@ def load_models_and_documents():
577
  container.empty()
578
 
579
  return client, collection_name, llm, model, dense_model, sparse_model, nlp, conn, cursor
580
-
581
- def on_change_documents_only():
582
- if st.session_state.documents_only:
583
- st.session_state.initialized = True
584
- st.session_state.toggle_docs = {
585
- 'tooltip': 'The AI answer your questions only considering the documents provided',
586
- 'display': True
587
- }
588
- else:
589
- st.session_state.initialized = False
590
- st.session_state.toggle_docs = {
591
- 'tooltip': """The AI answer your questions considering the documents provided, and if it doesn't found the answer in them, try to find in its own internal knowledge""",
592
- 'display': False
593
- }
594
 
595
 
596
  if __name__ == '__main__':
597
  st.set_page_config(page_title="Multipurpose AI Agent",layout="wide", initial_sidebar_state='auto')
598
 
599
- if 'initialized' not in st.session_state:
600
- st.session_state.initialized = True
601
-
602
  client, collection_name, llm, model, dense_model, sparse_model, nlp, conn, cursor = load_models_and_documents()
603
 
604
  styles = {
@@ -752,6 +750,10 @@ if __name__ == '__main__':
752
  if 'id_chat' not in st.session_state:
753
  st.session_state.id_chat = 'New Conversation'
754
 
 
 
 
 
755
  def options_list(conversations: Dict[str, list]):
756
  if st.session_state.id_chat == 'New Conversation':
757
  return [st.session_state.id_chat] + list(conversations.keys())
@@ -760,10 +762,9 @@ if __name__ == '__main__':
760
 
761
  with st.sidebar:
762
  st.session_state.id_chat = st.selectbox(
763
- label='Choose a conversation',
764
  options=options_list(conversations),
765
  index=0,
766
- placeholder='_',
767
  key='chat_id'
768
  )
769
 
@@ -775,7 +776,6 @@ if __name__ == '__main__':
775
  packed_bytes = msgpack.packb(conversations, use_bin_type=True)
776
  fp.write(packed_bytes)
777
  st.session_state.chat_id = 'New Conversation'
778
-
779
 
780
  st.button(
781
  'Delete Conversation',
@@ -785,6 +785,25 @@ if __name__ == '__main__':
785
  args=(conversations_path, conversations)
786
  )
787
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
788
  def generate_conv_title(llm):
789
  if st.session_state.chat_id == 'New Conversation':
790
  output = llm.chat(
@@ -815,7 +834,7 @@ if __name__ == '__main__':
815
  st.chat_message("user").markdown(prompt)
816
  st.session_state.messages.append({"role": "user", "content": prompt})
817
 
818
- ai_response = main(prompt, client, collection_name, model, dense_model, sparse_model, "\n".join([f'{msg["role"]}: {msg["content"]}' for msg in st.session_state.messages]))
819
  with st.chat_message("assistant"):
820
  message_placeholder = st.empty()
821
  full_response = ""
@@ -843,7 +862,7 @@ if __name__ == '__main__':
843
  'tooltip': 'The AI answer your questions only considering the documents provided',
844
  'display': True
845
  }
846
-
847
  st.toggle(
848
  label="""Enable 'Documents-Only' Mode""",
849
  value=st.session_state.toggle_docs['display'],
 
95
  """
96
  return f'Represent this sentence for searching relevant passages: {query}'
97
 
98
+ def query_hybrid_search(query: str, client: QdrantClient, collection_name: str, dense_embeddings, sparse_embeddings):
99
  return client.query_points(
100
  collection_name=collection_name,
101
  prefetch=[
 
121
  },
122
  {
123
  'role': 'user',
124
+ 'content': f"""Generate a short, single-sentence summary, in 10 tokens maximum, of the user's intent or topic based on their question, capturing the main focus of what they want to discuss. Do NOT cite the user.
125
 
126
  Question : {st.session_state.user_input}
127
  """
 
228
  Question: {{ query }}
229
  """
230
 
231
+ def generate_answer(query: str,
232
+ client: QdrantClient,
233
+ collection_name: str,
234
+ llm,
235
+ dense_model: AsyncEmbeddingEngine,
236
+ sparse_model: SparseTextEmbedding,
237
+ past_messages: str,
238
+ search_strategy: str,
239
+ ):
240
  sparse_embeddings = list(sparse_model.query_embed(query))[0].as_object()
241
 
242
  s = time.time()
 
 
 
 
 
 
 
243
 
244
+ if search_strategy == 'Exact Search':
245
+ scored_points = query_keywords_search(query, client, collection_name, sparse_embeddings).points
246
 
247
+ answer = f"{scored_points[0].payload['text']}\n\n\nSource :\n\n{scored_points[0].payload['metadata']}"
248
+ else:
249
+ regex = build_regex_from_schema(schema, r"[\n ]?")
250
+ gen_text = outlines.generate.regex(llm, regex)
 
 
 
 
 
 
 
 
 
251
 
252
+ gen_choice = outlines.generate.choice(llm, choices=['Yes', 'No'])
253
+ prompt = route_llm(context, query)
254
+ action = gen_choice(prompt, max_tokens=2, sampling_params=SamplingParams(temperature=0))
255
+ print(f'Choice: {action}')
256
+
257
+ if action == 'Yes':
258
+ dense_embeddings, tokens_count = asyncio.run(embed_text(dense_model[0], transform_query(query)))
259
 
260
+ scored_points = query_hybrid_search(query, client, collection_name, dense_embeddings, sparse_embeddings).points
261
+ print(f'Score : {scored_points[0]}')
262
+ docs = [(scored_point.payload['text'], scored_point.payload['metadata']) for scored_point in scored_points]
263
+ contents, metadatas = [list(t) for t in zip(*docs)]
264
+
265
+ context = "\n".join(contents)
266
+ print(f'Context : \n + {context}')
267
+
268
+ filtered_metadatas = {
269
+ value
270
+ for metadata in metadatas
271
+ if 'url' in metadata
272
+ for value in [metadata['url']]
273
+ }
274
+ result_metadatas = "\n\n".join(f'{value}' for value in filtered_metadatas)
275
+
276
+ prompt = answer_with_context(context, query)
277
+ answer = json.loads(gen_text(prompt, max_tokens=300, sampling_params=SamplingParams(temperature=0)))['answer']
278
+ answer = f"{answer}\n\n\nSource(s) :\n\n{result_metadatas}"
279
+
280
+ if search_strategy == 'Documents + LLM Search':
281
+ answer = f'Documents Based :\n\n{answer}'
282
  else:
283
+ gen_choice = outlines.generate.choice(llm, choices=['Domain-Specific Question', 'General Question'])
284
+ prompt = question_type_prompt(query)
285
+ action = gen_choice(prompt, max_tokens=3, sampling_params=SamplingParams(temperature=0))
286
+ print(f'Choice 2: {action}')
287
+
288
+ if action == 'General Question':
289
+ prompt = open_query_prompt(past_messages, query)
290
  answer = json.loads(gen_text(prompt, max_tokens=300, sampling_params=SamplingParams(temperature=0.6, top_p=0.9, top_k=10)))['answer']
291
+ else:
292
+ if search_strategy == 'Documents Only Search':
293
+ prompt = idk(query)
294
+ answer = json.loads(gen_text(prompt, max_tokens=128, sampling_params=SamplingParams(temperature=0.6, top_p=0.9, top_k=10)))['answer']
295
+ elif search_strategy == 'Documents + LLM Search':
296
+ prompt = self_knowledge(query)
297
+ answer = json.loads(gen_text(prompt, max_tokens=300, sampling_params=SamplingParams(temperature=0.6, top_p=0.9, top_k=10)))['answer']
298
+ answer = f'Internal Knowledge :\n\n{answer}'
299
 
300
  torch.cuda.empty_cache()
301
 
 
592
  container.empty()
593
 
594
  return client, collection_name, llm, model, dense_model, sparse_model, nlp, conn, cursor
 
 
 
 
 
 
 
 
 
 
 
 
 
 
595
 
596
 
597
  if __name__ == '__main__':
598
  st.set_page_config(page_title="Multipurpose AI Agent",layout="wide", initial_sidebar_state='auto')
599
 
 
 
 
600
  client, collection_name, llm, model, dense_model, sparse_model, nlp, conn, cursor = load_models_and_documents()
601
 
602
  styles = {
 
750
  if 'id_chat' not in st.session_state:
751
  st.session_state.id_chat = 'New Conversation'
752
 
753
+ if 'search_strategy' not in st.session_state:
754
+ st.session_state.search_strategy = 'Documents Only Search'
755
+ st.session_state.tooltip = 'The AI answer your questions only considering the documents provided'
756
+
757
  def options_list(conversations: Dict[str, list]):
758
  if st.session_state.id_chat == 'New Conversation':
759
  return [st.session_state.id_chat] + list(conversations.keys())
 
762
 
763
  with st.sidebar:
764
  st.session_state.id_chat = st.selectbox(
765
+ label='Choose a Conversation',
766
  options=options_list(conversations),
767
  index=0,
 
768
  key='chat_id'
769
  )
770
 
 
776
  packed_bytes = msgpack.packb(conversations, use_bin_type=True)
777
  fp.write(packed_bytes)
778
  st.session_state.chat_id = 'New Conversation'
 
779
 
780
  st.button(
781
  'Delete Conversation',
 
785
  args=(conversations_path, conversations)
786
  )
787
 
788
+ st.divider()
789
+
790
+ def tooltip_change():
791
+ if st.session_state.search_id == 'Exact Search':
792
+ st.session_state.tooltip = 'Search the exact definition'
793
+ elif st.session_state.search_id == 'Documents Only Search':
794
+ st.session_state.tooltip = 'The AI answer your questions only considering the documents provided'
795
+ elif st.session_state.search_id == 'Documents + LLM Search':
796
+ st.session_state.tooltip = 'The AI answer your questions considering the documents provided, and if it doesn't found the answer in them, try to find in its own internal knowledge'
797
+
798
+ st.session_state.search_strategy = st.radio(
799
+ label='Choose a Search Strategy',
800
+ options=['Exact Search', 'Documents Only Search', 'Documents + LLM Search'],
801
+ index=1,
802
+ on_change=tooltip_change,
803
+ key='search_id',
804
+ help=st.session_state.tooltip
805
+ )
806
+
807
  def generate_conv_title(llm):
808
  if st.session_state.chat_id == 'New Conversation':
809
  output = llm.chat(
 
834
  st.chat_message("user").markdown(prompt)
835
  st.session_state.messages.append({"role": "user", "content": prompt})
836
 
837
+ ai_response = generate_answer(prompt, client, collection_name, model, dense_model, sparse_model, "\n".join([f'{msg["role"]}: {msg["content"]}' for msg in st.session_state.messages]), st.session_state.search_strategy)
838
  with st.chat_message("assistant"):
839
  message_placeholder = st.empty()
840
  full_response = ""
 
862
  'tooltip': 'The AI answer your questions only considering the documents provided',
863
  'display': True
864
  }
865
+
866
  st.toggle(
867
  label="""Enable 'Documents-Only' Mode""",
868
  value=st.session_state.toggle_docs['display'],