基于 FastAPI、React 和 Milvus 的本地知识库问答系统,提供文档摄取、流式回答、引用溯源和独立纯检索接口,并通过文档生命周期与离线评测约束数据一致性和能力变更。
适用于本地单用户或可信私网。Web 问答默认使用 Dense,可选质量优先模式在 Dense 候选上本地重排;纯检索 API 仍为 Dense-only。不提供公网认证、多租户隔离或高可用承诺。
- 文档管理:支持 PDF、DOCX、TXT,内容哈希持久化、幂等摄取、索引版本及 active 原子切换。
- 交互式问答:React 工作台通过 SSE 展示生成过程、引用来源和中断状态,支持本地对话记录。
- 可选质量优先(实验):Web 问答可用本地 Cross-Encoder 重排 Dense 候选;需先准备模型,等待可能更久且不保证每题更好。历史
qmv3-replacement独立 one-shot 曾未通过 MRR@3 与 nDCG@3 质量门槛,因此不宣称普遍质量提升;2026-09-26 的 C4 独立题集在固定 K=4、CPU、本地模型和 retrieval-through-sources 口径下通过冻结门禁,适用范围仅限该题集与配置。 - 机器检索接口:
POST /api/v1/retrieve返回指定文档的原始 Chunk,不调用生成模型;固定 Schema1.0、dense-v1。 - 可靠性:依赖探活;纯检索执行具备有界超时、重试、进程内并发限制及失效索引校验。
- 可观测性:结构化 JSONL 日志、Prometheus Metrics、可选 OpenTelemetry Tracing 与凭据脱敏。
- 质量验证:确定性 CI 回归门禁,以及独立的检索、答案质量和增强方案对照评测。
flowchart LR
UI[React 工作台] --> API[FastAPI]
API --> DOC[文档生命周期]
DOC --> REG[SQLite Registry]
DOC --> EMB[Embedding]
EMB --> VEC[Milvus]
API --> QUERY[纯检索服务]
QUERY --> REG
QUERY --> RET[Retriever]
RET --> VEC
API --> CHAT[SSE 问答服务]
CHAT --> RET
RET --> MODE{问答模式}
MODE -->|标准| GEN[RAGGenerator]
MODE -->|质量优先| RERANK[本地 Cross-Encoder]
RERANK --> GEN
GEN --> LLM[配置的 LLM Provider]
Milvus Standalone 的 etcd、MinIO 由 Compose 编排;Ollama 和生成模型服务不包含在这组容器内。详细模块职责见架构说明。
当前源码使用 3.1.1 版本标识;这是本轮源码候选,尚不代表已发布 Release。新版统一采用 React/FastAPI/Milvus,不再提供 Gradio 启动入口;应用相对路径和默认环境文件以项目根为基准。旧版用户先阅读3.0.0 迁移说明。纯检索 Schema 仍为 1.0,dense-v1 不变。
3.1.1 的版本范围见版本演进,可选重排的冻结指标见质量模式评测。此前 3.1.0 的源码与依赖记录保留在历史检查记录,不代表当前提交已经发布。
旧架构入口为 v1.7.1(Chroma/Gradio),需要时检出对应标签并使用该快照的说明。源码版本标识不等于 GitHub Release 已发布;实际发布以对应标签与发布页为准。
| 场景 | 需要准备 |
|---|---|
| Compose 运行 | Docker Engine / Docker Desktop + Compose;可访问的 Embedding 与 LLM Provider |
| 默认 Embedding | 本机 Ollama 已运行,并安装 qwen3-embedding |
| 本地开发 | Python 3.11、Node.js 22,以及运行中的 Milvus |
| 离线回归测试 | 安装开发依赖;确定性测试不需要真实模型或数据库 |
Python 直接依赖见 requirements.txt,前端使用 package-lock.json;另提供已验证 Python 3.11 容器环境的 requirements.lock 快照。安装与可复现性边界见依赖说明。
以下命令使用 PowerShell,默认从仓库根目录执行。
if (-not (Test-Path .env)) { Copy-Item .env.example .env }
ollama pull qwen3-embedding先确认 Ollama 服务可用;需要手动启动时,在单独终端运行 ollama serve。使用本地模型生成时,在本地 .env 设置 DEFAULT_LLM_PROVIDER=ollama;模型由 OLLAMA_CHAT_MODEL 选择,OLLAMA_CHAT_NUM_GPU=0 可强制 CPU。不要将真实配置提交到 Git。Compose 会通过宿主机 Ollama 地址访问该服务。
默认生成 Provider 为 OpenAI,因此 Web 问答并非默认完全离线。纯检索不调用生成模型,但仍依赖 Embedding、Milvus 和有效文档索引。
docker compose up -d --build
docker compose ps
Invoke-RestMethod http://127.0.0.1:8001/api/v1/health/live
Invoke-RestMethod http://127.0.0.1:8001/api/v1/health/ready| 入口 | 默认地址 |
|---|---|
| React 工作台 | http://127.0.0.1:5173 |
| API / Swagger | http://127.0.0.1:8001/docs |
| Metrics | http://127.0.0.1:8000/metrics |
| Milvus | 127.0.0.1:19530 |
打开工作台,上传文档,等待索引进入 active 状态,再进行问答或调用检索接口。live 只表示进程存活;ready 才反映依赖状态。若生成服务不可用但 components.retrieval=ready,可使用纯检索,不能据此认为问答可用。
容器默认通过 host.docker.internal:11434 访问宿主机 Ollama。Embedding 默认有 600 秒有界驻留和独立的 60 秒 readiness 冷加载窗口;遇到首次探活失败、端口冲突或资源不足,参见运行与故障处理。
docker compose stopdocker compose down 可移除容器和网络并保留命名卷。不要在需要保留知识库时使用 down -v。本地开发的 API 与前端启动步骤见运行说明。
| 位置 | 职责 |
|---|---|
app/ / frontend/ |
后端与前端源码 |
tests/ / frontend/e2e/ |
后端测试与浏览器流程测试 |
data/ |
注册表及上传文件;内容不提交 |
logs/ / artifacts/ |
日志与新生成的验证报告;内容不提交 |
evaluation/ |
固定数据集、基线、评测工具和历史证据 |
_private/ |
可选的本地私人资料目录,Git/Docker 均排除 |
默认 .env 和相对应用数据/日志路径以项目根解析;绝对路径覆盖继续有效。配置加载不创建文件,启动时准备必要目录。Docker 使用现有 /app/data、/app/logs 持久化位置,不会因更换终端目录自动迁移数据。
data、logs、artifacts 仅跟踪目录占位规则。明确传给评测 CLI 的相对输入/输出仍按调用者工作目录解释,绝对路径保持原位置。完整职责见项目结构。
在安装开发依赖的 Python 环境中执行:
python -m pytest -q
python -m evaluation.runner --output-json artifacts/evaluation/current.json --output-markdown artifacts/evaluation/current.md
python -m evaluation.regression_runner --baseline evaluation/baselines/deterministic_dense_v2.json --current artifacts/evaluation/current.json确定性检索使用固定数据、哈希 Embedding 和内存向量存储,不需要真实 Provider。真实 Milvus 集成有单独的显式开关;不要把默认测试通过解释为真实依赖或最终生产部署已通过。前端与完整检查命令见运行说明。
C4 新冻结题集 quality_mode_v3_c4_20260925 的 Cross-Encoder K=4 通过 retrieval-through-sources 门禁:MRR@3 delta +0.1528、nDCG@3 delta +0.1164、Recall@3 不下降、可回答题重排成功率 95.83%、warm P95 2306.749 ms。该报告不包含生成回答质量评分;旧 qmv3-replacement 失败记录仍然有效。详见 质量模式评测报告;运行配置与回退规则见 质量模式说明。
| 证据 | 结论与边界 |
|---|---|
| DS-06 检索对照 | 75 份合成代表性文档、235 Chunk,validation/holdout 各 50 题。Reranker 的 MRR@3 从 0.3018 提升至 0.4459,但 P95 从 170.25 ms 增至 1102.93 ms,超出预设延迟门禁,因此不替换 Dense 主线。 |
| 结构化上下文候选 | 固定工程文档题集、真实 qwen3-embedding、跨文档候选池;完整证据单元 Recall@3 未提升,开发集 MRR@3 从 0.7609 降至 0.7029;候选未采用,标准模式和纯检索仍使用 Dense。final 为已曝露集合复核,不是未接触 holdout。 |
| 答案质量对照 | 历史报告暴露拒答和统一引用等限制;检索命中不等于回答正确,不能宣称任意模型或用户文档都达到相同质量。 |
| ScholarTrace 联调 | 已有对应基线的真实上传/检索与 Evidence 校验记录;证明限定条件下的接口集成,不代表当前版本的独立部署验收或大规模吞吐。 |
详见DS-06 决策、评测文档和历史交付证据。数据集、指标、报告日期与依赖配置是证据的一部分,不将旧报告伪装成当前版本的新测试结果。
- 文档摄取同步执行;没有后台任务队列、租户鉴权或高可用部署保证。
- Web 标准模式与公共纯检索接口保持 Dense;质量优先是 Web 问答的可选 Cross-Encoder 重排模式。BM25、Hybrid、Rewrite 仍是离线实验能力。
/retrieve要求一个document_key和匹配的expected_index_id;不提供跨文档批量、结果缓存或 MCP 接口。- L2 阈值与 Embedding 空间、语料相关,没有可靠通用默认阈值;保留拒答和引用质量的已知限制。
- 不可信上下文隔离及测试不等于全面安全保证;不要直接暴露到公网。
- Prometheus、Grafana、Jaeger、Collector 等外部可观测性后端不在当前 Compose 中。
| 文档 | 内容 |
|---|---|
| 架构说明 | 模块依赖、文档/索引不变量、服务边界 |
| 运行与故障处理 | 本地/容器启动、检查、维护与停止 |
| 质量优先模式 | 本地模型准备、请求状态、回退与验证范围 |
| 项目结构 | 源码、测试、运行产物的归属 |
| 依赖说明 | 安装方式与依赖锁定边界 |
| 纯检索 API | 请求、响应、错误码、资源控制 |
| ScholarTrace 接入 | Consumer 流程及兼容边界 |
| 评测文档 | 当前回归操作与按版本归档的实验记录 |
| 可观测性 | 日志、指标、Trace 与隐私约束 |
| 版本演进 | 主要架构节点与历史版本差异 |
| 3.0.0 迁移 | 入口、配置与路径兼容变化 |
当前源码说明与历史标签是不同入口;需要旧架构时应检出对应标签,使用该快照自带的依赖和说明。不要将历史发布记录视为任意当前工作树已经发布的证明。