Spaces:
Sleeping
Sleeping
Commit
·
c63e515
1
Parent(s):
6ae72b8
made it asynchronous and resolved some dependency errors
Browse files- .cache.db +0 -0
- .gitignore +1 -0
- app.py +21 -19
- 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.
|
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.
|
146 |
if selected_sources[1]:
|
147 |
-
documents.extend(dora_rts_retriever.
|
148 |
if selected_sources[2]:
|
149 |
-
documents.extend(dora_news_retriever.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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
|