# llm-agent-rag-backend **Repository Path**: lazuli/llm-agent-rag-backend ## Basic Information - **Project Name**: llm-agent-rag-backend - **Description**: Python/FastAPI Agent 与中文 RAG 后端,支持 LangGraph、混合检索、引用校验、拒答与离线评测。 - **Primary Language**: Python - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-19 - **Last Updated**: 2026-08-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # LLM Agent & Chinese RAG Backend 面向 LLM / Agent 应用开发的 Python + FastAPI 工程实践仓库,包含一套共享的 OpenAI-compatible 模型接入层,以及两个可独立运行的后端应用: - **Tool Agent**:结构化决策协议、手写 Agent Loop、LangGraph StateGraph、工具参数校验和 SQLite Trace。 - **Chinese Document RAG**:中文文档入库、向量/BM25 混合检索、RRF、引用校验、证据不足拒答和离线评测框架。 本仓库重点展示应用层工程能力,包括模型接入、工作流编排、工具执行边界、可追踪性、检索与评测。所有自动化测试均使用 Fake / Scripted LLM,不需要真实 API Key,也不会消耗模型额度。 ## 能力概览 | 模块 | 主要能力 | 服务入口 | |---|---|---| | `llm_client` | 普通调用、流式输出、Pydantic 结构化输出、DeepSeek/Qwen 配置切换 | FastAPI / CLI | | `tool_agent` | Manual Agent Loop、LangGraph、ToolRegistry、JSON Schema 参数校验、三类工具、Trace 持久化 | `:8001` | | `rag_assistant` | 中文切分、Qwen Embedding、Chroma、BM25 + RRF、轻量词法重排、引用与拒答、JSONL 评测 | `:8002` | > 说明:Tool Agent 通过 Prompt + Pydantic 模型约束 LLM 输出结构化决策,并非对 OpenAI 原生 `tools/tool_calls` 字段的封装。RAG 是固定的检索后生成流程,不是 Agentic RAG;其中的 rerank 是可解释的轻量词法重排,不是神经 Cross-Encoder。 ## 架构 ### Tool Agent ```text POST /agent/run │ ├── engine=manual ───────> ManualToolAgent │ └── engine=langgraph ────> LangGraphToolAgent │ decision -> handler -> observation │ calculator / search_local_notes / query_applications │ v SQLite agent_traces ``` 手写循环和 LangGraph 工作流共享同一个 LLM 接口、ToolRegistry、工具协议及 SQLiteStore。模型输出被视为不可信输入,工具名和参数在 handler 执行前经过注册表查找和 Pydantic 校验;`max_steps` / `recursion_limit` 用于限制循环。 ### Chinese Document RAG ```text Markdown / TXT │ v 中文标题与标点感知切分 -> Qwen Embedding -> Chroma cosine index │ v vector 或 vector + BM25 -> RRF -> 可选词法轻量重排 │ v 证据阈值 -> 拒答 / 结构化回答 -> 引用编号校验 │ v JSONL evaluation -> per-case metrics -> SQLite experiment records ``` ## 快速开始 ### 1. 安装 需要 Python 3.13 与 [uv](https://docs.astral.sh/uv/)。 ```powershell uv sync --extra rag Copy-Item .env.example .env ``` 在 `.env` 中填写自己的模型 Key。不要修改 `.env.example` 来保存真实凭据。 ### 2. 运行无 Key 自动化测试 ```powershell uv run --extra rag pytest -q ``` 也可以分别运行: ```powershell uv run pytest tests/test_llm_client -q uv run pytest tests/test_tool_agent -q uv run --extra rag pytest tests/test_rag_assistant -q ``` 测试覆盖 LLM 配置与结构化响应、ToolRegistry、受限计算器、多步骤 Agent、循环上限、Trace 持久化、文档加载与切分、混合检索、引用校验、拒答策略、API 以及评测结果存储。 ### 3. 配置真实模型 `.env.example` 中保留的是公开厂商 API 地址和占位 Key: ```dotenv LLM_PROVIDER=deepseek DEEPSEEK_API_KEY=your_deepseek_api_key DEEPSEEK_BASE_URL=https://api.deepseek.com DEEPSEEK_MODEL=deepseek-v4-flash QWEN_API_KEY=your_qwen_api_key QWEN_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1 QWEN_MODEL=qwen-plus ``` 厂商公开 Base URL 和模型名可以进入仓库;API Key、带签名参数的 URL、内部网关、租户信息和 Authorization Header 不可以提交。 ## Tool Agent 启动服务: ```powershell uv run uvicorn tool_agent.api:app --reload --port 8001 ``` 选择 LangGraph 引擎: ```powershell curl.exe -X POST http://127.0.0.1:8001/agent/run ` -H "Content-Type: application/json" ` -d '{"question":"计算 (12+8)/4","engine":"langgraph","max_steps":5}' ``` 将 `engine` 改为 `manual` 可以运行手写循环。响应中的 `trace_id` 用于查询持久化轨迹: ```powershell curl.exe http://127.0.0.1:8001/agent/traces/替换为真实trace_id ``` ### 工具与执行边界 | 工具 | 作用 | 边界 | |---|---|---| | `calculator` | 算术表达式计算 | AST 白名单,不执行任意 Python 代码 | | `search_local_notes` | 检索本地示例笔记 | 限定目录与文件类型 | | `query_applications` | 查询示例投递记录 | SQLite 参数化查询 | ### API | Method | Path | 说明 | |---|---|---| | GET | `/health` | 存活检查 | | POST | `/agent/run` | 运行 Manual / LangGraph Agent | | GET | `/agent/traces/{trace_id}` | 查询成功或失败步骤 | ### Docker 当前镜像只运行 Tool Agent,并且只复制公开示例笔记,不复制本地数据库、上传文档或向量索引。 ```powershell docker build -t tool-agent . docker run --rm -p 8001:8001 ` --env-file .env ` -v "${PWD}/data:/app/data" ` tool-agent ``` ## Chinese Document RAG 先入库公开示例文档: ```powershell uv run --extra rag python -m rag_assistant.cli ingest data/rag_docs/samples ``` 向量检索问答: ```powershell uv run --extra rag python -m rag_assistant.cli ask "RAG 为什么需要拒答策略?" ``` 混合检索与轻量重排: ```powershell uv run --extra rag python -m rag_assistant.cli ask ` "语义检索和关键词检索各自擅长什么?" ` --retrieval-mode hybrid ` --rerank ``` 启动 API: ```powershell uv run --extra rag uvicorn rag_assistant.api:app --reload --port 8002 ``` Swagger UI:`http://127.0.0.1:8002/docs` ### API | Method | Path | 说明 | |---|---|---| | GET | `/health` | 存活检查 | | POST | `/rag/upload` | 上传 UTF-8 Markdown / TXT | | POST | `/rag/ask` | 检索、引用回答或拒答 | | GET | `/rag/documents` | 查看已入库文档 | | DELETE | `/rag/documents/{doc_id}` | 删除文档与向量 | | POST | `/rag/evaluate` | 启动后台评测 | | GET | `/rag/evaluate/{task_id}` | 查询逐题及聚合结果 | ### 评测状态与边界 仓库包含与三份公开示例文档配套的 30 条 synthetic/demo JSONL 问题,覆盖直接问题、同义改写和知识库外拒答。它用于证明评测机制可以运行,不是企业真实语料,也不是具有外部泛化意义的 Benchmark。 | 能力 | 当前状态 | |---|---| | Markdown/TXT 入库与中文切分 | 已实现 | | Chroma 向量检索 | 已实现 | | BM25 + RRF 混合检索 | 已实现 | | 引用编号校验与证据不足拒答 | 已实现 | | JSONL 评测框架与 SQLite 存储 | 已实现 | | Fake / Scripted LLM 确定性测试 | 已实现 | | 真实供应商 A-D 对比实验结果 | 尚未发布 | | 生产级鉴权、限流和任务队列 | 不在当前范围 | 可复现实验配置如下;这是计划实验矩阵,不是效果结果: | 实验 | chunk / overlap | Top-K | 检索模式 | 轻量重排 | |---|---:|---:|---|---| | A | 400 / 80 | 3 | vector | 否 | | B | 600 / 100 | 5 | vector | 否 | | C | 600 / 100 | 5 | hybrid | 否 | | D | 600 / 100 | 5 | hybrid | 是 | 在没有实际保存实验记录前,本仓库不声称命中率、引用正确率或延迟有任何百分比提升。 ## 仓库结构 ```text src/ llm_client/ # OpenAI-compatible 模型客户端 tool_agent/ # Manual / LangGraph Tool Agent rag_assistant/ # 中文文档 RAG 与评测 tests/ test_llm_client/ # 配置、结构化响应与错误脱敏 test_tool_agent/ # Agent 确定性测试 test_rag_assistant/ # RAG 确定性测试 data/ notes/ # Tool Agent 公开示例数据 rag_docs/samples/ # RAG 公开示例文档 eval/ # synthetic/demo 评测集 ``` 本地 `.env`、SQLite、Trace、上传文档、Chroma 索引、简历和编辑器缓存均被排除在 Git 与 Docker 构建上下文之外。 ## 安全与部署注意事项 - 不要提交 `.env`、API Key、Token、私有代理地址、请求头或真实用户数据。 - 不要提交 `data/*.db`、`data/rag_index/` 或 `data/rag_docs/uploads/`;Chroma 元数据可能包含原文。 - 当前 API 面向本地演示,没有实现身份认证与限流。若部署到公网,应先增加鉴权、速率限制、请求大小限制、成本预算和数据清理策略。 - 如果凭据曾进入 Git 历史,应立即在供应商控制台撤销/轮换,再处理历史;仅删除工作区文件并不足够。 更完整的公开仓库安全边界见 [`SECURITY.md`](./SECURITY.md)。 ## 已知限制 - RAG 只支持 UTF-8 Markdown/TXT,不支持 PDF、DOCX 和 OCR。 - BM25 适合当前小型本地语料,不适合直接扩展为大型知识库服务。 - Chroma 按本地单进程使用,不建议多个 Uvicorn worker 同时写索引。 - FastAPI `BackgroundTasks` 在进程重启时会丢失任务,不等同于可靠任务队列。 - 当前 Dockerfile 只面向 Tool Agent;RAG 的向量库与数据生命周期需要单独设计。