From 42f2d0fd0e53bdd7edf59ab13ae19b9dcf49a9d2 Mon Sep 17 00:00:00 2001 From: Yiorgis Gozadinos Date: Fri, 30 Jan 2026 22:43:56 +0200 Subject: [PATCH] docs --- CHANGELOG.md | 8 +++++++ docs/agents.md | 35 ++++++++++++---------------- evaluations/evaluations/benchmark.py | 7 +----- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dcf25872..fbae4fa4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ # Changelog ## [Unreleased] +### Changed + +- **Iterative Research Planning**: Research graph now uses an iterative feedback loop instead of batch question processing + - Planner proposes ONE question at a time, sees the answer, then decides whether to continue + - Removes `gather_context` tool — planner proposes questions directly + - Simpler flow: `plan_next` → `search_one` → loop back until complete → `synthesize` + - Consolidated `build_conversational_graph()` into `build_research_graph(output_mode="conversational")` + ## [0.27.2] - 2026-01-29 ### Added diff --git a/docs/agents.md b/docs/agents.md index 5ddfe641..2711156e 100644 --- a/docs/agents.md +++ b/docs/agents.md @@ -163,44 +163,39 @@ Frontend clients should extract state from under this key. See the [Web Applicat ## Research Graph -The research workflow is implemented as a typed pydantic-graph. It plans, searches (in parallel batches), evaluates, and synthesizes into a final report. +The research workflow is implemented as a typed pydantic-graph. It uses an iterative feedback loop where the planner proposes one question at a time, sees the answer, then decides whether to continue or synthesize. ```mermaid --- title: Research graph --- stateDiagram-v2 - [*] --> plan - plan --> get_batch - get_batch --> search_one: Has questions (map) - get_batch --> synthesize: No questions - search_one --> collect_answers - collect_answers --> decide - decide --> get_batch: Continue research - decide --> synthesize: Done researching + [*] --> plan_next + plan_next --> search_one: Has next question + plan_next --> synthesize: Complete or max iterations + search_one --> plan_next synthesize --> [*] ``` **Key nodes:** -- **plan**: Builds up to 3 standalone sub-questions (uses an internal presearch tool) -- **get_batch**: Retrieves remaining sub-questions for the current iteration -- **search_one**: Answers a single sub-question using the KB (mapped in parallel) -- **collect_answers**: Aggregates search results from parallel executions -- **decide**: Evaluates confidence and determines whether to continue or synthesize +- **plan_next**: Evaluates gathered evidence and either proposes the next question to investigate or marks research as complete +- **search_one**: Answers a single question using the knowledge base - **synthesize**: Generates a final structured research report **Primary models:** -- `SearchAnswer` — one per sub-question (query, answer, confidence, citations) -- `EvaluationResult` — confidence score, new questions, sufficiency assessment +- `IterativePlanResult` — planning decision (is_complete, next_question, reasoning) +- `SearchAnswer` — answer to a single question (query, answer, confidence, citations) - `ResearchReport` — final report (title, executive summary, findings, conclusions, …) +- `ConversationalAnswer` — alternative output for chat integration (answer, citations, confidence) -**Parallel execution:** +**Iterative flow:** -- The `search_one` node is mapped over all questions in a batch -- Parallelism is controlled via `max_concurrency` -- Decision nodes process results after each batch completes +- Each iteration: planner evaluates context → proposes one question → search answers it → loop back +- Planner can decompose complex questions (e.g., "benefits and drawbacks" → start with "benefits") +- Session context is used to resolve ambiguous references and inform planning +- Loop terminates when planner marks `is_complete=True` or `max_iterations` is reached ### CLI Usage diff --git a/evaluations/evaluations/benchmark.py b/evaluations/evaluations/benchmark.py index c6e98a96..247f2df5 100644 --- a/evaluations/evaluations/benchmark.py +++ b/evaluations/evaluations/benchmark.py @@ -308,12 +308,7 @@ async def run_qa_benchmark( async def answer_question(question: str) -> str: context = ResearchContext(original_question=question) - state = ResearchState.from_config( - context=context, - config=config, - max_iterations=2, - confidence_threshold=0.0, - ) + state = ResearchState.from_config(context=context, config=config) deps = ResearchDeps(client=rag) report = await graph.run(state=state, deps=deps) return report.executive_summary if report else ""