haiku.rag 0.9.1__py3-none-any.whl → 0.9.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- haiku/rag/app.py +2 -7
- haiku/rag/qa/agent.py +3 -0
- haiku/rag/research/__init__.py +2 -0
- haiku/rag/research/base.py +9 -1
- haiku/rag/research/evaluation_agent.py +3 -1
- haiku/rag/research/orchestrator.py +37 -2
- haiku/rag/research/presearch_agent.py +34 -0
- haiku/rag/research/prompts.py +13 -0
- haiku/rag/research/search_agent.py +1 -0
- haiku/rag/research/synthesis_agent.py +4 -3
- {haiku_rag-0.9.1.dist-info → haiku_rag-0.9.2.dist-info}/METADATA +1 -1
- {haiku_rag-0.9.1.dist-info → haiku_rag-0.9.2.dist-info}/RECORD +15 -14
- {haiku_rag-0.9.1.dist-info → haiku_rag-0.9.2.dist-info}/WHEEL +0 -0
- {haiku_rag-0.9.1.dist-info → haiku_rag-0.9.2.dist-info}/entry_points.txt +0 -0
- {haiku_rag-0.9.1.dist-info → haiku_rag-0.9.2.dist-info}/licenses/LICENSE +0 -0
haiku/rag/app.py
CHANGED
|
@@ -122,12 +122,7 @@ class HaikuRAGApp:
|
|
|
122
122
|
self.console.print(f"• {finding}")
|
|
123
123
|
self.console.print()
|
|
124
124
|
|
|
125
|
-
# Themes
|
|
126
|
-
if report.themes:
|
|
127
|
-
self.console.print("[bold cyan]Key Themes:[/bold cyan]")
|
|
128
|
-
for theme, explanation in report.themes.items():
|
|
129
|
-
self.console.print(f"• [bold]{theme}[/bold]: {explanation}")
|
|
130
|
-
self.console.print()
|
|
125
|
+
# (Themes section removed)
|
|
131
126
|
|
|
132
127
|
# Conclusions
|
|
133
128
|
if report.conclusions:
|
|
@@ -261,7 +256,7 @@ class HaikuRAGApp:
|
|
|
261
256
|
elif transport == "sse":
|
|
262
257
|
await server.run_sse_async()
|
|
263
258
|
else:
|
|
264
|
-
await server.run_http_async("streamable-http")
|
|
259
|
+
await server.run_http_async(transport="streamable-http")
|
|
265
260
|
except KeyboardInterrupt:
|
|
266
261
|
pass
|
|
267
262
|
finally:
|
haiku/rag/qa/agent.py
CHANGED
|
@@ -49,6 +49,9 @@ class QuestionAnswerAgent:
|
|
|
49
49
|
limit: int = 3,
|
|
50
50
|
) -> list[SearchResult]:
|
|
51
51
|
"""Search the knowledge base for relevant documents."""
|
|
52
|
+
|
|
53
|
+
# Remove quotes from queries as this requires positional indexing in lancedb
|
|
54
|
+
query = query.replace('"', "")
|
|
52
55
|
search_results = await ctx.deps.client.search(query, limit=limit)
|
|
53
56
|
expanded_results = await ctx.deps.client.expand_context(search_results)
|
|
54
57
|
|
haiku/rag/research/__init__.py
CHANGED
|
@@ -12,6 +12,7 @@ from haiku.rag.research.evaluation_agent import (
|
|
|
12
12
|
EvaluationResult,
|
|
13
13
|
)
|
|
14
14
|
from haiku.rag.research.orchestrator import ResearchOrchestrator, ResearchPlan
|
|
15
|
+
from haiku.rag.research.presearch_agent import PresearchSurveyAgent
|
|
15
16
|
from haiku.rag.research.search_agent import SearchSpecialistAgent
|
|
16
17
|
from haiku.rag.research.synthesis_agent import ResearchReport, SynthesisAgent
|
|
17
18
|
|
|
@@ -25,6 +26,7 @@ __all__ = [
|
|
|
25
26
|
# Specialized agents
|
|
26
27
|
"SearchAnswer",
|
|
27
28
|
"SearchSpecialistAgent",
|
|
29
|
+
"PresearchSurveyAgent",
|
|
28
30
|
"AnalysisEvaluationAgent",
|
|
29
31
|
"EvaluationResult",
|
|
30
32
|
"SynthesisAgent",
|
haiku/rag/research/base.py
CHANGED
|
@@ -33,10 +33,18 @@ class BaseResearchAgent[T](ABC):
|
|
|
33
33
|
# Import deps type lazily to avoid circular import during module load
|
|
34
34
|
from haiku.rag.research.dependencies import ResearchDependencies
|
|
35
35
|
|
|
36
|
+
# If the agent is expected to return plain text, pass `str` directly.
|
|
37
|
+
# Otherwise, wrap the model with ToolOutput for robust tool-handling retries.
|
|
38
|
+
agent_output_type: Any
|
|
39
|
+
if self.output_type is str: # plain text output
|
|
40
|
+
agent_output_type = str
|
|
41
|
+
else:
|
|
42
|
+
agent_output_type = ToolOutput(self.output_type, max_retries=3)
|
|
43
|
+
|
|
36
44
|
self._agent = Agent(
|
|
37
45
|
model=model_obj,
|
|
38
46
|
deps_type=ResearchDependencies,
|
|
39
|
-
output_type=
|
|
47
|
+
output_type=agent_output_type,
|
|
40
48
|
system_prompt=self.get_system_prompt(),
|
|
41
49
|
)
|
|
42
50
|
|
|
@@ -11,7 +11,9 @@ class EvaluationResult(BaseModel):
|
|
|
11
11
|
description="Main insights extracted from the research so far"
|
|
12
12
|
)
|
|
13
13
|
new_questions: list[str] = Field(
|
|
14
|
-
description="New sub-questions to add to the research (max 3)",
|
|
14
|
+
description="New sub-questions to add to the research (max 3)",
|
|
15
|
+
max_length=3,
|
|
16
|
+
default=[],
|
|
15
17
|
)
|
|
16
18
|
confidence_score: float = Field(
|
|
17
19
|
description="Confidence level in the completeness of research (0-1)",
|
|
@@ -12,6 +12,7 @@ from haiku.rag.research.evaluation_agent import (
|
|
|
12
12
|
AnalysisEvaluationAgent,
|
|
13
13
|
EvaluationResult,
|
|
14
14
|
)
|
|
15
|
+
from haiku.rag.research.presearch_agent import PresearchSurveyAgent
|
|
15
16
|
from haiku.rag.research.prompts import ORCHESTRATOR_PROMPT
|
|
16
17
|
from haiku.rag.research.search_agent import SearchSpecialistAgent
|
|
17
18
|
from haiku.rag.research.synthesis_agent import ResearchReport, SynthesisAgent
|
|
@@ -41,6 +42,9 @@ class ResearchOrchestrator(BaseResearchAgent[ResearchPlan]):
|
|
|
41
42
|
self.search_agent: SearchSpecialistAgent = SearchSpecialistAgent(
|
|
42
43
|
provider, model
|
|
43
44
|
)
|
|
45
|
+
self.presearch_agent: PresearchSurveyAgent = PresearchSurveyAgent(
|
|
46
|
+
provider, model
|
|
47
|
+
)
|
|
44
48
|
self.evaluation_agent: AnalysisEvaluationAgent = AnalysisEvaluationAgent(
|
|
45
49
|
provider, model
|
|
46
50
|
)
|
|
@@ -61,7 +65,12 @@ class ResearchOrchestrator(BaseResearchAgent[ResearchPlan]):
|
|
|
61
65
|
"original_question": context.original_question,
|
|
62
66
|
"unanswered_questions": context.sub_questions,
|
|
63
67
|
"qa_responses": [
|
|
64
|
-
{
|
|
68
|
+
{
|
|
69
|
+
"question": qa.query,
|
|
70
|
+
"answer": qa.answer,
|
|
71
|
+
"context_snippets": qa.context,
|
|
72
|
+
"sources": qa.sources,
|
|
73
|
+
}
|
|
65
74
|
for qa in context.qa_responses
|
|
66
75
|
],
|
|
67
76
|
"insights": context.insights,
|
|
@@ -99,12 +108,38 @@ class ResearchOrchestrator(BaseResearchAgent[ResearchPlan]):
|
|
|
99
108
|
# Use provided console or create a new one
|
|
100
109
|
console = console or Console() if verbose else None
|
|
101
110
|
|
|
111
|
+
# Run a simple presearch survey to summarize KB context
|
|
112
|
+
if console:
|
|
113
|
+
console.print(
|
|
114
|
+
"\n[bold cyan]🔎 Presearch: summarizing KB context...[/bold cyan]"
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
presearch_result = await self.presearch_agent.run(question, deps=deps)
|
|
118
|
+
|
|
102
119
|
# Create initial research plan
|
|
103
120
|
if console:
|
|
104
121
|
console.print("\n[bold cyan]📋 Creating research plan...[/bold cyan]")
|
|
105
122
|
|
|
123
|
+
# Include the presearch summary to ground the planning step.
|
|
124
|
+
|
|
125
|
+
planning_context_xml = format_as_xml(
|
|
126
|
+
{
|
|
127
|
+
"original_question": question,
|
|
128
|
+
"presearch_summary": presearch_result.output or "",
|
|
129
|
+
},
|
|
130
|
+
root_tag="planning_context",
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
plan_prompt = (
|
|
134
|
+
"Create a research plan for the main question below.\n\n"
|
|
135
|
+
f"Main question: {question}\n\n"
|
|
136
|
+
"Use this brief presearch summary to inform the plan. Focus the 3 sub-questions "
|
|
137
|
+
"on the most important aspects not already obvious from the current KB context.\n\n"
|
|
138
|
+
f"{planning_context_xml}"
|
|
139
|
+
)
|
|
140
|
+
|
|
106
141
|
plan_result: AgentRunResult[ResearchPlan] = await self.run(
|
|
107
|
-
|
|
142
|
+
plan_prompt, deps=deps
|
|
108
143
|
)
|
|
109
144
|
|
|
110
145
|
context.sub_questions = plan_result.output.sub_questions
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from pydantic_ai import RunContext
|
|
2
|
+
from pydantic_ai.run import AgentRunResult
|
|
3
|
+
|
|
4
|
+
from haiku.rag.research.base import BaseResearchAgent
|
|
5
|
+
from haiku.rag.research.dependencies import ResearchDependencies
|
|
6
|
+
from haiku.rag.research.prompts import PRESEARCH_AGENT_PROMPT
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class PresearchSurveyAgent(BaseResearchAgent[str]):
|
|
10
|
+
"""Presearch agent that gathers verbatim context and summarizes it."""
|
|
11
|
+
|
|
12
|
+
def __init__(self, provider: str, model: str) -> None:
|
|
13
|
+
super().__init__(provider, model, str)
|
|
14
|
+
|
|
15
|
+
async def run(
|
|
16
|
+
self, prompt: str, deps: ResearchDependencies, **kwargs
|
|
17
|
+
) -> AgentRunResult[str]:
|
|
18
|
+
return await super().run(prompt, deps, **kwargs)
|
|
19
|
+
|
|
20
|
+
def get_system_prompt(self) -> str:
|
|
21
|
+
return PRESEARCH_AGENT_PROMPT
|
|
22
|
+
|
|
23
|
+
def register_tools(self) -> None:
|
|
24
|
+
@self.agent.tool
|
|
25
|
+
async def gather_context(
|
|
26
|
+
ctx: RunContext[ResearchDependencies],
|
|
27
|
+
query: str,
|
|
28
|
+
limit: int = 6,
|
|
29
|
+
) -> str:
|
|
30
|
+
"""Return verbatim concatenation of relevant chunk texts."""
|
|
31
|
+
query = query.replace('"', "")
|
|
32
|
+
results = await ctx.deps.client.search(query, limit=limit)
|
|
33
|
+
expanded = await ctx.deps.client.expand_context(results)
|
|
34
|
+
return "\n\n".join(chunk.content for chunk, _ in expanded)
|
haiku/rag/research/prompts.py
CHANGED
|
@@ -114,3 +114,16 @@ Focus on creating a report that provides clear value to the reader by:
|
|
|
114
114
|
- Highlighting the most important findings
|
|
115
115
|
- Explaining the implications of the research
|
|
116
116
|
- Suggesting concrete next steps"""
|
|
117
|
+
|
|
118
|
+
PRESEARCH_AGENT_PROMPT = """You are a rapid research surveyor.
|
|
119
|
+
|
|
120
|
+
Task:
|
|
121
|
+
- Call the gather_context tool once with the main question to obtain a
|
|
122
|
+
relevant texts from the Knowledge Base (KB).
|
|
123
|
+
- Read that context and produce a brief natural-language summary describing
|
|
124
|
+
what the KB appears to contain relative to the question.
|
|
125
|
+
|
|
126
|
+
Rules:
|
|
127
|
+
- Base the summary strictly on the provided text; do not invent.
|
|
128
|
+
- Output only the summary as plain text (one short paragraph).
|
|
129
|
+
"""
|
|
@@ -42,6 +42,7 @@ class SearchSpecialistAgent(BaseResearchAgent[SearchAnswer]):
|
|
|
42
42
|
) -> str:
|
|
43
43
|
"""Search the KB and return a concise context pack."""
|
|
44
44
|
# Remove quotes from queries as this requires positional indexing in lancedb
|
|
45
|
+
# XXX: Investigate how to do that with lancedb
|
|
45
46
|
query = query.replace('"', "")
|
|
46
47
|
search_results = await ctx.deps.client.search(query, limit=limit)
|
|
47
48
|
expanded = await ctx.deps.client.expand_context(search_results)
|
|
@@ -12,11 +12,12 @@ class ResearchReport(BaseModel):
|
|
|
12
12
|
main_findings: list[str] = Field(
|
|
13
13
|
description="Primary research findings with supporting evidence"
|
|
14
14
|
)
|
|
15
|
-
themes: dict[str, str] = Field(description="Major themes and their explanations")
|
|
16
15
|
conclusions: list[str] = Field(description="Evidence-based conclusions")
|
|
17
|
-
limitations: list[str] = Field(
|
|
16
|
+
limitations: list[str] = Field(
|
|
17
|
+
description="Limitations of the current research", default=[]
|
|
18
|
+
)
|
|
18
19
|
recommendations: list[str] = Field(
|
|
19
|
-
description="Actionable recommendations based on findings"
|
|
20
|
+
description="Actionable recommendations based on findings", default=[]
|
|
20
21
|
)
|
|
21
22
|
sources_summary: str = Field(
|
|
22
23
|
description="Summary of sources used and their reliability"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
haiku/rag/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
haiku/rag/app.py,sha256=
|
|
2
|
+
haiku/rag/app.py,sha256=o64L7aj5V8lYHxWhAKBNj1tGfXiN6xr0_Cc1dEYd3As,11483
|
|
3
3
|
haiku/rag/chunker.py,sha256=PVe6ysv8UlacUd4Zb3_8RFWIaWDXnzBAy2VDJ4TaUsE,1555
|
|
4
4
|
haiku/rag/cli.py,sha256=3nlzrT5FPCyfnu51KHchLG4Cj2eVv9YsuGHMShBnVb0,9845
|
|
5
5
|
haiku/rag/client.py,sha256=NJVGXzVzpoVy1sttz_xEU7mXWtObKT8pGpvo5pZyzwc,21288
|
|
@@ -17,21 +17,22 @@ haiku/rag/embeddings/openai.py,sha256=fIFCk-jpUtaW0xsnrQnJ824O0UCjaGG2sgvBzREhil
|
|
|
17
17
|
haiku/rag/embeddings/vllm.py,sha256=vhaUnCn6VMkfSluLhWKtSV-sekFaPsp4pKo2N7-SBCY,626
|
|
18
18
|
haiku/rag/embeddings/voyageai.py,sha256=UW-MW4tJKnPB6Fs2P7A3yt-ZeRm46H9npckchSriPX8,661
|
|
19
19
|
haiku/rag/qa/__init__.py,sha256=Sl7Kzrg9CuBOcMF01wc1NtQhUNWjJI0MhIHfCWrb8V4,434
|
|
20
|
-
haiku/rag/qa/agent.py,sha256=
|
|
20
|
+
haiku/rag/qa/agent.py,sha256=f4Keh-ESgctNbTg96QL95HYjINVLOcxa8t8crx92MMk,3081
|
|
21
21
|
haiku/rag/qa/prompts.py,sha256=LhRfDtO8Pb06lpr4PpwEaKUYItZ5OiIkeqcCogcssHY,3347
|
|
22
22
|
haiku/rag/reranking/__init__.py,sha256=IRXHs4qPu6VbGJQpzSwhgtVWWumURH_vEoVFE-extlo,894
|
|
23
23
|
haiku/rag/reranking/base.py,sha256=LM9yUSSJ414UgBZhFTgxGprlRqzfTe4I1vgjricz2JY,405
|
|
24
24
|
haiku/rag/reranking/cohere.py,sha256=1iTdiaa8vvb6oHVB2qpWzUOVkyfUcimVSZp6Qr4aq4c,1049
|
|
25
25
|
haiku/rag/reranking/mxbai.py,sha256=46sVTsTIkzIX9THgM3u8HaEmgY7evvEyB-N54JTHvK8,867
|
|
26
26
|
haiku/rag/reranking/vllm.py,sha256=xVGH9ss-ISWdJ5SKUUHUbTqBo7PIEmA_SQv0ScdJ6XA,1479
|
|
27
|
-
haiku/rag/research/__init__.py,sha256=
|
|
28
|
-
haiku/rag/research/base.py,sha256=
|
|
27
|
+
haiku/rag/research/__init__.py,sha256=qLF41YayAxW_VeHhuTceVuz9hw1FNbuRV9VMhonUMW0,1078
|
|
28
|
+
haiku/rag/research/base.py,sha256=ZUvqh-IxU8r4mOPRKjwZcHciKcIfrTnP6Q_9jVElelQ,4041
|
|
29
29
|
haiku/rag/research/dependencies.py,sha256=vZctKC5donqhm8LFO6hQdXZZXzjdW1__4eUlhyZn058,1573
|
|
30
|
-
haiku/rag/research/evaluation_agent.py,sha256=
|
|
31
|
-
haiku/rag/research/orchestrator.py,sha256=
|
|
32
|
-
haiku/rag/research/
|
|
33
|
-
haiku/rag/research/
|
|
34
|
-
haiku/rag/research/
|
|
30
|
+
haiku/rag/research/evaluation_agent.py,sha256=yyBobKr8MRwiox59I2Jqycp02ju9EGVaI9FceRGL188,1386
|
|
31
|
+
haiku/rag/research/orchestrator.py,sha256=LrxRG74BWun0T4uOxhc9AuitxbPioS_eG_nE098ftyY,11765
|
|
32
|
+
haiku/rag/research/presearch_agent.py,sha256=vf-WlY46g5tuuLKMBuPXXYYffynsBw7KVLr8LoTNHnU,1292
|
|
33
|
+
haiku/rag/research/prompts.py,sha256=pVRB7_b_p3JaLF1bC3ANTbSFY78ypSjDhoq6peoU6jo,5685
|
|
34
|
+
haiku/rag/research/search_agent.py,sha256=0iK7vCd9w7h8pWJgB6VUSPOdjlzB8peboNSXxuEGBK0,2464
|
|
35
|
+
haiku/rag/research/synthesis_agent.py,sha256=jo5rg7aL4zGXLQP105cANqRPIiwJLqYe2unO5BQkNvE,1511
|
|
35
36
|
haiku/rag/store/__init__.py,sha256=hq0W0DAC7ysqhWSP2M2uHX8cbG6kbr-sWHxhq6qQcY0,103
|
|
36
37
|
haiku/rag/store/engine.py,sha256=fNrykqMX7PRSCt4LSRfuJ66OLrb8BVYq2bpbfI2iaWU,8455
|
|
37
38
|
haiku/rag/store/models/__init__.py,sha256=s0E72zneGlowvZrFWaNxHYjOAUjgWdLxzdYsnvNRVlY,88
|
|
@@ -42,8 +43,8 @@ haiku/rag/store/repositories/chunk.py,sha256=1RmPyEYRYOFbrALbmLOo62t3f-xO2KgxUjc
|
|
|
42
43
|
haiku/rag/store/repositories/document.py,sha256=XoLCrMrZqs0iCZoHlDOfRDaVUux77Vdu5iZczduF1rY,7812
|
|
43
44
|
haiku/rag/store/repositories/settings.py,sha256=wx3fuP_5CpPflZHRrIkeoer6ml-iD0qXERh5k6MQRzI,5291
|
|
44
45
|
haiku/rag/store/upgrades/__init__.py,sha256=wUiEoSiHTahvuagx93E4FB07v123AhdbOjwUkPusiIg,14
|
|
45
|
-
haiku_rag-0.9.
|
|
46
|
-
haiku_rag-0.9.
|
|
47
|
-
haiku_rag-0.9.
|
|
48
|
-
haiku_rag-0.9.
|
|
49
|
-
haiku_rag-0.9.
|
|
46
|
+
haiku_rag-0.9.2.dist-info/METADATA,sha256=IM9tGvye83CRTj2wOFtPP7oD9KtJvp3RXh4QdCFknD4,4681
|
|
47
|
+
haiku_rag-0.9.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
48
|
+
haiku_rag-0.9.2.dist-info/entry_points.txt,sha256=G1U3nAkNd5YDYd4v0tuYFbriz0i-JheCsFuT9kIoGCI,48
|
|
49
|
+
haiku_rag-0.9.2.dist-info/licenses/LICENSE,sha256=eXZrWjSk9PwYFNK9yUczl3oPl95Z4V9UXH7bPN46iPo,1065
|
|
50
|
+
haiku_rag-0.9.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|