take the last question as history to understand the question
Browse files
climateqa/chat.py
CHANGED
@@ -101,6 +101,7 @@ async def chat_stream(
|
|
101 |
audience_prompt = init_audience(audience)
|
102 |
sources = sources or ["IPCC", "IPBES"]
|
103 |
reports = reports or []
|
|
|
104 |
|
105 |
# Prepare inputs for agent
|
106 |
inputs = {
|
@@ -109,7 +110,8 @@ async def chat_stream(
|
|
109 |
"sources_input": sources,
|
110 |
"relevant_content_sources_selection": relevant_content_sources_selection,
|
111 |
"search_only": search_only,
|
112 |
-
"reports": reports
|
|
|
113 |
}
|
114 |
|
115 |
# Get streaming events from agent
|
|
|
101 |
audience_prompt = init_audience(audience)
|
102 |
sources = sources or ["IPCC", "IPBES"]
|
103 |
reports = reports or []
|
104 |
+
relevant_history_discussion = history[-2:] if len(history) > 1 else []
|
105 |
|
106 |
# Prepare inputs for agent
|
107 |
inputs = {
|
|
|
110 |
"sources_input": sources,
|
111 |
"relevant_content_sources_selection": relevant_content_sources_selection,
|
112 |
"search_only": search_only,
|
113 |
+
"reports": reports,
|
114 |
+
"chat_history": relevant_history_discussion,
|
115 |
}
|
116 |
|
117 |
# Get streaming events from agent
|
climateqa/engine/chains/answer_rag.py
CHANGED
@@ -65,6 +65,7 @@ def make_rag_node(llm,with_docs = True):
|
|
65 |
async def answer_rag(state,config):
|
66 |
print("---- Answer RAG ----")
|
67 |
start_time = time.time()
|
|
|
68 |
print("Sources used : " + "\n".join([x.metadata["short_name"] + " - page " + str(x.metadata["page_number"]) for x in state["documents"]]))
|
69 |
|
70 |
answer = await rag_chain.ainvoke(state,config)
|
@@ -73,9 +74,10 @@ def make_rag_node(llm,with_docs = True):
|
|
73 |
elapsed_time = end_time - start_time
|
74 |
print("RAG elapsed time: ", elapsed_time)
|
75 |
print("Answer size : ", len(answer))
|
76 |
-
# print(f"\n\nAnswer:\n{answer}")
|
77 |
|
78 |
-
|
|
|
|
|
79 |
|
80 |
return answer_rag
|
81 |
|
|
|
65 |
async def answer_rag(state,config):
|
66 |
print("---- Answer RAG ----")
|
67 |
start_time = time.time()
|
68 |
+
chat_history = state.get("chat_history",[])
|
69 |
print("Sources used : " + "\n".join([x.metadata["short_name"] + " - page " + str(x.metadata["page_number"]) for x in state["documents"]]))
|
70 |
|
71 |
answer = await rag_chain.ainvoke(state,config)
|
|
|
74 |
elapsed_time = end_time - start_time
|
75 |
print("RAG elapsed time: ", elapsed_time)
|
76 |
print("Answer size : ", len(answer))
|
|
|
77 |
|
78 |
+
chat_history.append({"question":state["query"],"answer":answer})
|
79 |
+
|
80 |
+
return {"answer":answer,"chat_history": chat_history}
|
81 |
|
82 |
return answer_rag
|
83 |
|
climateqa/engine/chains/standalone_question.py
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from langchain.prompts import ChatPromptTemplate
|
2 |
+
|
3 |
+
def make_standalone_question_chain(llm):
|
4 |
+
prompt = ChatPromptTemplate.from_messages([
|
5 |
+
("system", """You are a helpful assistant that transforms user questions into standalone questions
|
6 |
+
by incorporating context from the chat history if needed. The output should be a self-contained
|
7 |
+
question that can be understood without any additional context.
|
8 |
+
|
9 |
+
Examples:
|
10 |
+
Chat History: "Let's talk about renewable energy"
|
11 |
+
User Input: "What about solar?"
|
12 |
+
Output: "What are the key aspects of solar energy as a renewable energy source?"
|
13 |
+
|
14 |
+
Chat History: "What causes global warming?"
|
15 |
+
User Input: "And what are its effects?"
|
16 |
+
Output: "What are the effects of global warming on the environment and society?"
|
17 |
+
"""),
|
18 |
+
("user", """Chat History: {chat_history}
|
19 |
+
User Question: {question}
|
20 |
+
|
21 |
+
Transform this into a standalone question:""")
|
22 |
+
])
|
23 |
+
|
24 |
+
chain = prompt | llm
|
25 |
+
return chain
|
26 |
+
|
27 |
+
def make_standalone_question_node(llm):
|
28 |
+
standalone_chain = make_standalone_question_chain(llm)
|
29 |
+
|
30 |
+
def transform_to_standalone(state):
|
31 |
+
chat_history = state.get("chat_history", "")
|
32 |
+
output = standalone_chain.invoke({
|
33 |
+
"chat_history": chat_history,
|
34 |
+
"question": state["user_input"]
|
35 |
+
})
|
36 |
+
state["user_input"] = output.content
|
37 |
+
return state
|
38 |
+
|
39 |
+
return transform_to_standalone
|
climateqa/engine/graph.py
CHANGED
@@ -23,13 +23,14 @@ from .chains.retrieve_documents import make_IPx_retriever_node, make_POC_retriev
|
|
23 |
from .chains.answer_rag import make_rag_node
|
24 |
from .chains.graph_retriever import make_graph_retriever_node
|
25 |
from .chains.chitchat_categorization import make_chitchat_intent_categorization_node
|
26 |
-
|
27 |
|
28 |
class GraphState(TypedDict):
|
29 |
"""
|
30 |
Represents the state of our graph.
|
31 |
"""
|
32 |
user_input : str
|
|
|
33 |
language : str
|
34 |
intent : str
|
35 |
search_graphs_chitchat : bool
|
@@ -128,6 +129,7 @@ def make_graph_agent(llm, vectorstore_ipcc, vectorstore_graphs, vectorstore_regi
|
|
128 |
workflow = StateGraph(GraphState)
|
129 |
|
130 |
# Define the node functions
|
|
|
131 |
categorize_intent = make_intent_categorization_node(llm)
|
132 |
transform_query = make_query_transform_node(llm)
|
133 |
translate_query = make_translation_node(llm)
|
@@ -142,6 +144,7 @@ def make_graph_agent(llm, vectorstore_ipcc, vectorstore_graphs, vectorstore_regi
|
|
142 |
|
143 |
# Define the nodes
|
144 |
# workflow.add_node("set_defaults", set_defaults)
|
|
|
145 |
workflow.add_node("categorize_intent", categorize_intent)
|
146 |
workflow.add_node("answer_climate", dummy)
|
147 |
workflow.add_node("answer_search", answer_search)
|
@@ -157,7 +160,7 @@ def make_graph_agent(llm, vectorstore_ipcc, vectorstore_graphs, vectorstore_regi
|
|
157 |
workflow.add_node("answer_rag_no_docs", answer_rag_no_docs)
|
158 |
|
159 |
# Entry point
|
160 |
-
workflow.set_entry_point("
|
161 |
|
162 |
# CONDITIONAL EDGES
|
163 |
workflow.add_conditional_edges(
|
@@ -190,6 +193,7 @@ def make_graph_agent(llm, vectorstore_ipcc, vectorstore_graphs, vectorstore_regi
|
|
190 |
)
|
191 |
|
192 |
# Define the edges
|
|
|
193 |
workflow.add_edge("translate_query", "transform_query")
|
194 |
workflow.add_edge("transform_query", "retrieve_documents") #TODO put back
|
195 |
# workflow.add_edge("transform_query", "retrieve_local_data")
|
@@ -228,6 +232,8 @@ def make_graph_agent_poc(llm, vectorstore_ipcc, vectorstore_graphs, vectorstore_
|
|
228 |
workflow = StateGraph(GraphState)
|
229 |
|
230 |
# Define the node functions
|
|
|
|
|
231 |
categorize_intent = make_intent_categorization_node(llm)
|
232 |
transform_query = make_query_transform_node(llm)
|
233 |
translate_query = make_translation_node(llm)
|
@@ -243,6 +249,7 @@ def make_graph_agent_poc(llm, vectorstore_ipcc, vectorstore_graphs, vectorstore_
|
|
243 |
|
244 |
# Define the nodes
|
245 |
# workflow.add_node("set_defaults", set_defaults)
|
|
|
246 |
workflow.add_node("categorize_intent", categorize_intent)
|
247 |
workflow.add_node("answer_climate", dummy)
|
248 |
workflow.add_node("answer_search", answer_search)
|
@@ -260,7 +267,7 @@ def make_graph_agent_poc(llm, vectorstore_ipcc, vectorstore_graphs, vectorstore_
|
|
260 |
workflow.add_node("answer_rag_no_docs", answer_rag_no_docs)
|
261 |
|
262 |
# Entry point
|
263 |
-
workflow.set_entry_point("
|
264 |
|
265 |
# CONDITIONAL EDGES
|
266 |
workflow.add_conditional_edges(
|
@@ -293,6 +300,7 @@ def make_graph_agent_poc(llm, vectorstore_ipcc, vectorstore_graphs, vectorstore_
|
|
293 |
)
|
294 |
|
295 |
# Define the edges
|
|
|
296 |
workflow.add_edge("translate_query", "transform_query")
|
297 |
workflow.add_edge("transform_query", "retrieve_documents") #TODO put back
|
298 |
workflow.add_edge("transform_query", "retrieve_local_data")
|
|
|
23 |
from .chains.answer_rag import make_rag_node
|
24 |
from .chains.graph_retriever import make_graph_retriever_node
|
25 |
from .chains.chitchat_categorization import make_chitchat_intent_categorization_node
|
26 |
+
from .chains.standalone_question import make_standalone_question_node
|
27 |
|
28 |
class GraphState(TypedDict):
|
29 |
"""
|
30 |
Represents the state of our graph.
|
31 |
"""
|
32 |
user_input : str
|
33 |
+
chat_history : str
|
34 |
language : str
|
35 |
intent : str
|
36 |
search_graphs_chitchat : bool
|
|
|
129 |
workflow = StateGraph(GraphState)
|
130 |
|
131 |
# Define the node functions
|
132 |
+
standalone_question_node = make_standalone_question_node(llm)
|
133 |
categorize_intent = make_intent_categorization_node(llm)
|
134 |
transform_query = make_query_transform_node(llm)
|
135 |
translate_query = make_translation_node(llm)
|
|
|
144 |
|
145 |
# Define the nodes
|
146 |
# workflow.add_node("set_defaults", set_defaults)
|
147 |
+
workflow.add_node("standalone_question", standalone_question_node)
|
148 |
workflow.add_node("categorize_intent", categorize_intent)
|
149 |
workflow.add_node("answer_climate", dummy)
|
150 |
workflow.add_node("answer_search", answer_search)
|
|
|
160 |
workflow.add_node("answer_rag_no_docs", answer_rag_no_docs)
|
161 |
|
162 |
# Entry point
|
163 |
+
workflow.set_entry_point("standalone_question")
|
164 |
|
165 |
# CONDITIONAL EDGES
|
166 |
workflow.add_conditional_edges(
|
|
|
193 |
)
|
194 |
|
195 |
# Define the edges
|
196 |
+
workflow.add_edge("standalone_question", "categorize_intent")
|
197 |
workflow.add_edge("translate_query", "transform_query")
|
198 |
workflow.add_edge("transform_query", "retrieve_documents") #TODO put back
|
199 |
# workflow.add_edge("transform_query", "retrieve_local_data")
|
|
|
232 |
workflow = StateGraph(GraphState)
|
233 |
|
234 |
# Define the node functions
|
235 |
+
standalone_question_node = make_standalone_question_node(llm)
|
236 |
+
|
237 |
categorize_intent = make_intent_categorization_node(llm)
|
238 |
transform_query = make_query_transform_node(llm)
|
239 |
translate_query = make_translation_node(llm)
|
|
|
249 |
|
250 |
# Define the nodes
|
251 |
# workflow.add_node("set_defaults", set_defaults)
|
252 |
+
workflow.add_node("standalone_question", standalone_question_node)
|
253 |
workflow.add_node("categorize_intent", categorize_intent)
|
254 |
workflow.add_node("answer_climate", dummy)
|
255 |
workflow.add_node("answer_search", answer_search)
|
|
|
267 |
workflow.add_node("answer_rag_no_docs", answer_rag_no_docs)
|
268 |
|
269 |
# Entry point
|
270 |
+
workflow.set_entry_point("standalone_question")
|
271 |
|
272 |
# CONDITIONAL EDGES
|
273 |
workflow.add_conditional_edges(
|
|
|
300 |
)
|
301 |
|
302 |
# Define the edges
|
303 |
+
workflow.add_edge("standalone_question", "categorize_intent")
|
304 |
workflow.add_edge("translate_query", "transform_query")
|
305 |
workflow.add_edge("transform_query", "retrieve_documents") #TODO put back
|
306 |
workflow.add_edge("transform_query", "retrieve_local_data")
|