TillLangbein commited on
Commit
c63e515
·
1 Parent(s): 6ae72b8

made it asynchronous and resolved some dependency errors

Browse files
Files changed (4) hide show
  1. .cache.db +0 -0
  2. .gitignore +1 -0
  3. app.py +21 -19
  4. requirements.txt +2 -0
.cache.db CHANGED
Binary files a/.cache.db and b/.cache.db differ
 
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ test_env/
app.py CHANGED
@@ -10,6 +10,7 @@ from langchain_openai import OpenAIEmbeddings
10
  from langgraph.graph import END, StateGraph, START
11
  from langchain_core.output_parsers import StrOutputParser
12
 
 
13
  from typing import List
14
  from typing_extensions import TypedDict
15
  import gradio as gr
@@ -105,7 +106,7 @@ def load_vectorstores(paths: list):
105
  return retrievers
106
 
107
  # Put all chains in fuctions
108
- def dora_rewrite(state):
109
  """
110
  Rewrites the question to fit dora wording
111
 
@@ -118,14 +119,14 @@ def dora_rewrite(state):
118
  print("---TRANSLATE TO DORA---")
119
  question = state["question"]
120
 
121
- new_question = dora_question_rewriter.invoke({"question": question, "topics": TOPICS})
122
 
123
  if new_question == "Thats an interesting question, but I dont think I can answer it based on my Dora knowledge.":
124
  return {"question": new_question, "generation": new_question}
125
  else:
126
  return {"question": new_question}
127
 
128
- def retrieve(state):
129
  """
130
  Retrieve documents
131
 
@@ -142,15 +143,15 @@ def retrieve(state):
142
  # Retrieval
143
  documents = []
144
  if selected_sources[0]:
145
- documents.extend(dora_retriever.invoke(question))
146
  if selected_sources[1]:
147
- documents.extend(dora_rts_retriever.invoke(question))
148
  if selected_sources[2]:
149
- documents.extend(dora_news_retriever.invoke(question))
150
 
151
  return {"documents": documents, "question": question}
152
 
153
- def grade_documents(state):
154
  """
155
  Determines whether the retrieved documents are relevant to the question.
156
 
@@ -169,7 +170,7 @@ def grade_documents(state):
169
 
170
  # Score each doc
171
  for d in documents:
172
- score = retrieval_grader.invoke(
173
  {"question": question, "document": d.page_content}
174
  )
175
  grade = score.binary_score
@@ -185,7 +186,7 @@ def grade_documents(state):
185
 
186
  return {"fitting_documents": fitting_documents}
187
 
188
- def generate(state):
189
  """
190
  Generate answer
191
 
@@ -204,10 +205,10 @@ def generate(state):
204
  dora_news_docs = [d for d in fitting_documents if d.metadata["source"].startswith("https")]
205
 
206
  # RAG generation
207
- generation = answer_chain.invoke({"context": fitting_documents, "question": question})
208
  return {"generation": generation, "dora_docs": dora_docs, "dora_rts_docs": dora_rts_docs, "dora_news_docs": dora_news_docs}
209
 
210
- def transform_query(state):
211
  """
212
  Transform the query to produce a better question.
213
 
@@ -222,12 +223,12 @@ def transform_query(state):
222
  question = state["question"]
223
 
224
  # Re-write question
225
- better_question = question_rewriter.invoke({"question": question})
226
  print(f"{better_question =}")
227
  return {"question": better_question}
228
 
229
  ### Edges ###
230
- def suitable_question(state):
231
  """
232
  Determines whether the question is suitable.
233
 
@@ -246,7 +247,7 @@ def suitable_question(state):
246
  else:
247
  return "retrieve"
248
 
249
- def decide_to_generate(state):
250
  """
251
  Determines whether to generate an answer, or re-generate a question.
252
 
@@ -272,7 +273,7 @@ def decide_to_generate(state):
272
  print(f"---DECISION: GENERATE WITH {len(fitting_documents)} DOCUMENTS---")
273
  return "generate"
274
 
275
- def grade_generation_v_documents_and_question(state):
276
  """
277
  Determines whether the generation is grounded in the document and answers question.
278
 
@@ -288,7 +289,7 @@ def grade_generation_v_documents_and_question(state):
288
  fitting_documents = state["fitting_documents"]
289
  generation = state["generation"]
290
 
291
- score = hallucination_grader.invoke(
292
  {"documents": fitting_documents, "generation": generation}
293
  )
294
  grade = score.binary_score
@@ -298,7 +299,7 @@ def grade_generation_v_documents_and_question(state):
298
  print("---DECISION: GENERATION IS GROUNDED IN DOCUMENTS---")
299
  # Check question-answering
300
  print("---GRADE GENERATION vs QUESTION---")
301
- score = answer_grader.invoke({"question": question, "generation": generation})
302
  grade = score.binary_score
303
  if grade == "yes":
304
  print("---DECISION: GENERATION ADDRESSES QUESTION---")
@@ -313,6 +314,7 @@ def grade_generation_v_documents_and_question(state):
313
  print(f"{generation = }")
314
  return "not supported"
315
 
 
316
  def compile_graph():
317
  workflow = StateGraph(GraphState)
318
  # Define the nodes
@@ -355,9 +357,9 @@ def compile_graph():
355
  return app
356
 
357
  # Function to interact with Gradio
358
- def generate_response(question: str, dora: bool, rts: bool, news: bool):
359
  selected_sources = [dora, rts, news] if any([dora, rts, news]) else [True, False, False]
360
- state = app.invoke({"question": question, "selected_sources": selected_sources})
361
  return (
362
  state["generation"],
363
  ('\n\n'.join([f"***{doc.metadata['source']} section {doc.metadata['section']}***: {doc.page_content}" for doc in state["dora_docs"]])) if "dora_docs" in state and state["dora_docs"] else 'No documents available.',
 
10
  from langgraph.graph import END, StateGraph, START
11
  from langchain_core.output_parsers import StrOutputParser
12
 
13
+ import asyncio
14
  from typing import List
15
  from typing_extensions import TypedDict
16
  import gradio as gr
 
106
  return retrievers
107
 
108
  # Put all chains in fuctions
109
+ async def dora_rewrite(state):
110
  """
111
  Rewrites the question to fit dora wording
112
 
 
119
  print("---TRANSLATE TO DORA---")
120
  question = state["question"]
121
 
122
+ new_question = await dora_question_rewriter.ainvoke({"question": question, "topics": TOPICS})
123
 
124
  if new_question == "Thats an interesting question, but I dont think I can answer it based on my Dora knowledge.":
125
  return {"question": new_question, "generation": new_question}
126
  else:
127
  return {"question": new_question}
128
 
129
+ async def retrieve(state):
130
  """
131
  Retrieve documents
132
 
 
143
  # Retrieval
144
  documents = []
145
  if selected_sources[0]:
146
+ documents.extend(await dora_retriever.ainvoke(question))
147
  if selected_sources[1]:
148
+ documents.extend(await dora_rts_retriever.ainvoke(question))
149
  if selected_sources[2]:
150
+ documents.extend(await dora_news_retriever.ainvoke(question))
151
 
152
  return {"documents": documents, "question": question}
153
 
154
+ async def grade_documents(state):
155
  """
156
  Determines whether the retrieved documents are relevant to the question.
157
 
 
170
 
171
  # Score each doc
172
  for d in documents:
173
+ score = await retrieval_grader.ainvoke(
174
  {"question": question, "document": d.page_content}
175
  )
176
  grade = score.binary_score
 
186
 
187
  return {"fitting_documents": fitting_documents}
188
 
189
+ async def generate(state):
190
  """
191
  Generate answer
192
 
 
205
  dora_news_docs = [d for d in fitting_documents if d.metadata["source"].startswith("https")]
206
 
207
  # RAG generation
208
+ generation = await answer_chain.ainvoke({"context": fitting_documents, "question": question})
209
  return {"generation": generation, "dora_docs": dora_docs, "dora_rts_docs": dora_rts_docs, "dora_news_docs": dora_news_docs}
210
 
211
+ async def transform_query(state):
212
  """
213
  Transform the query to produce a better question.
214
 
 
223
  question = state["question"]
224
 
225
  # Re-write question
226
+ better_question = await question_rewriter.ainvoke({"question": question})
227
  print(f"{better_question =}")
228
  return {"question": better_question}
229
 
230
  ### Edges ###
231
+ async def suitable_question(state):
232
  """
233
  Determines whether the question is suitable.
234
 
 
247
  else:
248
  return "retrieve"
249
 
250
+ async def decide_to_generate(state):
251
  """
252
  Determines whether to generate an answer, or re-generate a question.
253
 
 
273
  print(f"---DECISION: GENERATE WITH {len(fitting_documents)} DOCUMENTS---")
274
  return "generate"
275
 
276
+ async def grade_generation_v_documents_and_question(state):
277
  """
278
  Determines whether the generation is grounded in the document and answers question.
279
 
 
289
  fitting_documents = state["fitting_documents"]
290
  generation = state["generation"]
291
 
292
+ score = await hallucination_grader.ainvoke(
293
  {"documents": fitting_documents, "generation": generation}
294
  )
295
  grade = score.binary_score
 
299
  print("---DECISION: GENERATION IS GROUNDED IN DOCUMENTS---")
300
  # Check question-answering
301
  print("---GRADE GENERATION vs QUESTION---")
302
+ score = await answer_grader.ainvoke({"question": question, "generation": generation})
303
  grade = score.binary_score
304
  if grade == "yes":
305
  print("---DECISION: GENERATION ADDRESSES QUESTION---")
 
314
  print(f"{generation = }")
315
  return "not supported"
316
 
317
+ # Then compile the graph
318
  def compile_graph():
319
  workflow = StateGraph(GraphState)
320
  # Define the nodes
 
357
  return app
358
 
359
  # Function to interact with Gradio
360
+ async def generate_response(question: str, dora: bool, rts: bool, news: bool):
361
  selected_sources = [dora, rts, news] if any([dora, rts, news]) else [True, False, False]
362
+ state = await app.ainvoke({"question": question, "selected_sources": selected_sources})
363
  return (
364
  state["generation"],
365
  ('\n\n'.join([f"***{doc.metadata['source']} section {doc.metadata['section']}***: {doc.page_content}" for doc in state["dora_docs"]])) if "dora_docs" in state and state["dora_docs"] else 'No documents available.',
requirements.txt CHANGED
@@ -5,3 +5,5 @@ langchain_openai==0.2.4
5
  langgraph==0.2.41
6
  pydantic==2.9.2
7
  typing_extensions==4.12.2
 
 
 
5
  langgraph==0.2.41
6
  pydantic==2.9.2
7
  typing_extensions==4.12.2
8
+ faiss-cpu==1.8.0.post1
9
+ asyncio==3.4.3