# 111 **Repository Path**: the-handsome-man0/111 ## Basic Information - **Project Name**: 111 - **Description**: 专业实习留痕 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 0 - **Created**: 2026-09-02 - **Last Updated**: 2026-09-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 曲阜师范大学学生手册智能问答系统 > 基于 RAG 与 AI Agent(ReAct)架构的规章制度问答系统,面向《曲阜师范大学学生手册》提供「引用可溯源」的制度问答能力。 ## 简介 本系统以 FastAPI 构建,核心链路为:文档解析 → 结构化分块 → 混合检索(语义向量 + 关键词)→ 交叉编码器重排 → LLM 生成;在此之上封装 ReAct Agent 编排层,使系统具备工具调用、多轮记忆与流式输出能力。回答可附带「章 / 条」来源引用,并内置溯源校验与结构冲突检测,降低幻觉。 支持两种响应模式: - **RAG 模式**:单轮检索 + 生成,速度快、可解释。 - **Agent 模式**:多步推理 + 工具调用(知识库检索、联网搜索),适合需要拆解子问题的复杂提问。 ## 功能特性 - **混合检索**:融合 FAISS 向量检索与 BM25 关键词检索,通过 α 参数(默认 0.5)平衡两者权重 - **交叉编码器重排**:采用 `bge-reranker-base` 提升 top-k 精度(LLM 评分为可选降级) - **Agent 模式(ReAct)**:文本式 ReAct 编排,支持多步推理、工具调用与跨轮记忆 - **溯源增强**:回答附带 `source / chapter / article` 来源卡片,并校验引用条号是否真实存在 - **冲突检测**:检测多来源在同一主题词上的数值差异,自动标注「疑似来源冲突」 - **增量构建**:上传文档追加到知识库,不清空已有数据 - **流式响应**:SSE 逐 token 输出(打字机效果),Agent 模式额外推送思考与工具卡片 - **模型本地缓存**:嵌入与重排模型从本地缓存加载,避免部署环境无外网时卡住 ## 技术栈 | 层 | 技术 | |----|------| | 后端 | Python 3 + FastAPI + Uvicorn | | 前端 | 原生 HTML / JavaScript(单页应用,SSE 消费) | | 向量检索 | FAISS(`IndexFlatL2` 等,按数据量自动选型) | | 关键词检索 | BM25(`rank_bm25`) | | 向量化 | `BAAI/bge-small-zh-v1.5`(512 维) | | 重排 | `BAAI/bge-reranker-base`(CrossEncoder) | | LLM | DeepSeek(OpenAI 兼容协议,唯一后端) | | 联网搜索 | Tavily(优先)/ SERPAPI(可选兜底) | ## 目录结构 ``` . ├── api_router.py # FastAPI 入口(REST + SSE、知识库自动加载、前端托管) ├── config.py # 配置中心(环境变量、RAG 超参数、模型与缓存路径) ├── runtime_env.py # 运行时环境(最先导入,设置 HF 离线/缓存) ├── version.py # 版本号(当前 v1.3.0) ├── download_models.py # 模型预下载脚本 ├── requirements.txt # Python 依赖 ├── example.env # 环境变量模板(复制为 .env 使用) ├── core/ # 核心模块 │ ├── agent.py # ReAct Agent 编排(工具执行、溯源校验、冲突提示) │ ├── generator.py # 生成与提示构建(RAG 管道、流式输出) │ ├── retriever.py # 混合检索编排(hybrid_merge、递归检索) │ ├── vector_store.py # FAISS 向量存储 │ ├── bm25_index.py # BM25 索引管理 │ ├── reranker.py # 重排序策略(CrossEncoder / LLM) │ ├── text_splitter.py # 文本分块(按「章 / 条」结构化) │ ├── embeddings.py # 文本嵌入封装 │ └── document_loader.py # 文档解析(PDF / Word / PPT / 表格 / 文本) ├── features/ # 领域能力 │ ├── web_search.py # 联网搜索(SERPAPI) │ ├── conflict_detector.py # 结构冲突检测 │ └── thinking_chain.py # 思考链处理(过滤 + XSS 转义) ├── utils/ # 工具 │ └── network.py # 会话复用、端口可用性探测 ├── public/ # 前端静态资源 │ └── index.html # 单页前端页面 ├── project-docs/ # 项目文档 │ ├── architecture.md # 软件设计架构书(含 ADR) │ ├── agent.md # 智能体设定书 │ ├── skills.md # 技能定义文件 │ ├── tasks.md # 任务清单 │ └── 验收手册.md # 验收手册 ├── deliverables/ # 交付物 │ ├── 交付清单.md │ └── 测试记录.md ├── docs/ # 知识库源(学生手册,启动自动加载) └── tests/ # 自动化测试 ├── test_agent.py # Agent 单元测试 ├── test_generator.py # 生成模块测试 ├── test_api.py # API 接口测试 ├── conftest.py # 测试桩(离线、不打真实 API) ├── smoke_server.py # 离线冒烟测试 └── eval/ # 评测集与评测脚本 ``` ## 快速开始 ### 1. 创建虚拟环境 项目约定使用 `.venv` 作为虚拟环境目录: ```bash python -m venv .venv # Windows .venv\Scripts\activate # macOS / Linux source .venv/bin/activate ``` ### 2. 安装依赖 ```bash pip install -r requirements.txt ``` > 国内网络建议加镜像:`pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt` ### 3. 配置环境变量 复制模板为 `.env` 并填入真实密钥: ```bash # Windows copy example.env .env # macOS / Linux cp example.env .env ``` | 变量 | 用途 | 必填 | |------|------|------| | `DEEPSEEK_API_KEY` | DeepSeek 官方 API Key(唯一模型后端) | **必填** | | `DEEPSEEK_API_URL` | 接口地址,默认 `https://api.deepseek.com/v1/chat/completions` | 可选 | | `DEEPSEEK_MODEL_NAME` | 模型 ID,默认 `deepseek-chat`(推理模型可填 `deepseek-reasoner`) | 可选 | | `TAVILY_API_KEY` | 联网搜索(Tavily,推荐,有免费额度) | 可选 | | `SERPAPI_KEY` | 联网搜索兜底(SerpAPI) | 可选 | | `RERANK_METHOD` | 重排序方法 `cross_encoder`(默认)或 `llm` | 可选 | ### 4. 预下载模型(首次运行必做) ```bash python download_models.py ``` 下载 `bge-small-zh-v1.5`(向量化)与 `bge-reranker-base`(重排),落到项目内 `.cache/`。跳过此步会导致启动时知识库加载卡住。 ### 5. 放入知识库文档 把《学生手册》PDF / Word 放入项目根目录的 `docs/` 目录,启动时会自动解析、分块并向量化。 > 注意:仅扫描 `docs/` 目录。项目自身开发文档已放在 `project-docs/`,不会进入知识库。 ### 6. 启动服务 ```bash python api_router.py ``` 默认端口 `17995`(被占用时自动顺延到 17996–17999)。启动后浏览器访问 即可使用前端界面。 ## API 接口 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/` | 返回前端 `index.html` | | GET | `/api/status` | 健康检查(Key 配置、知识库就绪、分块数、版本) | | POST | `/api/upload` | 上传文档,增量构建知识库 | | POST | `/api/ask` | RAG 非流式问答,返回 `{answer, sources, metadata}` | | POST | `/api/ask/stream` | RAG 流式问答(SSE:text / thinking / sources) | | POST | `/api/agent/ask` | Agent 非流式问答,额外返回 `metadata.tools` | | POST | `/api/agent/stream` | Agent 流式问答(SSE:text / thinking / tools / sources / status) | 请求体 `QuestionRequest`: ```json { "question": "学生处分有哪些类型?", "enable_web_search": false, "model_choice": "deepseek", "history": [] } ``` ### 非流式响应示例(`/api/ask`) ```json { "answer": "根据《学生手册》……", "sources": [ { "source": "学生手册.pdf", "chapter": "第四章", "article": "第四十条", "content": "……" } ], "metadata": { "enable_web_search": false, "model": "deepseek" } } ``` ### 流式响应(SSE) ``` data: {"text": "根据", "thinking": "", "sources": [], "status": "..."} data: {"text": "《学生手册》", ...} ... data: {"text": "……", "thinking": "", "sources": [...], "status": "完成!"} data: [DONE] ``` ## 架构设计 详见 [project-docs/architecture.md](project-docs/architecture.md)。核心决策记录(ADR): - **ADR-001**:采用 RAG 而非模型微调,降低维护成本、支撑引用溯源 - **ADR-002**:混合检索 α=0.5,平衡语义与关键词召回(实测 20/20 命中) - **ADR-003**:交叉编码器重排,替代区分度弱的 `distiluse` 模型 - **ADR-004**:文本式 ReAct 而非 Function Calling,兼容无 tool-calling 能力的模型 - **ADR-005**:按「章 / 条」结构化分块,保持语义完整 - **ADR-006**:控制成本与延迟 —— `MAX_AGENT_STEPS=4`、工具内单次检索、单条上下文限长 700 字符 - **ADR-007**:知识库增量构建,避免清空已有数据 - **ADR-008**:可信增强(溯源校验 + 冲突检测) - **ADR-009**:模型本地缓存加载(嵌入/重排模型从 .cache 读取) - **ADR-010**:唯一 LLM 后端 DeepSeek,统一调用接口 ## Agent 能力 详见 [project-docs/agent.md](project-docs/agent.md) 与 [project-docs/skills.md](project-docs/skills.md)。 Agent 采用 ReAct 范式:每轮输出 `THOUGHT / ACTION`,解析后调用工具、回填观察,直至无动作或达到步数上限。内置两个技能(工具): - `retrieve_knowledge`:知识库混合检索 + 重排(RAG) - `web_search`:联网搜索(Tavily 优先,SerpAPI 兜底,需配置 Key) ## 测试 ### 单元测试(离线,无需 API Key) ```bash .venv\Scripts\python.exe -m pytest tests/ -q # Windows # .venv/bin/python -m pytest tests/ -q # macOS / Linux ``` 当前全部通过:**189 passed**。 ### 离线冒烟测试 无需 API Key 与模型权重,验证接口与 SSE 接线: ```bash python tests/smoke_server.py ``` ### 评测 需配置 API Key 且知识库就绪后运行: ```bash python tests/eval/run_eval.py --path tests/eval/eval_set.json --model deepseek ``` 详见 [tests/README.md](tests/README.md)。 ## 扩展 - **新增工具**:在 `core/agent.py` 的 `run_tool` 中实现,并在 `project-docs/skills.md` 注册。 - **调整检索策略**:修改 `core/retriever.py` 的 `hybrid_merge` 权重,或调整 `core/reranker.py` 的重排方法与 top-k 参数。 - **更换 LLM 后端**:在 `core/generator.py` 实现对应调用函数(遵循 OpenAI 兼容协议)。 ## 版本 当前 `v1.3.0`,迭代记录见 [project-docs/agent.md](project-docs/agent.md)。