Skip to content

V1: RAG pipeline with hybrid search, reranker and Telegram bot - #1

Merged
johnma96 merged 56 commits into
mainfrom
feature/v1-infrastructure-setup
Aug 10, 2026
Merged

johnma96 merged 56 commits into
mainfrom
feature/v1-infrastructure-setup

Conversation

@johnma96

Copy link
Copy Markdown
Owner

Scope

Closes V1 of the ResearchOS roadmap: a complete RAG pipeline over open-access
papers, exposed through a Telegram bot, built on Clean Architecture with
Protocol-based abstractions.

What was built

Domain layer

  • Pydantic v2 models: Document, Chunk, Message, Paper
  • Protocols in domain/interfaces.py: LLMProvider, VectorStore,
    Retriever, MemoryStore
  • Prompt templates as .txt files with str.format(), loaded via
    PromptTemplate

Ingestion pipeline (offline)

  • arXiv API client with XML parsing and metadata extraction
  • PDF text extraction with PyMuPDF
  • Fixed-size chunking with overlap in chunking_service.py
  • Orchestrated by ingestion_service.py, run via scripts/ingest_documents.py

Retrieval

  • ChromaVectorStore with local embeddings (sentence-transformers,
    all-MiniLM-L6-v2)
  • BM25Retriever using rank_bm25
  • hybrid_search: Reciprocal Rank Fusion over an arbitrary list of
    Retriever implementations
  • hybrid_rerank_search: Claude as a relevance reranker over hybrid candidates
  • scripts/eval_retrieval.py compares four strategies (vector, BM25, hybrid,
    hybrid+rerank) with P@k and MRR

Delivery channel

  • TelegramBot adapter in infrastructure/bot/telegram_bot.py
  • Wiring in scripts/run_telegram_bot.py, injecting an
    AnswerFn = Callable[[str], Awaitable[str]]

Tests

  • 25 unit tests with @pytest.mark.unit / @pytest.mark.integration
    separation, mocking Protocols rather than concrete implementations

Key architectural decisions

  • Protocols over ABCs. Structural subtyping keeps application/ decoupled
    from inheritance hierarchies and lets test mocks satisfy contracts without
    importing infrastructure.
  • hybrid_search accepts list[Retriever], not concrete classes. Adding a
    third retriever requires no signature change and no edits to
    application/.
  • Engine/channel separation. The Telegram bot receives an injected
    AnswerFn and never instantiates AnthropicLLM or ChromaVectorStore.
    Dependency wiring lives in the composition root (scripts/). The same
    contract will serve Slack, FastAPI or a CLI.
  • Composition over inheritance for agents. Shared behaviour lives in
    agent_utils.py; agents import what they need instead of inheriting from a
    base class.
  • BM25 exposes an async search despite being in-memory, for uniformity
    with ChromaVectorStore under asyncio.gather in hybrid_search. Documented
    as a conscious trade-off; revisit if corpus size makes the blocking cost
    material.

Known debt

  • test_extract_text_pdf depends on a sample PDF that is not versioned, so it
    fails on a clean clone. Should be mocked (V3).
  • The 20-question eval dataset was written with knowledge of the indexed
    corpus (data leakage), so all four strategies score near 1.000 and the
    comparison is non-discriminative. Rebuilt in V3 with real bot queries.
  • No conversational memory: answer_query takes no history, so follow-up
    questions lose their referent (V2).
  • No query rewriting, so anaphoric queries ("what is the mechanism?") retrieve
    poorly even with memory (V2).
  • The bot is wired to vector-only retrieval, not hybrid_rerank_search.
  • Telegram truncates messages above 4096 characters; not handled.

Out of scope for V1

LangGraph orchestration, agent tools, morning briefing, observability,
guardrails, deployment. All planned in V2–V4.

Mario and others added 30 commits March 30, 2026 14:24
…Input/Output, agent_utils)

- Add PromptTemplate class to domain/prompts/__init__.py (str.format, no Jinja2)
- Add AgentInput and AgentOutput models to domain/models.py
- Add load_history_and_append() and wrap_output() to agent_utils.py
…s/ . And update repo structure to v2 clean agents template
John Mario Montoya Zapata added 26 commits May 21, 2026 09:12
Scaffolding for the concepts-tutor system was incomplete — bank generation
and essay proposal modes need these dirs to exist before writing drafts.
Corrects three conceptual errors written in today's learnings.md entry
(infrastructure/application dependency direction, business logic location,
agent composition wording) and tracks them in "¿Qué no entendí bien?" for
follow-up in future sessions. Reconciles the work_log.md draft with the
day's actual commits.
Portable end-of-day skill: reviews the latest learnings.md entry and
synthesizes work_log.md from actual git history, so day closeouts stay
disciplined and traceable across projects.
TelegramBot depends only on AnswerFn (Callable[[str], Awaitable[str]]),
never on LLMProvider/VectorStore/AnthropicLLM/ChromaVectorStore. Wiring
of concrete infrastructure lives in the composition root
(scripts/run_telegram_bot.py) via a closure, keeping the adapter testable
and channel-agnostic.
Adds today's learnings entry on AnswerFn as a lightweight function-type
contract for the Telegram adapter, and reconciles work_log.md with the
actual bot implementation committed today.
@johnma96
johnma96 merged commit d0b9983 into main Aug 10, 2026
1 check failed
@johnma96
johnma96 deleted the feature/v1-infrastructure-setup branch August 10, 2026 18:55
johnma96 added a commit that referenced this pull request Aug 13, 2026
V1: RAG pipeline with hybrid search, reranker and Telegram bot
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