KingIAsk 是一个面向 KF 产品使用手册的企业级 RAG 问答助手。它会从 data/help 加载手册文档,构建本地 Chroma 向量库,再通过 DeepSeek 生成带资料来源和相关图片的回答。
当前版本优先保证本地轻量可运行,同时保留企业级产品需要的接口、配置、健康检查、评测中心和压测入口。
- 加载 Markdown 和 HTML 手册文档。
- 保留文档中的图片位置,并在回答来源中返回相关图片路径。
- 使用
BAAI/bge-small-zh-v1.5在本地生成 embedding。 - embedding 模型按需懒加载,无变化索引检查不会加载重量级模型。
- 使用 Chroma 持久化向量库,默认目录为
storage/chroma。 - 使用 DeepSeek 生成最终回答。
- 支持向量检索和关键词召回混合排序。
- 支持资料来源去重、证据编号、图片数量限制和拒答保护。
- 提供 FastAPI 问答接口、KingIAsk Vue 前端和 Streamlit 轻量 Demo 页面。
- 提供索引状态、就绪检查、评测中心、评估脚本和轻量压测脚本。
backend/ FastAPI RAG 后端,包含 API、RAG 核心代码、评测系统、脚本和测试
frontend/ KingIAsk 前端工作台(Apple 风格,推荐)
frontend-legacy/ 旧版 KingIAsk Vue 前端工作台(已弃用,仅存档)
data/ KF 产品手册原始文档,本地放置,不提交仓库
storage/ Chroma 向量库和增量索引清单,本地生成,不提交仓库
docs/evaluation/ RAG 评测中心使用说明
docs/ 本地学习和设计文档,不提交仓库
.env.example 可提交的环境变量样例
.env 本地真实配置,不提交仓库
建议使用独立 conda 环境,避免污染 base 环境。
conda create -n kf-rag python=3.11 -y
conda activate kf-rag
cd backend
pip install -r requirements.txt
cd ..
cp .env.example .env编辑 .env,至少填写:
DEEPSEEK_API_KEY=你的 DeepSeek API Key
第一次构建索引时会加载 embedding 模型。如果本机没有缓存,需要能访问 HuggingFace 或提前准备好模型缓存。
前端使用 Vue 3、Vite 和 npm。进入 frontend/ 后安装依赖:
cd frontend
npm install如果你习惯 pnpm,也可以使用 pnpm install 和 pnpm run dev;本项目新前端默认使用 npm。
第一次运行时,先准备手册和索引:
mkdir -p data/help storage/chroma storage/processed把 KF 手册放入:
data/help/
然后构建向量索引:
cd backend
python -m scripts.build_index索引构建完成后,启动后端 API:
cd backend
uvicorn app.main:app --reload再启动前端:
cd frontend
npm run dev浏览器打开:
http://127.0.0.1:5174
.env.example 已列出项目用到的配置。常用配置如下:
APP_ENV=local
DISABLE_AUTH=true
APP_API_KEY=
CORS_ALLOWED_ORIGINS=http://127.0.0.1:5174,http://localhost:5174
DEEPSEEK_API_KEY=
DEEPSEEK_BASE_URL=https://api.deepseek.com
DEEPSEEK_MODEL=deepseek-v4-flash
DEEPSEEK_TIMEOUT_SECONDS=60
EMBEDDING_MODEL_NAME=BAAI/bge-small-zh-v1.5
DATA_DIR=data/help
CHROMA_PERSIST_DIR=storage/chroma
INDEX_MANIFEST_PATH=storage/processed/index_manifest.json
CHUNK_SIZE=700
CHUNK_OVERLAP=100
TOP_K=5
MAX_IMAGES_PER_SOURCE=5
MAX_IMAGES_PER_ANSWER=8
KF_RAG_API_URL=http://127.0.0.1:8000/api/chat
EVALUATION_DB_PATH=storage/evaluation/kingiask_eval.db
EVALUATION_CASES_PATH=backend/evaluation_cases/eval_questions.json
EVALUATION_DIALOGUES_PATH=backend/evaluation_cases/eval_dialogues.json
EVALUATION_FAIL_UNDER=0.8
EVALUATION_MAX_P95_MS=30000
TOP_K 表示每次问答检索多少个相关 chunk。值越大,可用资料越多,但大模型上下文更长、速度可能更慢。
MAX_IMAGES_PER_SOURCE 控制每个来源最多返回多少张图片;MAX_IMAGES_PER_ANSWER 控制一次回答最多返回多少张图片。
CHUNK_SIZE 是每个知识片段的目标字符数,CHUNK_OVERLAP 是相邻片段的重叠字符数。必须满足 0 <= CHUNK_OVERLAP < CHUNK_SIZE。
把 KF 产品手册放到:
data/help/
data/ 已在 .gitignore 中忽略,手册文件不会被提交到远程仓库。
如果后续手册更新,只需要重新运行 python -m scripts.build_index。系统会对比文档哈希,只处理新增、修改和删除的文件。
cd backend
python -m scripts.build_index构建流程是:
扫描 data/help 并计算 SHA-256
-> 对比 storage/processed/index_manifest.json
-> 只加载新增或修改的文档
-> 清洗、保留图片位置并切分
-> 只为变化 chunks 生成 embedding
-> 同步更新 Chroma 和索引清单
服务启动不会自动重新 embedding。python -m scripts.build_index 默认执行增量更新:内容没有变化的文档会直接跳过,不调用 embedding,也不会重写 manifest;新增、修改和删除的文档会同步到 Chroma。
从不带 manifest 的旧版本第一次升级运行时,系统会自动执行一次全量重建来建立基线。以后再次运行就是增量更新。修改了 embedding 模型或分块规则时,使用下面的命令强制全量重建:
cd backend
python -m scripts.build_index --full全量重建开始前会写入恢复标记。若 embedding 或 Chroma 写入中途失败,下一次默认构建会自动再次执行全量恢复,不会被旧 manifest 误判为“文档没有变化”。如果 data/help 不存在或没有可索引文档,构建会直接终止,不修改已有向量库,避免服务器挂载错误清空知识库。
manifest 同时保存索引配置指纹。embedding 模型、CHUNK_SIZE、CHUNK_OVERLAP 或内部文档处理版本变化时,系统会自动执行一次全量重建;配置不变时继续复用增量索引。旧版本 manifest 没有指纹时也会自动完成一次升级,无需手动删除向量库。
开发环境推荐:
cd backend
uvicorn app.main:app --reload也可以显式指定地址和端口:
cd backend
uvicorn app.main:create_app --factory --host 127.0.0.1 --port 8000 --reload接口地址:
http://127.0.0.1:8000
后端还会把 DATA_DIR 中的手册静态资源挂载到:
http://127.0.0.1:8000/manuals/<手册内相对路径>
问答接口返回的图片路径仍然保持为手册相对路径,例如 html/xxx/1.png。KingIAsk 前端会自动把它转换为 /manuals/html/xxx/1.png,所以用户点击证据图片时可以直接预览原始手册截图。
先启动 API 服务,再运行:
cd frontend
npm install
npm run dev默认访问地址:
http://127.0.0.1:5174
如果后端地址不是 http://127.0.0.1:8000,可以在前端页面右上角设置里修改 API 地址。前端会把设置保存到浏览器本地存储,刷新页面后继续复用。
如果页面显示“后端未连接”,先确认后端服务已经启动,并检查 .env 中的 CORS_ALLOWED_ORIGINS 是否包含当前前端地址,例如 http://127.0.0.1:5174。
先启动后端和前端,然后打开:
http://127.0.0.1:5174
点击顶部“评测中心”,可以查看用例、运行评测、查看报告详情和最近两次运行对比。
评测用例目录:
backend/evaluation_cases/
评测运行结果默认保存到:
storage/evaluation/kingiask_eval.db
更详细说明见:
docs/evaluation/README.md
旧版前端已更名为
frontend-legacy/,仅作存档,不再维护。
服务器上建议使用 Docker Compose 固定运行环境。先准备配置和目录:
cp .env.example .env
mkdir -p data/help storage/chroma storage/processed把 KF 手册放入:
data/help/
生产环境建议在 .env 中至少设置:
APP_ENV=production
DISABLE_AUTH=false
APP_API_KEY=自定义内部访问密钥
DEEPSEEK_API_KEY=生产可用的 DeepSeek Key
DATA_DIR=data/help
CHROMA_PERSIST_DIR=storage/chroma
INDEX_MANIFEST_PATH=storage/processed/index_manifest.json
构建镜像:
docker compose builddocker-compose.yml 会使用 ./backend 作为后端镜像构建上下文,实际读取的是 backend/Dockerfile 和 backend/.dockerignore。
第一次部署或手册更新后,先构建向量索引:
docker compose run --rm kf-rag-api python -m scripts.build_index启动服务:
docker compose up -d查看日志:
docker compose logs -f kf-rag-api停止服务:
docker compose downdocker-compose.yml 默认挂载:
./data/help -> /app/data/help:ro
./storage -> /app/storage
手册目录用只读挂载,整个 storage 目录用可写挂载,让 Chroma 和增量索引清单一起持久化。这样升级镜像时,手册和索引数据仍然留在服务器磁盘上。
存活检查只判断服务进程是否正常:
curl http://127.0.0.1:8000/api/health预期返回:
{"status":"ok"}就绪检查判断系统是否具备真实问答条件:
curl http://127.0.0.1:8000/api/health/ready它会检查:
DEEPSEEK_API_KEY是否配置。- 生产环境是否关闭了免认证。
- 向量库索引是否已经构建。
如果未就绪,会返回 503 和 issues 列表,按提示处理即可。
curl http://127.0.0.1:8000/api/index/status返回示例:
{
"status": "ready",
"chunks": 6291,
"documents": 2275,
"last_built_at": "2026-07-21T02:00:00+00:00",
"index_signature": "当前索引配置指纹",
"current_signature": "当前运行配置指纹",
"config_matches": true,
"rebuild_pending": false,
"persist_dir": "storage/chroma",
"manifest_path": "storage/processed/index_manifest.json",
"issue": null
}last_built_at 来自 manifest 的最后修改时间。无变化的增量检查不会刷新它,因此它表示最近一次真实索引更新,而不是最近一次执行命令的时间。
status 可能是:
ready:向量库非空,manifest 与当前 embedding、分块配置一致,可以正常问答。empty:向量库为空,需要先构建索引。stale:已有索引与当前配置不一致,需要重新构建。rebuild_required:检测到上一次全量重建中断,需要再次构建以恢复完整索引。error:manifest 损坏,查看issue并执行全量重建。
手册更新后,可以通过接口执行默认增量更新:
curl -X POST "http://127.0.0.1:8000/api/index/rebuild"修改 embedding 模型或分块规则后,可以强制全量重建:
curl -X POST "http://127.0.0.1:8000/api/index/rebuild?full=true"接口会返回 added_documents、modified_documents、deleted_documents、skipped_documents、written_chunks 和 total_chunks。
同一服务进程一次只允许一个索引任务。已有任务运行时,重复请求会返回 409;当前 Docker 配置使用单 Uvicorn 进程,多 worker 或多副本部署需要额外配置跨进程索引锁。
本地默认 DISABLE_AUTH=true,可以直接调用:
curl -X POST "http://127.0.0.1:8000/api/chat" \
-H "Content-Type: application/json" \
-d '{"question":"如何创建采集工程?"}'返回结构:
{
"answer": "回答内容",
"sources": [
{
"title": "来源标题",
"source_path": "html/...",
"snippet": "命中的手册片段",
"evidence_ids": ["资料 1"],
"images": ["html/.../1.png"],
"score": 0.5
}
]
}如果手册中没有可靠依据,系统会返回固定拒答:
{
"answer": "手册中没有找到相关说明。",
"sources": []
}请求方式:
POST http://127.0.0.1:8000/api/chat
Headers:
Content-Type: application/json
Body 选择 raw 和 JSON:
{
"question": "如何创建采集工程?"
}如果开启了接口认证,还需要增加:
x-api-key: 你的 APP_API_KEY
Streamlit Demo 是轻量验证页面,正式体验建议优先使用 KingIAsk 前端。先启动 API 服务,再运行:
cd backend
streamlit run demo/streamlit_app.py默认 Demo 会调用:
http://127.0.0.1:8000/api/chat
如果 API 地址不同,可以在 .env 中修改:
KF_RAG_API_URL=http://你的服务地址/api/chat
cd backend
python -m scripts.ask "页面编辑器主要包括哪些区域?"这个脚本适合不打开 Demo 时快速验证问答效果。
评估集位于:
backend/evaluation_cases/eval_questions.json
运行评估:
cd backend
python -m scripts.evaluate
python -m scripts.evaluate --output ../storage/reports/evaluation.json评估脚本会检查回答关键词、来源关键词、拒答行为和图片返回数量,并输出总通过率以及各规则通过率。它不是最终人工验收标准,但能快速发现检索跑偏、回答缺关键点、该拒答时没有拒答等问题。存在失败题目时命令返回非零退出码,适合后续接入 CI;--output 可以保存结构化 JSON 报告。
更推荐的产品化方式是打开前端“评测中心”,在页面中运行评测、查看历史报告和最近两次结果对比。详细说明见 docs/evaluation/README.md。
如果某个问题回答不好,先看检索层找到了哪些 chunk:
python -m scripts.inspect_retrieval "如何创建采集工程?" --top-k 5这个脚本不会调用大模型,适合定位问题是在“资料没找对”,还是“资料找对了但回答生成不好”。
启动 API 后运行:
python -m scripts.load_test -n 10 -c 2
python -m scripts.load_test -n 5 -c 1 --output ../storage/reports/load-test.json参数含义:
-n:总请求数。-c:并发数。--question:压测使用的问题。--url:问答接口地址,默认读取KF_RAG_API_URL。--timeout:单请求超时时间,单位为秒。--api-key:可选的后端 API Key,通过X-API-Key请求头传递。--output:可选的 JSON 报告输出路径,不保存 API Key。
它会输出成功数、失败数、成功率、平均耗时、P50/P95/P99 耗时、状态码分布和吞吐量。性能测试会调用真实问答接口,可能产生 DeepSeek 费用,建议先用少量请求做冒烟测试。
部署到公司服务器时,建议至少调整:
APP_ENV=production
DISABLE_AUTH=false
APP_API_KEY=自定义内部访问密钥
DEEPSEEK_API_KEY=生产可用的 DeepSeek Key
CHROMA_PERSIST_DIR=/data/kf-rag/chroma
INDEX_MANIFEST_PATH=/data/kf-rag/processed/index_manifest.json
DATA_DIR=/data/kf-rag/help
生产调用接口时需要带请求头:
x-api-key: 自定义内部访问密钥
建议把 data/help 和整个 storage 挂载到服务器持久化目录,避免服务升级或容器重建后丢失手册、向量库和增量索引清单。
- 不要提交
.env。 - 不要把真实 API Key 写进 README、测试或日志。
data/和storage/默认不提交仓库。- 生产环境不要使用
DISABLE_AUTH=true。 - DeepSeek API 会收到用户问题和检索出来的手册片段。
不会。服务启动时只会读取已有的 Chroma 向量库。重新运行 python -m scripts.build_index 或调用索引接口时,也只会 embedding 新增或修改的文档;未变化文档直接复用已有向量,而且不会加载本地 embedding 模型。只有真正写入变化 chunks、执行向量检索,或传入 --full、full=true 时才会按需加载模型。
图片是绑定在命中的 chunk 上的。如果检索命中的 chunk 附近没有图片,回答就不会返回图片。系统不会为了展示图片而返回无关截图。
表示每次从知识库中选出 5 个最相关的 chunk 交给大模型。它影响资料覆盖范围、回答质量、速度和 token 消耗。
查看 issues 字段。常见原因是没有填 DEEPSEEK_API_KEY、没有构建索引,或生产环境还开着 DISABLE_AUTH=true。