# yuncheng-agent-qa **Repository Path**: liochaoo/yuncheng-agent-qa ## Basic Information - **Project Name**: yuncheng-agent-qa - **Description**: 基于 Spring AI + 阿里云百炼 + Qdrant 向量库的企业级知识问答系统 - **Primary Language**: Java - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 7 - **Forks**: 5 - **Created**: 2026-04-11 - **Last Updated**: 2026-04-29 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # AI 智能助手 - 基于 RAG 的知识问答系统

AI智能助手

基于 Spring AI + 阿里云百炼 + Qdrant 向量库的企业级知识问答系统

🌐 云程低代码平台官网  |  🤖 在线体验智能客服

---

RAG 核心处理流程
RAG 核心处理流程

--- ## 目录 - [项目简介](#项目简介) - [技术架构](#技术架构) - [功能特性](#功能特性) - [快速开始](#快速开始) - [系统配置](#系统配置) - [使用指南](#使用指南) - [接口文档](#接口文档) - [系统截图](#系统截图) - [RAG 核心处理流程](#rag-核心处理流程) --- ## 项目简介 本项目是一个基于 **RAG(检索增强生成)** 技术的企业级 AI 知识问答系统,是 [云程低代码平台](http://www.yunchengxc.com/) 官网智能客服系统的开源版本。系统支持从语雀文档或本地 Markdown 文件构建知识库,通过向量检索 + 大语言模型生成精准回答。 > 想先体验效果?点击访问 [云程官网智能客服](https://www.yunbangong100.com:31190/agent/) 在线体验 ### 核心能力 - **智能问答**:基于知识库的智能问答,支持多轮对话 - **文档管理**:支持语雀文档和本地 Markdown 文档导入 - **向量检索**:混合检索(稠密向量 + 稀疏向量 + 重排序) - **权限控制**:管理员专属的数据管理功能 - **流式响应**:SSE 流式输出,实时展示 AI 回答 --- ## 技术架构 ### 后端技术栈 | 技术 | 版本 | 说明 | |------|------|------| | Java | 21 | 编程语言 | | Spring Boot | 3.5.11 | 基础框架 | | Spring AI | 1.1.2 | AI 框架 | | Spring AI Alibaba | 1.1.2.2 | 阿里云 AI 适配 | | MyBatis-Plus | 3.5.16 | ORM 框架 | | MySQL | 8.x | 关系型数据库 | | Qdrant | 1.x | 向量数据库 | | JWT | 4.4.0 | 身份认证 | ### 前端技术栈 | 技术 | 版本 | 说明 | |------|------|------| | Vue | 3.5.30 | 前端框架 | | TypeScript | 5.9.3 | 类型语言 | | Element Plus | 2.13.6 | UI 组件库 | | Vite | 8.0.1 | 构建工具 | | Pinia | 3.0.4 | 状态管理 | ### 系统架构图

系统架构图
系统架构图

--- ## 功能特性 ### 用户端功能 - **密码登录**:支持账号密码 + 滑块验证码登录 - **体验登录**:一键体验账号登录(无需密码) - **智能对话**:流式 AI 回答,支持多轮对话 - **历史会话**:查看历史对话记录,支持会话切换 - **个人资料**:查看剩余问答次数、修改密码 ### 管理端功能(仅管理员) - **加载语雀文档**:从语雀知识库批量导入文档 - **加载本地文档**:从本地 Markdown 目录导入文档 - **同步向量库**:将审核通过的知识片段同步到向量库 - **清空向量库**:清空所有向量数据(危险操作) --- ## 快速开始 ### 环境要求 - JDK 21+ - Node.js 18+ - MySQL 8.0+ - Docker(用于运行 Qdrant) ### 1. 克隆项目 ```bash git clone https://github.com/your-repo/yuncheng-agent-qa.git cd yuncheng-agent-qa ``` ### 2. 启动 Qdrant 向量库 使用 Docker 快速启动: ```bash docker run -d \ --name qdrant \ -p 6333:6333 \ -p 6334:6334 \ -v $(pwd)/qdrant_storage:/qdrant/storage \ qdrant/qdrant:latest ``` 参数说明: - `-p 6333:6333`:HTTP API 端口 - `-p 6334:6334`:gRPC API 端口 - `-v`:持久化存储目录 ### 3. 初始化数据库 ```bash # 1. 创建数据库 mysql -u root -p -e "CREATE DATABASE qa CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" # 2. 执行建表脚本 mysql -u root -p qa < db/create_table.sql ``` ### 4. 配置环境变量 创建 `backend/.env` 文件或在系统中设置以下环境变量: ```bash # MySQL 配置 export MYSQL_HOST=127.0.0.1 export MYSQL_PORT=3306 export MYSQL_DB=qa export MYSQL_USERNAME=root export MYSQL_PASSWORD=your_password # 阿里云百炼配置(必需) export DASHSCOPE_API_KEY=sk-your-api-key # Qdrant 配置 export QDRANT_HOST=127.0.0.1 export QDRANT_PORT=6334 export QDRANT_API_KEY=your-qdrant-api-key # 如设置了API Key # JWT 密钥(建议修改) export JWT_SECRET=your-jwt-secret-key # 语雀配置(可选,如需导入语雀文档) export YUQUE_AUTH_TOKEN=your-yuque-token export YUQUE_REPO_NAMESPACE=your-namespace/your-repo # 本地文档目录(可选,如需导入本地文档) export LOCAL_MARKDOWN_DIR=/path/to/your/docs ``` ### 5. 启动后端服务 ```bash cd backend mvn clean install mvn spring-boot:run ``` 后端服务默认运行在 `http://localhost:9090/agent` ### 6. 启动前端服务 ```bash cd frontend npm install npm run dev ``` 前端服务默认运行在 `http://localhost:3000/agent` ### 7. 访问系统 打开浏览器访问 `http://localhost:3000/agent` --- ## 系统配置 ### 默认账号 | 账号类型 | 手机号 | 密码 | 说明 | |---------|--------|------|------| | 管理员 | 19999999999 | 123456 | 拥有文档管理、向量库操作权限 | | 体验账号 | 18888888888 | 无需密码 | 一键登录体验 | > **注意**:管理员手机号在 `application-dev.yml` 的 `qa.admin.phones` 中配置。 ### 问答次数配置 每个账号的问答次数存储在 `qa_user` 表的 `res_available` 字段中,可通过 SQL 修改: ```sql -- 增加指定用户的问答次数 UPDATE qa_user SET res_available = res_available + 100 WHERE user_phone = '19999999999'; ``` ### 系统提示词配置 系统提示词定义了 AI 助手的行为规范,可在以下文件中修改: | 提示词类型 | 文件路径 | 说明 | |-----------|---------|------| | RAG 系统提示词 | `backend/src/main/java/com/yuncheng/agent/qa/config/agent/ReactAgentConfig.java` | 定义 AI 回答的核心规则、检索策略、兜底话术 | | 问题重写提示词 | `backend/src/main/java/com/yuncheng/agent/qa/config/agent/ReactAgentConfig.java` | 定义问题重写专家的行为 | | 产品信息 | `backend/src/main/resources/information/yuncheng-info.md` | 产品基本介绍,可替换为自己的产品信息 | --- ## 使用指南 ### 接入语雀文档 1. **获取语雀 Token** - 登录语雀,进入「设置」→「开发者设置」→「个人访问令牌」 - 创建新 Token,复制保存 2. **配置环境变量** ```bash export YUQUE_AUTH_TOKEN=your-token export YUQUE_REPO_NAMESPACE=your-namespace/your-repo ``` 3. **加载文档** - 使用管理员账号登录系统 - 点击右上角头像 → 「加载语雀文档」 - 等待处理完成 4. **审核并同步** ```sql -- 将所有知识片段标记为审核通过 UPDATE qa_pair SET check_status = 'CHECKED' WHERE check_status = 'UNCHECKED'; ``` - 点击「同步向量库」完成向量化 ### 接入本地 Markdown 文档 1. **准备文档** - 确保文档为 `.md` 格式 - 文档需包含一级标题(`# 标题`) - 建议按功能模块组织文档 2. **配置目录** ```bash export LOCAL_MARKDOWN_DIR=/path/to/your/markdown/files ``` 3. **加载文档** - 使用管理员账号登录 - 点击「加载本地文档」 - 系统自动处理目录下所有 `.md` 文件 4. **审核并同步**(同上) ### 文档处理流程

文档处理流程
文档处理流程

### 重要 SQL 语句 ```sql -- 查看所有待审核的知识片段 SELECT * FROM qa_pair WHERE check_status = 'UNCHECKED'; -- 批量审核通过 UPDATE qa_pair SET check_status = 'CHECKED' WHERE check_status = 'UNCHECKED'; -- 查看向量同步状态 SELECT check_status, vector_status, COUNT(*) as count FROM qa_pair GROUP BY check_status, vector_status; -- 查看用户剩余次数 SELECT user_phone, nickname, res_available, res_used FROM qa_user; ``` --- ## 接口文档 ### 主要 Controller 接口 #### 1. 用户模块 (UserController) | 接口 | 方法 | 说明 | |------|------|------| | `POST /api/user/login` | 密码登录 | 账号密码 + 滑块验证码 | | `POST /api/user/login/demo` | 体验登录 | 无需密码,一键登录 | | `GET /api/user/profile` | 获取用户信息 | 包含剩余次数等 | | `POST /api/user/password` | 修改密码 | 需登录 | #### 2. 问答模块 (QaController) | 接口 | 方法 | 说明 | |------|------|------| | `POST /api/qa/chat` | 流式对话 | SSE 流式返回 | | `GET /api/qa/sessions` | 获取会话列表 | 当前用户的所有会话 | | `GET /api/qa/history/{chatId}` | 获取对话历史 | 指定会话的详细对话 | #### 3. 文档模块 (DocumentController) - 仅管理员 | 接口 | 方法 | 说明 | |------|------|------| | `POST /api/document/load/yuque` | 加载语雀文档 | 从语雀批量导入 | | `POST /api/document/load/local` | 加载本地文档 | 从本地 Markdown 导入 | #### 4. 向量模块 (VectorController) - 仅管理员 | 接口 | 方法 | 说明 | |------|------|------| | `POST /api/vector/sync` | 同步向量库 | 将审核通过的数据向量化 | | `POST /api/vector/clear` | 清空向量库 | 危险操作,谨慎使用 | #### 5. 验证码模块 (CaptchaController) | 接口 | 方法 | 说明 | |------|------|------| | `POST /api/captcha/get` | 获取滑块验证码 | 返回滑块图片 | | `POST /api/captcha/check` | 验证滑块 | 返回验证结果 | --- ## 系统截图

登录页
登录页面

对话页
智能对话页面

管理功能
管理员功能菜单

--- ## 项目结构 ``` yuncheng-agent-qa/ ├── backend/ # 后端项目 │ ├── src/main/java/com/yuncheng/agent/qa/ │ │ ├── config/ # 配置类 │ │ │ ├── agent/ # AI Agent 配置 │ │ │ └── QaProperties.java # 业务配置属性 │ │ ├── controller/ # 控制器层 │ │ │ ├── CaptchaController.java │ │ │ ├── DocumentController.java │ │ │ ├── QaController.java │ │ │ ├── UserController.java │ │ │ └── VectorController.java │ │ ├── service/ # 服务层 │ │ ├── mapper/ # 数据访问层 │ │ ├── model/ # 数据模型 │ │ └── tools/ # 工具类 │ ├── src/main/resources/ │ │ ├── application-dev.yml # 开发环境配置 │ │ └── information/ │ │ └── yuncheng-info.md # 产品信息(可替换) │ └── pom.xml ├── frontend/ # 前端项目 │ ├── src/ │ │ ├── api/ # API 接口封装 │ │ ├── components/ # 组件 │ │ ├── stores/ # Pinia 状态管理 │ │ └── views/ # 页面视图 │ ├── package.json │ └── vite.config.ts ├── db/ │ └── create_table.sql # 数据库建表脚本 ├── doc/ │ └── images/ # 文档图片 ├── README.md └── .gitignore ``` --- ## RAG 核心处理流程 本系统采用企业级 RAG(检索增强生成)架构,以下详细介绍文档处理到问答的完整流程。 ### 一、文档切片规则 #### 1.1 清洗规则 文档加载后首先进行清洗处理: | 清理项 | 处理方式 | |--------|----------| | HTML 标签 | 使用 Jsoup 提取纯文本 | | Markdown 图片 | `![alt](url)` 完全移除 | | HTML 注释 | `` 移除 | | 代码块 | 保护后恢复(占位符替换) | | 行内代码 | 保护后恢复 | | 连续空行 | 3 个及以上合并为 2 个 | | 行尾空格 | 逐行去除 | #### 1.2 切片策略 清洗后的文档采用三级递进切片策略: | 层级 | 触发条件 | 处理方式 | |------|----------|----------| | **一级标题** | 文档存在 `# ` 标题 | 按 H1 切分,保留上下文路径 | | **二级标题** | H1 段落 > 800 字符 | 按 `## ` 继续切分 | | **段落拆分** | H2 段落 > 800 字符 | 按双换行分段 | | **强制拆分** | 单段落 > 800 字符 | 按句子边界强制切分 | #### 1.3 字数控制 - **最大块大小**: 800 字符 - **拆分优先级**: 优先在句子边界(。!?.!?)处截断 - **边界容差**: 不超过最大大小的 20%(160 字符) ### 二、信息提取规则 #### 2.1 标题选择优先级 1. 格式化后的 H1/H2 标题 2. 目录路径(如:功能模块 > 子模块) 3. 默认名称:"未命名知识片段" #### 2.2 关键词提取 **权重分配**(多维度打分): | 来源 | 权重 | 说明 | |------|------|------| | 标题 | 20 | 业务短语候选 | | 目录路径 | 14 | 业务短语候选 | | 正文 | 4 | 业务短语候选 | | 标题 | 12 | 结构化候选(驼峰、连字符等)| | 目录路径 | 8 | 结构化候选 | | 正文 | 1 | 文本候选 | **过滤规则**: - 长度 2-20 字符 - 排除纯数字 - 排除停用词("的"、"了"、"和"等) - 排除通用词("如下图所示"、"我们"等) - 英文词需命中白名单 **输出**: 默认提取 6 个关键词,逗号分隔 #### 2.3 摘要提取 **长度控制**: - 最大长度:120 字符 - 最小长度:40 字符 **生成策略**: 1. 优先从正文提取前 120 字符 2. 在标点符号(。;!?.)处智能截断 3. 格式:`{标题} - {摘要}` 4. 兜底:取正文前 40-120 字符 ### 三、存储规则 #### 3.1 数据表结构 (`qa_pair`) | 字段名 | 类型 | 说明 | |--------|------|------| | `id` | varchar(36) | 主键(UUID)| | `source_id` | varchar(36) | 关联文档源 ID | | `feature_title` | text | 功能点标题 | | `feature_keyword` | text | 功能点关键字(逗号分隔)| | `feature_summary` | text | 功能点摘要 | | `feature_content` | text | 功能点完整内容 | | `check_status` | varchar(32) | 审核状态:UNCHECKED/CHECKED/REJECTED | | `vector_status` | varchar(32) | 向量化状态:UNVECTORIZED/VECTORIZED/FAILED | | `original_link` | text | 原始文档链接 | | `vector_point_id` | varchar(255) | Qdrant 向量点 ID | #### 3.2 状态流转 ``` 文档加载 → UNCHECKED/UNVECTORIZED ↓ 审核通过 → CHECKED/UNVECTORIZED ↓ 同步向量库 → CHECKED/VECTORIZED ``` ### 四、向量化规则 #### 4.1 向量模型 - **模型**: `text-embedding-v3`(阿里云百炼) - **批次大小**: 20 条/批次 #### 4.2 正文组织格式 ``` [TITLE]: {feature_title} [KEYWORDS]: {feature_keyword} [SUMMARY]: {feature_summary} [CONTENT]: {feature_content} ``` #### 4.3 元数据结构 | 字段 | 存储位置 | 用途 | |------|----------|------| | pairId | metadata | 关联数据库记录 | | featureTitle | metadata | 稀疏检索字段 | | featureKeywords | metadata | 稀疏检索字段 | | featureSummary | metadata | 稀疏检索字段 | | originalLink | metadata | 参考链接 | **说明**: 完整结构化文本存储在 `Document.text` 中用于稠密向量编码 ### 五、问答策略 #### 5.1 问题重写 **触发条件**: 存在历史问答记录时触发 **重写规则**: - 话题判断:区分历史追问 vs 全新话题 - 指代消解:补全"它、这个、那个"等指代 - 术语标准化:使用平台标准功能术语 - 禁止扩写:绝不添加用户问题中不存在的信息 **示例**: - 原问题:"这个怎么配置?" - 重写后:"表单设计器的字段校验规则如何配置?" #### 5.2 关键字拆分策略 **系统强制规则**: - 每次检索只能是 **1 个核心功能点**,长度 ≤ 12 字 - 多要点问题必须先拆分,逐轮分别检索 - 严禁:长句、多词堆砌(如"表单+流程+配置")、宽泛词 #### 5.3 多轮检索流程 ``` 用户提问 ↓ 问题重写(基于历史上下文) ↓ 问题拆分(多要点拆分为单点) ↓ 逐轮检索(每轮检索一个单点,最多 10 轮) ↓ 结果聚合(合并多轮检索结果) ↓ 答案生成 ``` ### 六、检索规则(四阶段流水线) | 阶段 | 名称 | 处理逻辑 | TopK | |------|------|----------|------| | **1** | 稠密召回 | 对 Document.text 做向量相似度搜索 | 24 | | **2** | 稀疏召回 | 对 doc_content + title + keywords + summary 做文本匹配 | 48 | | **3** | 融合打分 | BM25 词法打分 + 字段加权,归一化融合 dense + sparse 分数 | 12 | | **4** | 重排序 | 基于 gte-rerank 模型,融合分数与重排分数加权混合 | - | #### 6.1 稠密召回配置 ```yaml dense-recall-top-k: 24 similarity-threshold: 0.7 ``` #### 6.2 稀疏召回配置 ```yaml sparse-recall-top-k: 48 sparse-scroll-batch-size: 128 min-query-term-length: 2 max-query-terms: 8 ``` **查询分词**: 使用 Jieba 分词,限制最多 8 个词,最小词长 2 字符 #### 6.3 融合打分规则 **字段权重**: ```yaml title-field-weight: 3.5 # 标题权重最高 keyword-field-weight: 2.8 # 关键词次之 summary-field-weight: 1.8 # 摘要再次 content-field-weight: 1.0 # 内容基础权重 ``` **精确匹配加权**: ```yaml exact-phrase-boost: 1.8 # 摘要/内容完整匹配加分 title-exact-match-boost: 1.4 # 标题完整匹配加分 keyword-exact-match-boost: 1.2 # 关键词完整匹配加分 ``` **融合权重**: ```yaml dense-weight: 0.45 # 稠密向量分数权重 sparse-weight: 0.55 # 稀疏检索分数权重 ``` **融合公式**: ``` finalScore = 0.45 × normalizedDenseScore + 0.55 × normalizedSparseScore ``` #### 6.4 重排序规则 ```yaml rerank-enabled: true rerank-model: gte-rerank rerank-max-text-length: 1800 rerank-blend-weight: 0.7 ``` **混合公式**: ``` finalScore = 0.7 × rerankScore + 0.3 × fusionScore ``` ### 七、给到大模型的内容 检索结果按以下格式组织后提供给大模型: ``` --- Result 1 --- Title: {功能点标题} Keywords: {关键词} Summary: {摘要} Content: {内容前 1200 字符} Score: {最终相关性分数} Reference: {原始文档链接} --- Result 2 --- ... ``` **系统提示词约束**: - 必须基于检索结果回答,严禁编造 - 优先使用高 Score 的结果 - 必须标注参考来源(Reference) - 无法回答时给出兜底话术 --- ## 常见问题 ### Q1: 如何修改系统提示词? 编辑 `backend/src/main/java/com/yuncheng/agent/qa/config/agent/ReactAgentConfig.java` 文件中的 `RAG_SYSTEM_PROMPT` 常量。 ### Q2: 如何接入自己的语雀知识库? 1. 在语雀创建个人访问令牌 2. 配置 `YUQUE_AUTH_TOKEN` 和 `YUQUE_REPO_NAMESPACE` 环境变量 3. 重启后端服务 4. 使用管理员账号点击「加载语雀文档」 ### Q3: 为什么加载文档后问答没有反应? 需要执行两步操作: 1. 在数据库中将 `qa_pair` 表的 `check_status` 更新为 `CHECKED` 2. 点击「同步向量库」按钮 ### Q4: 如何增加用户的问答次数? 执行 SQL: ```sql UPDATE qa_user SET res_available = 100 WHERE user_phone = '用户手机号'; ``` ### Q5: 向量库连接失败怎么办? 1. 检查 Qdrant 是否已启动:`docker ps | grep qdrant` 2. 检查 `QDRANT_HOST` 和 `QDRANT_PORT` 配置是否正确 3. 检查防火墙是否放行对应端口 --- ## 许可证 本项目采用 [MIT License](LICENSE) 开源协议。 --- ## 联系方式 如有问题或建议,欢迎提交 Issue 或 Pull Request。 ---

Made with ❤️ by Yuncheng