# agentflow **Repository Path**: yunqiqwe/agentflow ## Basic Information - **Project Name**: agentflow - **Description**: 这是我自己写的agentfolow项目 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-06 - **Last Updated**: 2026-10-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # agentflow — RAG 知识库问答系统 基于 LlamaIndex 的**四级 Advanced RAG** 知识库问答系统。检索链路完整可评估、可调参,配套自建 LLM-as-Judge 评估脚本。 > 通用问答的痛点是"检索不准、答案不可信"——回答得像模像样,但引用不到原文,专有名词和编号经常检索不到,用户也不知道该不该信。agentflow 把检索链路拆成四级分别优化,并用评估数据驱动调参。 --- ## 核心特性 - **四级检索链路**:向量召回 + BM25 关键词召回 → RRF 融合 → 交叉编码精排 → 上下文压缩 - **知识库维度隔离**:每个知识库在 ChromaDB 中独立集合(`agentflow_kb_{kb_id}`),避免跨库串数据 - **可评估**:自建 LLM-as-Judge 评估脚本,按忠实度 / 相关性 / 召回 / 精度四维自动打分 - **防幻觉生成**:提示词"三铁律"约束(仅用上下文、禁止编造、无据则明说),回答附命中片段与来源 - **多格式文档解析**:PDF / Word / TXT,扫描件走 OCR 兜底 - **鉴权与权限隔离**:JWT + OAuth2PasswordBearer,知识库归属校验(管理员可查全部,普通用户仅限自己的) --- ## 四级检索链路 ``` 用户问题 │ ├─ ① 召回:向量检索 (top 10) ┐ │ BM25 关键词检索 (top 10) ┘ 双路并行 │ 向量管语义,BM25 管专有名词与编号 │ ├─ ② 融合:QueryFusionRetriever (RRF, num_queries=3) │ 多路结果合成一个排名,同时做查询改写 │ ├─ ③ 精排:bge-reranker-v2-m3 交叉编码重排 → Top 5 │ 粗召回后按问答相关性精排,提升精度 │ └─ ④ 压缩:SentenceEmbeddingOptimizer (percentile_cutoff=0.5) 按语义边界裁掉无关句子,省 token、提聚焦 │ ▼ qwen-plus 生成(compact 模式 + 三铁律提示词) │ ▼ 回答 + 命中片段 + 来源标注 ``` ### 每级为什么这么设计 | 阶段 | 关键参数 | 作用 | |---|---|---| | 召回 | `similarity_top_k=10` × 2 路 | 先把候选池做大,避免漏召回 | | 融合 | `num_queries=3`, `mode=reciprocal_rerank` | RRF 不看分数只看排名,避免两路分数量纲不可比 | | 精排 | `top_n=5` | 交叉编码精度高但慢,只对少量候选做 | | 压缩 | `percentile_cutoff=0.5` | 保留相似度高于中位数的句子 | **几个工程细节**: - reranker 单例懒加载,避免每请求重复加载模型 - 模型下载走 HuggingFace 镜像(`HF_ENDPOINT=https://hf-mirror.com`),国内网络可用 - 无独显时 `use_fp16=False` 走 CPU 推理 --- ## 技术栈 **后端**:Python · FastAPI · SQLAlchemy 2.x · MySQL · LlamaIndex · ChromaDB **AI**:DashScope `text-embedding-v3`(向量化)· `qwen-plus`(生成与裁判)· BM25 + jieba(关键词召回)· `bge-reranker-v2-m3`(精排) **文档解析**:PyMuPDF · python-docx · pypdf · RapidOCR **前端**:Vue3 · Vite · Element Plus · axios · vue-router --- ## 目录结构 ``` agentflow/ ├── README.md ├── requirements.txt # Python 依赖清单 ├── backend/ │ ├── main.py # FastAPI 入口,挂载 8 个路由 │ ├── evaluate_rag.py # LLM-as-Judge 评估脚本 │ └── app/ │ ├── router/ # 接口层 │ │ ├── auth.py # 注册 / 登录 / 冻结 / 用户管理 │ │ ├── knowledge.py # 知识库 CRUD │ │ ├── document.py # 文档上传 / 切分 / 删除 │ │ ├── document_list.py │ │ ├── cun.py # 向量化入库 │ │ ├── qu.py # 知识库问答(四级检索链路) │ │ ├── open.py # 召回接口 │ │ └── upload.py # 图片上传 │ ├── models/ # SQLAlchemy 模型(4 张表) │ ├── schemas/ # Pydantic 请求 / 响应结构 │ ├── db/ # 数据库连接 │ └── utils/ # JWT 与依赖注入 └── frontend/ # Vue3 + Element Plus ``` --- ## 快速开始 ### 1. 后端 在仓库根目录安装依赖: ```bash pip install -r requirements.txt ``` 在 `backend/.env` 中配置: ```env # 大模型与向量化 DASHSCOPE_API_KEY=your_dashscope_key SECRET_KEY=your_jwt_secret # 数据库(不配则用 app/db/mysql.py 里的默认值) DB_USER=root DB_PASSWORD=your_password DB_HOST=localhost DB_PORT=3306 DB_NAME=agent_db ``` 启动: ```bash cd backend python main.py # 或 uvicorn main:app --host 0.0.0.0 --port 8000 --reload ``` 接口文档:http://localhost:8000/docs ### 2. 前端 ```bash cd frontend npm install npm run dev ``` --- ## 评估 `backend/evaluate_rag.py` 是自建的 LLM-as-Judge 评估脚本:批量跑知识库问答,用 `qwen-plus` 当裁判按四维 rubric 打分。 **四个维度**: - `faithfulness` 忠实度 —— 答案是否完全基于检索上下文、无编造 - `relevancy` 相关性 —— 答案是否切题、真正解决了问题 - `recall` 召回 —— 检索上下文是否覆盖了回答问题所需的知识点 - `precision` 精度 —— 上下文中真正相关的占比 **用法**: ```bash cd backend python evaluate_rag.py --kb_id 5 --csv questions.example.csv ``` 测试集格式(CSV):`question,reference_answer,gold_doc_id` **验收标准**:综合分 ≥ 7.5 达标,任一维度不得低于 7.0。 ### 评估结果与调参过程 | 阶段 | 问题 | 综合分 | |---|---|---| | 初版 | 知识库缺关键文档,某题忠实度为 0 | 7.15 | | 调整 rerank | `top_n=3` 截断过狠,第 4~10 名的相关片段被直接丢掉 | 7.7 | | 补文档 + `top_n=5` | —— | **9.0** | 最终各维度:忠实度 **9.6** / 相关性 **9.8** / 召回 **9.2** **结论**:检索阶段没召回全,后面再强也救不回来——"垃圾进,垃圾出"。四级链路里,召回和精排的截断点是收益最大的两个调参位。 --- ## 主要接口 | 分组 | 接口 | |---|---| | 认证 | `POST /auth/register` · `POST /auth/login` · `GET /auth/me` | | 知识库 | `POST /knowledge` · `GET /knowledge` · `GET /knowledge/{kb_id}` · `POST /knowledge/{kb_id}/update` | | 文档 | `POST /document/upload` · `POST /document/split` · `GET /document/list` · `GET /document/{doc_id}/chunks` | | 入库 | `POST /ingest/{doc_id}` | | 问答 | `POST /retrieve/ask` | | 召回 | `GET /open/retrieve/retrieve` | **问答请求示例**: ```bash curl -X POST http://localhost:8000/retrieve/ask \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"kb_id": 1, "question": "你们的服务包含哪些内容?"}' ``` --- ## 已知限制 - 向量库数据与 BM25 索引未做持久化缓存,每次问答会从 Chroma 重建 BM25 节点,数据量大时是瓶颈(可改按 `kb_id` 缓存) - reranker 在 CPU 上推理较慢,有 GPU 可将 `use_fp16` 改为 `True` - 未做多轮对话上下文管理,当前是单轮问答 - 评估脚本依赖后端服务已启动,是调用方而非独立评测框架 --- ## 后续计划 - BM25 索引按 `kb_id` 缓存,避免每请求全量重建 - 接入 RAGAS 做横向对比 - 增加多轮对话与查询改写策略(HyDE)