Skip to content

Feature/v2 langgraph core - #16

Merged
johnma96 merged 11 commits into
mainfrom
feature/v2-langgraph-core
Aug 20, 2026
Merged

johnma96 merged 11 commits into
mainfrom
feature/v2-langgraph-core

Conversation

@johnma96

Copy link
Copy Markdown
Owner

No description provided.

…s to interfaces

ResearchContext (query, documents, answer) is the LangGraph state per
ADR-005 — a dataclass, not a Pydantic model, since LangGraph accepts
TypedDict/dataclass/BaseModel equally and a dataclass skips re-validating
on every node's partial update.

RetrieveFn and AnswerFn move out of rag_service.py and telegram_bot.py into
domain/interfaces.py: the new research_agent/nodes.py needs RetrieveFn too,
and importing it from a service it has no other relation to would violate
the dependency direction. They now live as contract vocabulary alongside
the Protocols, per ADR-004.
make_retrieve_node and make_generate_node are (ResearchContext) -> dict
functions with zero LangGraph imports, per ADR-005. A node can't take extra
parameters, so RetrieveFn/LLMProvider are injected via a factory closure
instead of module globals or stuffing them into the state — same pattern
as AnswerFn, RetrieveFn and with_logging elsewhere in the project.

Tested by passing a fabricated ResearchContext and asserting the returned
partial-state dict, with no graph execution needed.
Documents T18 kickoff: the LangGraph node/state/factory reasoning behind
today's implementation (ADR-005), plus the mypy stub-limitation finding in
StateGraph.add_node discovered while wiring the graph.
answer_v2_graph invokes build_research_graph(...).ainvoke(ResearchContext),
replacing answer_query as the function wired to TelegramBot. No changes to
telegram_bot.py — the bot still only depends on AnswerFn.

answer_v1_pipeline (the old function-call pipeline) stays in the script,
unwired, so T24 can run it side by side with answer_v2_graph over the same
queries.

Closes the remaining T18 acceptance criteria: bot answers through the
graph, telegram_bot.py untouched, and a new test invokes the compiled graph
end to end with a mocked retriever and LLM.
run_telegram_bot.py and run_research_graph.py had the same embedder/Chroma/
BM25/LLM construction block duplicated. Yesterday it stayed duplicated on
purpose — with a single consumer the abstraction was premature. With two,
it's justified: build_dependencies() in scripts/_wiring.py now returns what
both need.

Also centralizes the pysqlite3 sys.modules patch, previously copied across
four scripts (run_telegram_bot.py, run_research_graph.py, eval_retrieval.py,
ingest_documents.py) — importing _wiring applies it. eval_retrieval.py and
ingest_documents.py only pick up the patch, not build_dependencies(): their
retriever wiring differs enough (per-strategy access, or no retrieval at
all) that forcing them onto the shared factory wasn't worth it.
@johnma96
johnma96 merged commit 999d77b into main Aug 20, 2026
1 check failed
@johnma96
johnma96 deleted the feature/v2-langgraph-core branch August 20, 2026 14:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant