Skip to content

yastman/rag

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

5,180 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

RAG Q&A Chatbot

Ask questions in natural language. Get answers grounded in your private documents.

CI Python 3.12+ Docker Compose License: MIT Code style: ruff


A self-hostable RAG question-answer bot. Users ask in natural language via Telegram; the system retrieves grounded context from a Qdrant document store and generates a cited answer via an LLM. It is a Python modular monolith β€” one process, in-process function calls, with external sidecar services managed by Docker Compose.

The current live domain is real-estate/apartments. The domain layer is replaceable.

Features

The live Telegram bot is a real-estate assistant: a RAG Q&A core plus a service menu. All actions are kept; only the question path is the pure RAG core, the rest is the (replaceable) domain layer.

Menu action What it does Layer
πŸ’¬ Ask a question RAG Q&A over the document store core
🏠 Find an apartment Filtered catalog search domain
πŸ”‘ Services Service info domain
πŸ“… Book a viewing Schedule a viewing domain
πŸ‘€ Contact a manager Human handoff (HITL) domain/agent
πŸ“Œ My bookmarks Saved listings domain
🎯 Demo Guided demo flow domain

How It Works

User message (Telegram)
        β”‚
        β–Ό
run_assistant_request()          src/core/assistant.py
        β”‚
        β–Ό
run_assistant_pipeline()         src/runtime/pipeline/assistant_pipeline.py
        β”‚
        β”œβ”€ classify_query()      src/runtime/graph/nodes/classify.py
        β”‚
        β–Ό
rag_pipeline()                   src/runtime/pipeline/rag.py
        β”‚  cache check β†’ hybrid Qdrant search (dense+sparse+ColBERT)
        β”‚  β†’ grade docs β†’ optional rerank β†’ optional query-rewrite loop
        β”‚  returns: grounded document context
        β”‚
        β–Ό
generate_answer()                src/runtime/generation/service.py
        β”‚  LLM call with retrieved context
        β”‚
        β–Ό
AssistantResult (answer + citations)
        β”‚
        β–Ό
Telegram reply

run_assistant_request (src/core/assistant.py) is the single public entrypoint used by all adapters and the golden E2E test.

Architecture

One Python process. Three layers:

Layer Path Role
Adapter telegram_bot/ Telegram interface β€” converts messages to/from AssistantRequest / AssistantResult
Public boundary src/core/ contracts.py defines Protocol-based DI types; assistant.py is the entrypoint
Engine src/runtime/ Pipeline, RAG, retrieval, generation, grounding

External sidecar services (Docker Compose β€” not part of the Python binary):

Service Purpose
Qdrant Vector store β€” dense, sparse, and ColBERT-style retrieval
BGE-M3 (ONNX) Self-hosted embeddings served via a local API
Redis Five independent caches: semantic answer, embedding, search, rerank, extraction. Version-prefixed keys; graceful degradation on miss
PostgreSQL Persistent state (conversation, ingestion tracking)

An optional LangGraph supervisor + tool-routing layer exists in telegram_bot/agents/ for CRM-style workflows (lead scoring, manager handoff, HITL confirmation). It is not required for the core Q&A path.

Ingestion

src/ingestion/unified/ β€” deterministic, idempotent, production-ready:

  • SHA256-based file identity: re-ingesting the same file is a no-op.
  • Idempotent upsert: changed files replace prior chunks by source path. Deleted source files are a known limitation β€” their chunks remain in Qdrant until manual cleanup.
  • Error handling: failed documents are logged and skipped; run_watch retries on the next polling cycle (60 s). No DLQ or exponential backoff β€” orphaned chunks from deleted source files remain in Qdrant until manual cleanup (known limitation).
  • Docling handles parsing in-process (native SDK, no HTTP sidecar); the unified pipeline handles chunking and embedding writes.

Adapt to Your Domain

Replace the domain layer; keep the engine and infrastructure.

Replaceable: telegram_bot/services/apartment_* prompts and extraction logic, search schema fields, CRM/tool integrations, UI copy, i18n strings.

Keep: src/core/, src/runtime/, src/ingestion/unified/, Redis cache layer, Docker Compose profiles.

The current domain (real-estate/apartments) lives entirely in the adapter and service layers. Swapping it does not require touching the retrieval engine or pipeline.

Quick Start

Prerequisites: Python 3.12+, uv, Docker with Compose.

Runtime: Docker Compose only. No k8s, no Mini App, no CRM/Kommo integration.

cp .env.example .env          # fill in credentials
make core-min-up              # start Qdrant + Redis (minimal)
# or
make core-up                  # start full sidecar stack (adds BGE-M3, PostgreSQL)

Run the bot natively:

make run-bot

Run the Compose bot stack:

make docker-bot-up

Notable configurable env vars (see .env.example): QDRANT_QUANTIZATION_MODE, REDIS_MAX_CONNECTIONS.

Validation

make check          # Ruff lint + MyPy type checking (non-strict; disallow_untyped_defs=false)
make test-core      # Fast core gate (~91 tests, ~8s) β€” run first for any src/core or src/runtime change
make test           # Broader fast gate (unit + graph paths) β€” run for adapter/service changes
make e2e-core-live  # Golden E2E: indexes fixture corpus, runs full spine through run_assistant_request
make qdrant-audit-indexes  # Audit Qdrant payload indexes

make e2e-core-live is the main proof of the core path. It exercises classification, retrieval, generation fallback, and runs without Telegram or voice. It requires local Qdrant and BGE-M3 running (make core-up).

CI runs static/lint guardrails only (Ruff, MyPy, Semgrep, lockfile check). Pytest suites are local/manual.

Honest Current State

The core pipeline (src/core/ + src/runtime/) is healthy and well-tested. The following surfaces are physically in-tree but are archived/reference β€” not part of the active production path, and being trimmed in open issues:

  • LangGraph dead nodes β€” some graph nodes are no longer on the live execution path but remain in the file tree.

Langfuse removed β€” Langfuse SDK and tracing are fully removed (no from langfuse imports anywhere). The @observe decorators that remain are local no-op shims (src.observability / telegram_bot.observability) β€” not tracing. Observability is through structured logs.

The active production adapter is Telegram (telegram_bot/). Voice input is active via telegram_bot/dialogs/ (catalog and demo dialogs).

Project Map

Area Path
Core entrypoint src/core/assistant.py
Pipeline + RAG engine src/runtime/pipeline/
Telegram adapter telegram_bot/
Domain tools + agents telegram_bot/agents/, telegram_bot/services/
Unified ingestion src/ingestion/unified/
Compose runtime compose.yml, DOCKER.md

Documentation

Document Use it for
DOCKER.md Compose services, profiles, ports, env, runtime contracts

Direction

The project is being hardened to a senior-grade codebase without dropping any feature β€” tracking epic #2983. In short: keep the full feature menu, remove migration cruft (dead LangGraph nodes, stale tests), decompose the bot.py god-object into per-feature handlers, document the feature map, and freeze the entry-path contracts β€” with no new frameworks and no over-engineering.

License

This project is licensed under the MIT License.

About

AI real-estate automation platform: Telegram bot, RAG, apartment search, CRM workflows, voice agent, Langfuse observability, and Dockerized AI runtime.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

10 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages