# rag-qa-agent **Repository Path**: aiagentdemo/rag-qa-agent ## Basic Information - **Project Name**: rag-qa-agent - **Description**: 一个基于本地文档检索(RAG)+ 大模型作答的问答 Agent - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-24 - **Last Updated**: 2026-07-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # RAG 问答 Agent 一个基于本地文档检索(RAG)+ 大模型作答的问答 Agent:输入问题,先在指定目录的文档中检索相关内容作答并标注来源;检索不到时回退大模型通用知识。**流式(SSE)返回**,支持**动态重建索引**。 - 后端:Python · FastAPI(SSE 流式) - 前端:Vue 3 · Vite(通用大模型问答页样式) - 向量化:本地哈希词袋向量 + 余弦检索(**零依赖、离线可跑通**) - 大模型:OpenAI 兼容(万擎 / DeepSeek / OpenAI / Ollama 皆可),无 key/无网络时自动降级 mock 流式 ## 界面预览 ![RAG 问答 Agent 界面预览](docs/screenshot.png) > 左侧为知识库侧栏(已索引文件列表 + 重建索引),顶部可切换「智能 / 仅文档 / 仅大模型」问答模式,命中知识库时回答上方标注来源文件。 --- ## 功能 | 能力 | 说明 | | --- | --- | | 文档 RAG | 扫描指定目录,加载 `.docx/.md/.txt/.pdf`,切分并建本地向量索引 | | 流式问答 | `POST /api/chat` 以 SSE 逐字返回;先推送 `meta`(模式+来源),再推送 `token` | | 三种模式 | 智能(命中文档用知识库否则回退大模型) / 仅文档 / 仅大模型 | | 来源引用 | 命中知识库时,回答上方标注来源文件与相似度 | | 动态索引 | `POST /api/reindex` 重新扫描目录重建 RAG 库,无需重启 | | 离线可跑 | 向量化零依赖;无大模型 key 时 mock 流式降级 | --- ## 目录结构 ``` rag-qa-agent/ ├── backend/ │ ├── app/ │ │ ├── config.py # 配置(文档目录、LLM、检索参数) │ │ ├── rag.py # 文档加载 + 切分 + 本地哈希向量 RAG 库 │ │ └── llm.py # 万擎(OpenAI兼容)流式 + mock 降级 │ ├── main.py # FastAPI:/api/chat(SSE) /api/reindex /api/sources │ ├── requirements.txt │ └── .env.example └── frontend/ # Vue3 问答页(流式渲染、来源引用、索引侧栏) └── src/{App.vue, main.js, styles.css} ``` --- ## 后端启动 ```bash cd backend cp .env.example .env # 按需修改文档目录与万擎 key python3 -m pip install -r requirements.txt python3 main.py # http://localhost:8010 ``` 关键配置(`.env`): ```ini # 文档语料目录(生成 RAG 库的来源) DOCS_DIR=/Users/dragonking/Documents/AiAgentTest/测试大模型相关文件 # 万擎大模型(OpenAI 兼容) LLM_BASE_URL=https://XXX.XXX.com/api/agent/v1/apps LLM_MODEL=app-XXXX LLM_API_KEY=key LLM_FALLBACK_TO_MOCK=true # 无 key/无网络时降级 mock,保证可跑通 RAG_TOP_K=4 RAG_MIN_SCORE=0.04 # 低于此相似度视为未命中,回退大模型 ``` > 默认 `DOCS_DIR` 已指向同级仓库的「测试大模型相关文件」目录(含此前生成的多份测试主题 docx)。往该目录放入新文档后,点前端「重建索引」或调用 `/api/reindex` 即可生效。 ### 切换大模型(OpenAI 兼容,含 DeepSeek) 本项目的 LLM 客户端走 **OpenAI 兼容协议**(只发送 `model + messages + stream`),因此任何兼容该协议的服务都能用,**切换模型只改 `.env`、无需改代码**。 **改用 DeepSeek**(推荐 `deepseek-chat`): ```ini LLM_BASE_URL=https://api.deepseek.com # 也可写 https://api.deepseek.com/v1 LLM_MODEL=deepseek-chat # V3 通用对话;推理用 deepseek-reasoner (R1) LLM_API_KEY=sk-你的deepseek-key # 在 https://platform.deepseek.com 申请 LLM_FALLBACK_TO_MOCK=true ``` 说明: - 依赖不变,仍用 `openai` SDK(`requirements.txt` 已包含),无需额外装包。 - `deepseek-chat`(V3)便宜快,日常 RAG 问答够用;`deepseek-reasoner`(R1)带推理、更强但更慢更贵。 - key 未换成真实值时,调用会鉴权失败并(在 `LLM_FALLBACK_TO_MOCK=true` 下)降级 mock,不会崩溃。 **常见大模型配置对照:** | 服务 | LLM_BASE_URL | LLM_MODEL | | --- | --- | --- | | DeepSeek | `https://api.deepseek.com` | `deepseek-chat` / `deepseek-reasoner` | | OpenAI 官方 | `https://api.openai.com/v1` | `gpt-4o` / `gpt-4o-mini` | | 本地 Ollama | `http://localhost:11434/v1` | `qwen2.5` / `llama3.1` 等 | 改完 `.env` 后重启后端(`python3 main.py`)即生效。 --- ## 前端启动 ```bash cd frontend npm install npm run dev # http://localhost:5180(已把 /api 代理到 8010) npm run build # 生产产物在 frontend/dist ``` 打开 http://localhost:5180,直接提问即可。左侧栏显示已索引文件与「重建索引」按钮,顶部可切换问答模式。 --- ## SSE 流式协议 `POST /api/chat` body:`{ "question": "...", "mode": "auto|doc|llm" }` 返回 `text/event-stream`: ``` event: meta data: {"mode":"rag","sources":[{"source":"xxx.docx","score":0.4}]} event: token data: {"text":"根"} event: token data: {"text":"据"} ... event: done data: {} ``` - `mode`:`rag`(来自知识库) / `llm`(来自大模型) / `doc-miss`(仅文档模式但未命中) - 前端用 `fetch` + `ReadableStream` 读取并逐字渲染。 --- ## 说明 - 本地哈希向量方案零依赖、离线可跑,检索质量对中文关键词较友好;若需更高召回,可将 `rag.py` 的 `_embed` 换成 sentence-transformers 或远程 embedding 接口。 - 接真实大模型:`.env` 配好 `LLM_BASE_URL / LLM_MODEL / LLM_API_KEY` 且能访问对应服务即可(DeepSeek、万擎、OpenAI、Ollama 等 OpenAI 兼容服务通用,见上文「切换大模型」)。回答会基于检索片段(RAG)或通用知识(回退)流式生成。