Improve behavior of simple reasoning (#157)
* Add base reasoning implementation * Provide explicit async and streaming capability * Allow refreshing the information panel
This commit is contained in:
committed by
GitHub
parent
cb01d27d19
commit
2950e6ed02
@@ -209,7 +209,10 @@ class ChatPage(BasePage):
|
||||
if "output" in response:
|
||||
text += response["output"]
|
||||
if "evidence" in response:
|
||||
refs += response["evidence"]
|
||||
if response["evidence"] is None:
|
||||
refs = ""
|
||||
else:
|
||||
refs += response["evidence"]
|
||||
|
||||
if len(refs) > len_ref:
|
||||
print(f"Len refs: {len(refs)}")
|
||||
|
@@ -1,5 +1,49 @@
|
||||
from typing import Optional
|
||||
|
||||
from kotaemon.base import BaseComponent
|
||||
|
||||
|
||||
class BaseReasoning(BaseComponent):
|
||||
retrievers: list = []
|
||||
"""The reasoning pipeline that handles each of the user chat messages
|
||||
|
||||
This reasoning pipeline has access to:
|
||||
- the retrievers
|
||||
- the user settings
|
||||
- the message
|
||||
- the conversation id
|
||||
- the message history
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def get_info(cls) -> dict:
|
||||
"""Get the pipeline information for the app to organize and display
|
||||
|
||||
Returns:
|
||||
a dictionary that contains the following keys:
|
||||
- "id": the unique id of the pipeline
|
||||
- "name": the human-friendly name of the pipeline
|
||||
- "description": the overview short description of the pipeline, for
|
||||
user to grasp what does the pipeline do
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
def get_user_settings(cls) -> dict:
|
||||
"""Get the default user settings for this pipeline"""
|
||||
return {}
|
||||
|
||||
@classmethod
|
||||
def get_pipeline(
|
||||
cls, user_settings: dict, retrievers: Optional[list["BaseComponent"]] = None
|
||||
) -> "BaseReasoning":
|
||||
"""Get the reasoning pipeline for the app to execute
|
||||
|
||||
Args:
|
||||
user_setting: user settings
|
||||
retrievers (list): List of retrievers
|
||||
"""
|
||||
return cls()
|
||||
|
||||
def run(self, message: str, conv_id: str, history: list, **kwargs): # type: ignore
|
||||
"""Execute the reasoning pipeline"""
|
||||
raise NotImplementedError
|
||||
|
@@ -200,22 +200,24 @@ class AnswerWithContextPipeline(BaseComponent):
|
||||
lang=self.lang,
|
||||
)
|
||||
|
||||
citation_task = asyncio.create_task(
|
||||
self.citation_pipeline.ainvoke(context=evidence, question=question)
|
||||
)
|
||||
print("Citation task created")
|
||||
|
||||
messages = []
|
||||
if self.system_prompt:
|
||||
messages.append(SystemMessage(content=self.system_prompt))
|
||||
messages.append(HumanMessage(content=prompt))
|
||||
output = ""
|
||||
for text in self.llm(messages):
|
||||
for text in self.llm.stream(messages):
|
||||
output += text.text
|
||||
self.report_output({"output": text.text})
|
||||
await asyncio.sleep(0)
|
||||
|
||||
try:
|
||||
citation = self.citation_pipeline(context=evidence, question=question)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
citation = None
|
||||
|
||||
# retrieve the citation
|
||||
print("Waiting for citation task")
|
||||
citation = await citation_task
|
||||
answer = Document(text=output, metadata={"citation": citation})
|
||||
|
||||
return answer
|
||||
@@ -242,6 +244,19 @@ class FullQAPipeline(BaseReasoning):
|
||||
if doc.doc_id not in doc_ids:
|
||||
docs.append(doc)
|
||||
doc_ids.append(doc.doc_id)
|
||||
for doc in docs:
|
||||
self.report_output(
|
||||
{
|
||||
"evidence": (
|
||||
"<details open>"
|
||||
f"<summary>{doc.metadata['file_name']}</summary>"
|
||||
f"{doc.text}"
|
||||
"</details><br>"
|
||||
)
|
||||
}
|
||||
)
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
evidence_mode, evidence = self.evidence_pipeline(docs).content
|
||||
answer = await self.answering_pipeline(
|
||||
question=message, evidence=evidence, evidence_mode=evidence_mode
|
||||
@@ -266,6 +281,7 @@ class FullQAPipeline(BaseReasoning):
|
||||
id2docs = {doc.doc_id: doc for doc in docs}
|
||||
lack_evidence = True
|
||||
not_detected = set(id2docs.keys()) - set(spans.keys())
|
||||
self.report_output({"evidence": None})
|
||||
for id, ss in spans.items():
|
||||
if not ss:
|
||||
not_detected.add(id)
|
||||
@@ -282,7 +298,7 @@ class FullQAPipeline(BaseReasoning):
|
||||
self.report_output(
|
||||
{
|
||||
"evidence": (
|
||||
"<details>"
|
||||
"<details open>"
|
||||
f"<summary>{id2docs[id].metadata['file_name']}</summary>"
|
||||
f"{text}"
|
||||
"</details><br>"
|
||||
|
Reference in New Issue
Block a user