Files
duocthu/docs-legacy/README.md
T

213 lines
9.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Documentation
Reverse-engineered from the code in this repository. Every claim here traces to
a file, a command, or an artifact on disk — see
[DOCUMENTATION_PLAN.md](DOCUMENTATION_PLAN.md) for the method and for what was
not verified.
## Chọn tài liệu theo việc bạn cần làm
Bộ tài liệu dùng cấu trúc Diataxis: mỗi trang ưu tiên một nhu cầu của người đọc
thay vì cố dạy, hướng dẫn thao tác, liệt kê reference và giải thích kiến trúc
trong cùng một trang.
### Học qua thực hành — Tutorial
- [Theo một câu hỏi từ API đến trang PDF nguồn](tutorials/first-grounded-query.md)
### Hoàn thành một tác vụ — How-to
- [Local development](23-local-development.md)
- [Rebuild và publish corpus](how-to/rebuild-and-publish-corpus.md)
- [Chạy test và evaluation](how-to/run-tests-and-evals.md)
- [Deploy và rollback production](how-to/deploy-and-rollback.md)
- [Lần một request từ người dùng đến evidence](how-to/trace-a-request.md)
- [Production operations](24-production-operations.md)
- [Troubleshooting](25-troubleshooting.md)
### Tra cứu dữ kiện — Reference
- [Catalog toàn bộ tài liệu](reference/documentation-catalog.md)
- [Repository structure](01-repository-structure.md)
- [API contracts](12-api-architecture.md)
- [Configuration](15-configuration.md)
- [Observability signals](17-observability.md)
- [Known limitations](26-known-limitations.md)
- [Glossary và reason codes](29-glossary.md)
### Hiểu thiết kế — Explanation
- [Pipeline canonical từ PDF đến chatbot](pipeline-tu-pdf-den-chatbot-production.md)
- [Vì sao dùng structured RAG](explanation/why-structured-rag.md)
- [System architecture](02-system-architecture.md)
- [Query understanding](08-query-understanding.md)
- [Retrieval pipeline](09-retrieval-pipeline.md)
- [Generation and grounding](11-generation-and-grounding.md)
- [Audit kiến trúc tài liệu](diataxis-audit.md)
## What this system is
A Vietnamese-language question-answering system over the **Dược thư Quốc gia
Việt Nam 2018** (Vietnamese National Drug Formulary), for doctors and
pharmacists. A user asks a drug question in Vietnamese; the system resolves what
was asked, retrieves the exact monograph section from a vector store, has an LLM
restate it, verifies that restatement against the retrieved text, and returns it
with printed-page citations — or refuses.
Two things distinguish it from a generic RAG app, and both are enforced in code:
- **Retrieval decides what is true; generation only decides how it reads.** A
generated answer is discarded unless every number in it appears verbatim in
the specific evidence block it cites (`rag/grounding.py`) *and* a second LLM
pass confirms the cited block actually says it (`rag/answer.py`).
- **Tables and formulas are quarantined, not linearised.** Content whose numbers
could not be reliably reconstructed from the PDF is never embedded as prose
and never restated; it is surfaced as "check the source page".
Scope boundary: the corpus is **Part 2 monographs only** (printed pages
991496). Part 1 general chapters and Part 3 appendices are not ingested.
## Architecture at a glance
```mermaid
flowchart LR
U[Clinician<br/>browser]
CADDY[Caddy 2<br/>TLS + reverse proxy]
WEB["web — Next.js 14<br/>chat UI + BFF routes<br/>+ in-memory rate limit"]
AI["ai-service — FastAPI<br/>RagAgent orchestrator"]
QD[("Qdrant<br/>duocthu_v1<br/>15,100 points")]
PG[("PostgreSQL 16<br/>traces · turns · feedback")]
BR["AWS Bedrock<br/>Cohere embed-v4 · Cohere rerank<br/>Converse generation"]
ING["ingestion — offline batch<br/>PDF → chunks → vectors"]
PDF[/"duoc-thu-quoc-gia-viet-nam-2018.pdf"/]
U --> CADDY --> WEB --> AI
AI --> QD
AI --> PG
AI --> BR
PDF --> ING --> QD
ING --> BR
```
The `api-gateway`, `auth-service`, `user-service` and `chat-service` directories
in `apps/` contain **only** a `README.md` and a `package.json`. There is no
gateway, no authentication and no chat-service in the request path; `web` calls
`ai-service` directly. See [02-system-architecture.md](02-system-architecture.md).
## Main technology stack
| Layer | Technology | Evidence |
|---|---|---|
| Frontend | Next.js 14 (App Router), React 18, Tailwind, framer-motion | `apps/web/package.json` |
| Backend | Python 3.12, FastAPI, Pydantic Settings, uvicorn | `apps/ai-service/pyproject.toml`, `Dockerfile` |
| Vector store | Qdrant (cosine, 1024-d) | `adapters/qdrant.py`, `ingestion/load/` |
| Relational | PostgreSQL 16 (`psycopg` 3) | `adapters/postgres.py`, `migrations/` |
| Embedding | `cohere.embed-v4:0` on AWS Bedrock | `adapters/embedding.py`, `ingestion/embed/bedrock_cohere.py` |
| Generation | Bedrock Converse API (model id is config) | `adapters/bedrock_converse.py` |
| Rerank | `cohere.rerank-v3-5:0` on Bedrock | `adapters/bedrock_converse.py` |
| PDF parsing | PyMuPDF (`fitz`), pdfplumber for tables only | `ingestion/extract/`, `ingestion/tables/` |
| Observability | Prometheus, OpenTelemetry → OTel Collector → Tempo, Grafana | `rag/telemetry.py`, `infra/docker/` |
| Runtime | Docker Compose on a single EC2 host, Caddy for TLS | `infra/docker/docker-compose.prod.yml` |
| Monorepo | pnpm workspaces + Turborepo (JS side only) | `pnpm-workspace.yaml`, `turbo.json` |
No RAG framework is used. There is no LangChain and no LlamaIndex anywhere in
the dependency set — the orchestration is hand-written in `rag/agent.py`.
## Core runtime services
| Service | Language | Entrypoint | Port |
|---|---|---|---|
| `ai-service` | Python | `apps/ai-service/main.py``app` | 8000 |
| `web` | TypeScript | `apps/web/app/` (Next.js) | 3000 |
| `caddy` | — | `infra/docker/Caddyfile` | 80/443 |
| `ingestion` | Python | `python -m ingestion.cli`, `python -m ingestion.load.run` | offline, no port |
## Main data stores
| Store | Holds | Live-path role |
|---|---|---|
| Qdrant `duocthu_v1` | 15,100 chunk points + payload | Every retrieval |
| Qdrant `duocthu_v1__manifest` | One point: corpus sha, model id, dimensions | Startup gate (`bootstrap.py`) |
| PostgreSQL | `rag_retrieval_trace`, `rag_conversation_turn`, `rag_answer_feedback` | Traces + multi-turn history; both fail-open |
| Local disk | `chunks.jsonl`, `monographs.jsonl`, embedding cache | Offline pipeline only |
Redis appears in `infra/docker/docker-compose.yml` (local dev) and in the
pre-existing architecture document. **Nothing in the codebase imports a Redis
client.** It is not deployed in production and not read or written by any code.
## Main pipelines
The single canonical, end-to-end explanation is
[pipeline-tu-pdf-den-chatbot-production.md](pipeline-tu-pdf-den-chatbot-production.md).
The numbered pages below remain the component-level reference.
For a concise demonstration of the changes delivered from 31/07 to 14/08/2026,
use [ke-hoach-showcase-cai-tien-2-tuan.md](ke-hoach-showcase-cai-tien-2-tuan.md).
1. **Ingestion (offline)** — PDF → spans → monographs → chunks → embeddings →
Qdrant. Seven CLI subcommands plus a separate embed/load entrypoint. Has
already been run; re-running the embed step costs real Bedrock spend.
→ [04-ingestion-pipeline.md](04-ingestion-pipeline.md)
2. **Query (live)** — HTTP → understanding LLM call → deterministic route →
Qdrant retrieval → generation LLM call → deterministic grounding →
entailment LLM call → citations → response.
→ [10-rag-orchestration.md](10-rag-orchestration.md)
## Documentation map
**Start here, in order:**
1. [00-project-overview.md](00-project-overview.md) — problem, users, boundaries
2. [02-system-architecture.md](02-system-architecture.md) — components and what is *not* built
3. [03-data-flow.md](03-data-flow.md) — the two end-to-end flows in one page
**For AI/RAG engineers:**
[08-query-understanding.md](08-query-understanding.md) →
[09-retrieval-pipeline.md](09-retrieval-pipeline.md) →
[10-rag-orchestration.md](10-rag-orchestration.md) →
[11-generation-and-grounding.md](11-generation-and-grounding.md) →
[19-rag-evaluation.md](19-rag-evaluation.md).
For the corpus itself: [04](04-ingestion-pipeline.md) →
[05](05-document-parsing.md) → [06](06-document-model-and-chunking.md) →
[07](07-indexing-and-storage.md).
**For backend engineers:**
[12-api-architecture.md](12-api-architecture.md) →
[14-data-stores.md](14-data-stores.md) →
[15-configuration.md](15-configuration.md) →
[18-testing.md](18-testing.md) →
[23-local-development.md](23-local-development.md).
**For frontend engineers:**
[13-frontend-architecture.md](13-frontend-architecture.md) →
[12-api-architecture.md](12-api-architecture.md) (the response contract) →
[16-security.md](16-security.md) (rate limiting lives in the frontend today).
**For DevOps/SRE:**
[20-deployment.md](20-deployment.md) →
[22-ci-cd.md](22-ci-cd.md) →
[17-observability.md](17-observability.md) →
[24-production-operations.md](24-production-operations.md) →
[25-troubleshooting.md](25-troubleshooting.md) →
[21-kubernetes-and-argocd.md](21-kubernetes-and-argocd.md) (unapplied target state).
**For QA:**
[18-testing.md](18-testing.md) →
[19-rag-evaluation.md](19-rag-evaluation.md) →
[26-known-limitations.md](26-known-limitations.md).
**Before planning work:**
[26-known-limitations.md](26-known-limitations.md) →
[27-technical-debt.md](27-technical-debt.md) →
[28-roadmap-from-code.md](28-roadmap-from-code.md).
Terms: [29-glossary.md](29-glossary.md).
## Historical and empirical documents
`architecture.md`, `progress-log.md`, `pdf-parsing-outlier-catalog.md`,
`document-profile.md`, and the ADRs predate the numbered set. They are retained
only for decision history and empirical PDF measurements. Completed plans and
superseded audits were removed; they are not current-state references.