基于AI Agent、RAG、工具调用与工作流编排的智能问答系统完整实施方案
基于AI Agent、RAG、工具调用与工作流编排的智能问答系统完整实施方案
一、方案整体概述
1.1 项目背景与目标
传统智能问答系统普遍存在知识库固化、无法实时联网更新、不会调用外部工具、复杂问题拆解能力弱、问答准确率低等问题,无法满足企业复杂业务咨询、智能客服、内部知识问答、文档答疑等场景的高阶需求。
本方案融合AI智能代理(Agent)、检索增强生成(RAG)、大模型工具调用、可视化工作流编排四大核心技术,搭建一套轻量化、可扩展、可定制的通用智能问答系统。系统具备自主问题拆解、知识库精准检索、外部工具联动、流程自动化执行、多轮对话记忆、答案溯源纠错能力,可适配企业内部知识库问答、客户智能客服、公文答疑、技术文档问答、行业智能咨询等全场景。
1.2 核心能力亮点
- RAG精准知识库问答:依托私有文档、业务数据构建专属知识库,解决大模型幻觉、知识滞后问题,答案可溯源、可审核。
- AI Agent自主决策:无需人工干预,自主判断问题类型、选择处理方式、拆解复杂任务、迭代优化回答结果。
- 通用工具调用能力:支持联网搜索、数据查询、接口调用、公式计算、文档解析、代码执行等第三方工具拓展。
- 可视化工作流编排:拖拽式配置问答流程,支持条件分支、循环、并行执行,适配各类复杂问答场景。
- 多轮对话与记忆:支持上下文记忆、对话复盘、历史问答复用,贴合真实交互场景。
- 全链路可观测:支持检索日志、模型调用记录、工具执行记录、流程运行日志查询,便于运维优化。
1.3 整体架构设计
系统采用五层分层架构,从底层数据层到上层应用层层层解耦,支持模块化迭代升级,架构清晰、扩展性强。
- 数据资源层:包含私有知识库(PDF、Word、Excel、Txt、网页文档、业务台账)、实时互联网数据、企业业务API数据、结构化数据库数据。
- 数据处理层:实现文档清洗、文本拆分、向量化嵌入、向量库存储、数据增量更新、脏数据过滤。
- 核心引擎层:包含RAG检索引擎、AI Agent决策引擎、工具调用引擎、工作流调度引擎、对话记忆引擎。
- 模型服务层:集成通用大模型、行业微调模型、嵌入向量模型,提供文本生成、语义理解、向量计算能力。
- 应用交互层:包含Web问答界面、API接口、小程序、企业微信/钉钉接入端、后台管理运维平台。
二、核心技术原理详解
2.1 RAG检索增强生成技术
RAG是解决大模型知识滞后、幻觉问题的核心技术,核心逻辑为“先检索、后生成”。系统不依赖模型固有知识,而是先从专属知识库中检索相关上下文,将检索内容与用户问题拼接后输入大模型,生成精准、合规、可溯源的答案。
核心流程:文档解析→文本分块→向量化编码→向量库存储→用户问题向量化→相似度检索→上下文召回→大模型答案生成。
2.2 AI Agent智能代理技术
AI Agent是系统的“大脑决策中心”,具备自主感知、思考、决策、执行、迭代能力。区别于传统固定流程问答,Agent可自主判断用户问题属性:简单知识问题调用RAG检索、实时问题调用联网工具、复杂问题拆解为多个子任务分步执行,全程自主调度,无需人工配置固定问答规则。
核心能力:意图识别、任务拆解、工具选择、流程调度、结果校验、错误重试、记忆迭代。
2.3 大模型工具调用技术
工具调用是系统能力拓展的核心,通过大模型函数调用能力,将外部工具封装为标准化接口。系统可根据用户问题,自动调用对应工具完成专属任务,弥补纯文本问答的能力短板。
常用工具:全网搜索、学术搜索、数据库查询、Excel数据解析、公式计算、图片识别、接口数据拉取、代码运行、日期计算等。
2.4 工作流编排技术
工作流编排实现问答流程可视化、标准化、自动化,针对复杂问答场景,通过拖拽方式配置“检索-判断-工具调用-二次检索-答案整合”的全流程,支持条件分支、循环执行、并行处理、异常兜底,解决单一RAG和Agent无法适配复杂业务流程的问题。
三、系统核心模块组成
整套系统由6大核心模块构成,各模块独立运行、协同联动,支撑全场景智能问答能力。
3.1 知识库管理模块
支持多格式文档批量导入、自动解析、智能分块、去重清洗、增量更新、权限管理。适配PDF、Word、TXT、Markdown、Excel、网页链接、业务话术等各类数据源,支持知识库分类管理、标签管理、版本回溯。
3.2 RAG检索模块
集成语义检索、关键词检索、混合检索模式,支持相似度阈值自定义、检索条数配置、重排序(Rerank)优化、上下文关联召回,大幅提升检索精准度,避免无效内容召回。
3.3 AI Agent决策模块
内置智能决策引擎,支持问题意图分类、复杂任务拆解、执行路径自主选择、结果自检纠错、多轮对话记忆管理,可自主区分知识库问题、实时信息问题、计算类问题、业务接口问题。
3.4 工具调用模块
提供标准化工具封装模板,支持自定义新增工具、工具权限配置、工具调用日志记录、调用频率限制。内置通用工具库,同时支持对接企业自有业务API、数据库接口。
3.5 工作流编排模块
可视化拖拽工作流画布,支持节点配置(检索节点、模型生成节点、工具调用节点、条件判断节点、循环节点、结束节点),支持流程保存、发布、调试、版本管理、一键启用。
3.6 前台交互与后台运维模块
前台提供Web端智能对话界面,支持多轮对话、历史记录、答案溯源、内容复制、问题反馈;后台提供数据统计、日志查询、模型配置、知识库管理、工作流管理、权限管理、系统监控功能。
四、完整落地实施步骤
本实施步骤从环境准备到上线运维,全程可落地、可复用,分为8个核心阶段,适配私有化部署、云端部署两种模式。
阶段一:需求梳理与环境搭建(1-2天)
1. 需求梳理
- 明确问答场景:内部知识问答、智能客服、行业咨询、文档答疑等;
- 梳理数据源类型:私有文档、业务数据库、网页数据、实时资讯等;
- 确定所需工具:是否需要联网搜索、数据查询、接口调用、计算能力等;
- 确定部署方式:云端SaaS部署/企业私有化部署。
2. 环境部署
- 基础环境:部署Linux服务器、配置Docker容器环境(统一运行环境、降低兼容问题);
- 数据库环境:部署向量数据库(Milvus/FAISS/Chroma,推荐Milvus,适配企业级大数据量)、业务数据库(MySQL);
- 模型环境:接入大模型API(GPT、文心一言、通义千问、本地开源模型均可)、接入向量嵌入模型、Rerank重排序模型;
- 依赖安装:安装文本解析、向量化、工作流调度相关依赖包。
阶段二:数据源整理与知识库构建(2-3天)
1. 数据收集与清洗
收集场景对应所有私有数据,剔除空白内容、重复内容、无效水印、广告信息、乱码内容,统一文档格式,保证数据源干净合规。
2. 文档解析与智能分块
- 文档解析:通过解析工具提取PDF、Word、Excel等文档的纯文本内容,保留标题、段落、表格核心信息;
- 智能分块:采用“固定长度+语义分块”结合模式,单块文本长度设置500-1000字,保证单块内容语义完整,避免拆分关键信息;
- 分块优化:对标题、目录、段落、表格单独处理,提升后续检索精准度。
3. 文本向量化与知识库入库
- 调用向量嵌入模型,将分块后的文本转化为多维向量;
- 将向量数据、原始文本、文档来源、标签信息同步存入向量数据库;
- 完成知识库分类、标签配置、权限分组,构建结构化专属知识库。
阶段三:RAG检索引擎配置与优化(1-2天)
1. 检索策略配置
配置混合检索策略:语义相似度检索为主、关键词检索为辅,兼顾语义匹配和精准词条匹配。设置检索相似度阈值(默认0.7),过滤低相关无效内容,配置单次召回文本条数(3-6条)。
2. 重排序优化
接入Rerank重排序模型,对初次召回的多条文本进行二次打分排序,优先保留与用户问题高度相关的上下文,解决传统向量检索排序不准的问题。
3. Prompt工程优化
定制专属问答提示词,约束大模型输出规则:基于检索内容作答、无对应知识明确告知、答案标注来源、禁止编造信息、适配场景话术风格,从根源解决模型幻觉问题。
阶段四:工具封装与工具调用能力搭建(1-2天)
1. 通用工具接入
根据场景需求,封装所需工具,完成接口调试:联网搜索工具、日期计算工具、数据统计工具、文档解析工具、代码执行工具等。
2. 自定义业务工具开发
对接企业自有业务API、数据库,封装专属业务工具,例如:员工信息查询、订单数据查询、政策条款校验、业务流程查询等。统一工具入参、出参格式,适配大模型函数调用规范。
3. 工具权限与调度配置
设置工具调用权限、调用频率、超时机制、异常兜底策略,避免工具滥用、调用超时导致问答失败。
阶段五:AI Agent决策引擎配置(1天)
1. 意图识别规则配置
为Agent配置问题分类规则,实现自主识别:私有知识库问题→调用RAG检索;实时动态问题→调用联网搜索;计算/数据查询问题→调用对应工具;复杂综合问题→拆解多子任务执行。
2. 任务拆解与迭代配置
开启Agent自主任务拆解能力,针对多维度复杂问题,自动拆分多个子问题,分步调用检索、工具能力,最终整合所有子结果,生成完整答案。同时配置结果自检机制,对不合理答案自动重试优化。
3. 对话记忆配置
配置短期对话记忆(单次会话上下文)和长期记忆(历史问答沉淀),支持多轮对话连贯交互,理解上下文指代关系。
阶段六:可视化工作流编排(2天)
针对复杂业务问答场景,通过可视化画布编排标准化问答工作流,以「企业政策智能问答」为例,标准工作流配置步骤如下:
- 输入节点:接收用户提问,清洗无效字符、标准化问题格式;
- 意图判断节点:Agent识别问题类型,生成分支路径;
- 分支1(知识库问题):触发RAG检索→重排序→上下文拼接→模型生成答案;
- 分支2(实时问题):触发联网搜索→数据清洗→有效信息提取→模型整合作答;
- 分支3(业务数据问题):触发业务工具调用→数据查询→数据解析→结构化输出;
- 结果校验节点:校验答案完整性、准确性,异常则触发重试或兜底回复;
- 溯源标注节点:自动标注答案来源文档、检索时间、工具调用记录;
- 输出节点:输出标准化问答结果,保存对话日志。
编排完成后保存流程、一键发布,支持后续随时修改迭代流程,无需代码开发。
阶段七:系统联调、测试与优化(2天)
1. 全链路联调
对知识库检索、Agent决策、工具调用、工作流执行、对话交互全链路调试,排查接口超时、检索失效、工具调用失败、流程卡顿等问题。
2. 场景化测试
覆盖简单问题、复杂问题、模糊问题、实时问题、业务专属问题、无效问题等多类测试用例,统计问答准确率、响应速度、错误率。
3. 针对性优化
- 检索不准:优化分块策略、调整相似度阈值、升级Rerank模型;
- 回答空洞:优化Prompt、增加上下文召回数量;
- 工具调用失败:优化工具参数、增加异常重试机制;
- 流程卡顿:精简工作流节点、优化接口响应速度。
阶段八:系统上线、运维与迭代(长期)
1. 正式上线
部署前台交互界面、开放API接口,完成企业终端接入(Web、小程序、企微/钉钉),配置后台管理员权限、数据备份策略。
2. 日常运维
实时监控系统响应速度、模型调用状态、工具运行状态、服务器负载;定期清理无效日志、备份知识库数据、排查系统漏洞。
3. 持续迭代
根据用户问答反馈,持续更新知识库、优化工作流、新增工具能力、迭代Prompt规则,不断提升问答准确率和场景适配度。
五、系统核心优化方案
5.1 检索优化
采用「语义分块+混合检索+Rerank重排+上下文关联召回」四重优化策略,解决传统RAG检索碎片化、精准度低的问题,大幅提升有效信息召回率。
5.2 Agent决策优化
通过Few-shot示例训练、决策Prompt迭代、错误案例复盘,提升Agent意图识别和任务拆解准确率,减少无效工具调用、错误流程触发问题。
5.3 输出内容优化
配置答案结构化输出规则、溯源标注、话术标准化,同时开启内容过滤机制,规避违规内容、虚假信息,保证问答内容合规、准确、专业。
5.4 性能优化
开启向量检索缓存、对话缓存,减少重复计算;优化工作流执行逻辑,精简冗余节点;支持知识库增量更新,无需全量重构,提升系统响应速度和运行稳定性。
六、落地场景与价值
6.1 核心落地场景
- 企业内部知识问答:员工制度、流程规范、培训文档智能答疑;
- 智能客服系统:产品咨询、售后问题、政策解读自动回复;
- 政务/行业答疑:政策文件、规章制度、行业标准智能解读;
- 科研/技术问答:论文、技术文档、开发手册智能咨询;
- 数据智能查询:对接业务数据库,实现自然语言查数据、做统计。
6.2 项目落地价值
- 降本增效:替代人工重复答疑,降低人力成本,7×24小时不间断服务;
- 精准可控:答案基于私有知识库生成,可溯源、可管控,杜绝模型幻觉;
- 灵活拓展:模块化设计,支持随时新增知识库、工具、工作流,适配业务迭代;
- 自主智能:Agent自主处理复杂问题,无需人工配置大量问答规则,运维成本极低。
七、常见问题与解决方案
- 问答准确率低:优化文档分块、开启Rerank重排、迭代Prompt、补充缺失知识库内容;
- 工具调用频繁出错:标准化工具入参出参、增加参数校验、配置重试与兜底机制;
- 复杂问题回答不完整:优化Agent任务拆解逻辑、编排精细化工作流、增加多轮迭代生成;
- 系统响应缓慢:开启缓存、优化向量库索引、精简工作流节点、升级服务器配置;
- 存在幻觉内容:强化Prompt约束、开启答案溯源校验、过滤无来源生成内容。
一、部署配置清单(可直接复制用于立项 / 部署文档)
1.1 硬件资源配置
私有化部署(企业生产环境)
表格
| 组件 | 推荐配置 | 说明 |
|---|---|---|
| 应用服务节点 | CPU 16 核,内存 32G,磁盘 SSD 500G | Agent、工作流编排、API 服务、文档解析服务 |
| 向量数据库 Milvus | CPU 16 核,内存 64G,SSD 1TB | 100 万以内向量规模;向量越大内存越高 |
| 业务数据库 MySQL | CPU 8 核,内存 16G,SSD 500G | 存储对话日志、用户、知识库元数据、工作流定义 |
| 对象存储 | 200G+ | 原始文档、附件存储 |
| GPU(本地模型模式) | A10‑24G / 2*A10‑24G | 运行 Embedding、Rerank、开源大模型;调用公有云 API 可不用 GPU |
测试环境最小配置:8 核 16G 机器,Docker Compose 一键拉起 Milvus+Chroma+MySQL,适合原型验证。
1.2 软件 & 组件栈清单
基础中间件
- 容器:Docker 24+、Docker‑Compose
- 业务库:MySQL 8.0
- 向量库:Milvus 2.4.x(生产);Chroma(原型测试)
- 消息队列:RocketMQ / RabbitMQ(可选,用于异步文档解析、任务队列)
- 缓存:Redis 7.x(对话记忆、检索缓存、工具调用限流)
AI 模型列表
表格
| 模型类型 | 选型建议 |
|---|---|
| 主大模型(Agent 推理、生成) | 通义千问‑Qwen‑72B / Qwen2‑72B / GLM‑4;公有云 API 或私有化 |
| Embedding 向量模型 | bge‑large‑zh / bge‑m3 |
| Rerank 重排序模型 | bge‑reranker‑large‑zh |
核心开源组件参考(自研二次开发基线)
- RAG:LangChain4j / LangChain
- Agent + 工具调用:LangChain4j、Spring‑AI‑Alibaba、LlamaIndex
- 工作流编排:Camunda / Flowable(后端流程引擎);前端自研拖拽画布;轻量原型可用 Dify / Flowise 做验证
- 文档解析:Apache‑Tika、PyPDF、MarkItDown(解析 PDF/Word/Excel/PPT)
1.3 网络与安全配置
- 向量库、MySQL 禁止公网暴露,内网访问;
- 工具调用增加白名单,防止 Agent 访问内部高危接口;
- 模型 API 密钥配置环境变量,禁止硬编码;
- 接口增加鉴权 token、限流;
- 对话日志敏感信息脱敏。
1.4 环境变量示例(docker .env)
# 大模型
LLM_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
LLM_API_KEY=sk-xxx
LLM_MODEL_NAME=qwen2-72b-instruct
# Embedding/Rerank
EMBEDDING_MODEL=bge-large-zh
RERANK_MODEL=bge-reranker-large-zh
# Milvus向量库
MILVUS_HOST=127.0.0.1
MILVUS_PORT=19530
MILVUS_USER=root
MILVUS_PASSWORD=Milvus@2026
# MySQL
MYSQL_HOST=127.0.0.1
MYSQL_PORT=3306
MYSQL_DB=agent_rag_qa
MYSQL_USER=root
MYSQL_PWD=Root@2026
# Redis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PWD=Redis@2026
# 系统参数
MAX_RETRIEVE_NUM=5
RERANK_TOP_K=3
SIMILARITY_THRESHOLD=0.70
AGENT_MAX_ITERATION=5
二、全套可直接复用 Prompt 模板
说明:分为 RAG 基础 Prompt、Agent 系统 Prompt、工具调用约束 Prompt、工作流结果校验 Prompt、兜底回复 Prompt。
2.1 RAG 知识库问答 Prompt(基础生成)
你是企业内部智能问答助手,请严格基于【参考上下文】回答用户问题。
【参考上下文】
{context}
规则:
1. 只使用上面参考上下文内的信息作答,严禁编造、臆测不存在的内容。
2. 如果参考上下文没有相关信息,直接回复:“知识库中未查询到相关信息,请换一种方式提问或联系人工。”,不要自行发挥。
3. 回答尽量条理清晰,分点输出,语言简洁专业。
4. 回答末尾标注信息来源文档名称:【来源:xxx】
5. 禁止输出上下文以外的知识,杜绝幻觉。
用户问题:
{question}
2.2 Agent 决策系统 Prompt(核心,用于工具调用、任务拆解)
你是智能问答系统Agent大脑,负责分析用户问题,决定执行策略。
可使用能力列表:
1. RAG知识库检索:查询企业私有文档、制度、手册;适合企业内部静态知识。
2. search联网搜索:获取互联网实时、最新外部信息。
3. custom_biz_tool业务工具:调用业务接口,查询订单、人员、台账等业务数据。
4. calc计算工具:数学计算、日期运算。
决策规则:
1. 如果问题属于企业内部静态知识 → 调用RAG知识库检索。
2. 如果问题需要最新实时互联网信息 → 调用search联网搜索。
3. 如果需要查询业务数据库、业务数据 → 调用custom_biz_tool业务工具。
4. 如果包含数学、日期计算 → 调用calc计算工具。
5. 复杂问题可以拆分为多个子任务,依次调用多个工具,最多允许{max_iter}轮工具调用。
6. 每一步执行完成后,评估已有信息是否足够回答用户;信息不足继续调用工具;信息充足则整合全部结果输出答案。
7. 禁止编造数据;工具返回无结果时不要强行生成答案,使用兜底话术。
8. 多轮对话需要结合历史上下文理解用户指代。
输出格式要求:
必须输出标准function call格式,不要自然语言描述要做什么。
如果信息已经足够,直接输出最终回答。
对话历史:
{chat_history}
用户当前提问:
{user_query}
2.3 工具调用返回结果整合 Prompt(工具执行完后)
下面是各个工具返回的执行结果,结合用户问题,整理出完整准确回答。
【工具执行结果集合】
{tool_result_list}
规则:
1. 整合全部有效信息,去重,逻辑梳理。
2. 如果多个工具结果冲突,客观展示冲突点,不要主观取舍。
3. 如果工具返回为空/失败,明确告知用户该部分无法获取。
4. 禁止脑补补充工具没有给出的数据。
5. 输出结构清晰,必要时分点。
用户问题:{user_query}
2.4 工作流结果校验 Prompt(工作流中校验节点使用,判断答案质量)
你作为结果校验器,校验待输出答案是否满足下面要求:
校验项:
1. 是否存在编造、幻觉内容;
2. 是否回答了用户原始问题;
3. 信息来源是否可靠;
4. 是否出现重要信息缺失。
输入:
用户问题:{user_question}
待校验答案:{candidate_answer}
输出JSON格式,只输出JSON:
{{
"pass": true/false,
"reason": "校验原因",
"suggestion": "如果不通过给出优化建议,通过填空字符串"
}}
2.5 兜底异常 Prompt(检索无结果、工具调用失败、Agent 执行超限)
很抱歉,暂时无法为您解答该问题。
可能原因:
1. 知识库暂无相关资料;
2. 外部工具调用异常;
3. 问题描述不够清晰。
建议:
- 调整提问关键词重新提问;
- 联系人工客服获取支持。
2.6 Few‑shot 示例(加入 Agent Prompt 提升决策准确率,Few‑shot 样例)
【示例1】
用户:公司的年假制度是什么?
思考:属于企业内部制度静态知识 → 调用RAG知识库检索
【示例2】
用户:今天A股大盘多少点?
思考:需要实时互联网数据 → 调用search联网搜索
【示例3】
用户:查询张三的本月考勤记录
思考:需要业务数据 → 调用custom_biz_tool业务工具
【示例4】
用户:5000元按年利率3.2%存3年利息多少
思考:数学计算 → 调用calc计算工具
三、关键参数调优参考表(生产调优直接对照)
表格
| 参数 | 推荐值 | 说明 |
|---|---|---|
| 文本分块大小 | 500‑800 token | 语义分块优先;表格、短文档适当缩小 |
| 向量检索 top_k | 4‑6 | 初筛召回数量 |
| Rerank 后 top_k | 2‑3 | 重排序之后送入 LLM 上下文 |
| 相似度阈值 | 0.65‑0.72 | 知识库质量差调低,质量高调高 |
| Agent 最大迭代轮次 | 4‑5 | 防止无限循环调用工具 |
| 单轮上下文最大 token | 4096 | 防止 Prompt 超限 |
| 对话记忆窗口 | 最近 6 轮 | 多轮对话,避免上下文膨胀 |
LangChain4j + SpringBoot 核心接口伪代码
技术栈:SpringBoot3 + LangChain4j 0.34.x + Milvus 向量库 + Spring‑AI‑Alibaba(可选) 包含:知识库文档入库、RAG 检索接口、Agent 工具调用、工作流编排简易实现、对话问答对外 API;伪代码可直接改造为生产代码。 依赖 maven 先给出,再是核心 Java 代码。
Maven 核心依赖 pom.xml
<dependencies>
<!-- spring boot web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- LangChain4j 核心 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-spring-boot-starter</artifactId>
<version>0.34.0</version>
</dependency>
<!-- dashscope 通义千问兼容 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
<version>0.34.0</version>
</dependency>
<!-- Milvus向量库 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-milvus</artifactId>
<version>0.34.0</version>
</dependency>
<!-- BGE embedding / rerank -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-hugging-face</artifactId>
<version>0.34.0</version>
</dependency>
<!-- tika文档解析 -->
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>2.9.1</version>
</dependency>
</dependencies>
application.yml 配置片段
langchain4j:
open-ai:
base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
api-key: ${LLM_API_KEY}
chat-model:
model-name: qwen2-72b-instruct
temperature: 0.01
max-tokens: 2048
embedding-model:
provider: hugging-face
hugging-face:
model-name: BAAI/bge-large-zh
milvus:
host: ${MILVUS_HOST:127.0.0.1}
port: 19530
collection-name: agent_rag_collection
dimension: 1024
metric-type: COSINE
1. 文档入库服务:文档解析 → 分块 → 向量化存入 Milvus
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.DocumentParser;
import dev.langchain4j.data.document.parser.apache.tika.ApacheTikaDocumentParser;
import dev.langchain4j.data.document.splitter.DocumentSplitters;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
@Service
public class KnowledgeBaseIngestService {
private final DocumentParser tikaParser = new ApacheTikaDocumentParser();
private final EmbeddingModel embeddingModel;
private final EmbeddingStore<TextSegment> milvusEmbeddingStore;
public KnowledgeBaseIngestService(EmbeddingModel embeddingModel,
EmbeddingStore<TextSegment> milvusEmbeddingStore) {
this.embeddingModel = embeddingModel;
this.milvusEmbeddingStore = milvusEmbeddingStore;
}
/**
* 上传文档,构建知识库
* @param file 上传文件 pdf/word/txt
* @param docSource 来源文件名
*/
public void ingestDocument(MultipartFile file, String docSource) throws Exception {
// 1.解析文档
Document document = tikaParser.parse(file.getInputStream());
// 设置元数据:文档来源
document.metadata().add("source", docSource);
// 2.语义分块:510token,重叠80token
var splitter = DocumentSplitters.recursive(510, 80);
// 3. ingestion:分块、向量化、写入Milvus
EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
.documentSplitter(splitter)
.embeddingModel(embeddingModel)
.embeddingStore(milvusEmbeddingStore)
.build();
ingestor.ingest(document);
}
}
2. RAG 检索服务(混合检索 + Rerank 重排)
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.rerank.RerankModel;
import dev.langchain4j.store.embedding.EmbeddingMatch;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.RelevanceScore;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class RagRetrieveService {
private final EmbeddingStore<TextSegment> embeddingStore;
private final EmbeddingModel embeddingModel;
private final RerankModel rerankModel;
@Value("${rag.top-k:5}")
private int topK;
@Value("${rag.threshold:0.65}")
private double scoreThreshold;
@Value("${rag.rerank-top:3}")
private int rerankTop;
public RagRetrieveService(EmbeddingStore<TextSegment> embeddingStore,
EmbeddingModel embeddingModel,
RerankModel rerankModel) {
this.embeddingStore = embeddingStore;
this.embeddingModel = embeddingModel;
this.rerankModel = rerankModel;
}
/**
* RAG检索:向量初筛 -> Rerank重排序 -> 返回上下文片段
*/
public List<TextSegment> retrieve(String userQuery) {
// 向量检索
var queryEmbedding = embeddingModel.embed(userQuery).content();
List<EmbeddingMatch<TextSegment>> matches = embeddingStore.findRelevant(queryEmbedding, topK, scoreThreshold);
List<TextSegment> candidateSegments = matches.stream()
.map(EmbeddingMatch::embedded)
.collect(Collectors.toList());
if(candidateSegments.isEmpty()){
return List.of();
}
// Rerank重排序
var rerankResp = rerankModel.rerank(userQuery, candidateSegments, rerankTop);
return rerankResp.results().stream()
.map(r -> r.input())
.collect(Collectors.toList());
}
// 拼接参考上下文给LLM
public String buildContext(List<TextSegment> segments){
StringBuilder sb = new StringBuilder();
for (TextSegment seg : segments) {
String source = seg.metadata().get("source");
sb.append(seg.text()).append("\n【来源:").append(source).append("】\n");
}
return sb.toString();
}
}
3. 自定义工具定义(Agent 可调用工具示例)
两种工具:业务查询工具、联网搜索模拟工具,供 Agent function‑call 调用
import dev.langchain4j.agent.tool.Tool;
import org.springframework.stereotype.Component;
@Component
public class CustomBizTools {
/**
* 业务工具:示例,查询员工考勤
*/
@Tool("根据员工姓名查询员工本月考勤记录,参数:staffName员工姓名")
public String queryStaffAttendance(String staffName){
// 实际这里调用mybatis/mapper查mysql业务表
return "员工["+staffName+"]本月出勤22天,请假0天";
}
/**
* 联网搜索工具
*/
@Tool("互联网实时搜索,用于获取最新外部信息,query搜索关键词")
public String webSearch(String query){
// 实际调用搜索引擎API(serpapi/duckduckgo)
return "模拟互联网搜索结果,query:"+query;
}
/**
* 计算工具
*/
@Tool("数学计算器,expression数学表达式,例如 1000 * 0.032 *3")
public String calc(String expression){
// 脚本执行计算,注意安全沙箱
return "计算结果";
}
}
4. AI Agent 服务(带工具调用、记忆)
import dev.langchain4j.agent.Agent;
import dev.langchain4j.agent.tool.ToolSpecification;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
import org.springframework.stereotype.Service;
@Service
public class AgentService {
private final ChatLanguageModel chatModel;
private final CustomBizTools customBizTools;
private final RagRetrieveService ragRetrieveService;
public AgentService(ChatLanguageModel chatModel,
CustomBizTools customBizTools,
RagRetrieveService ragRetrieveService) {
this.chatModel = chatModel;
this.customBizTools = customBizTools;
this.ragRetrieveService = ragRetrieveService;
}
// Agent接口定义,AiServices动态代理
interface SmartAgentAssistant {
@SystemMessage("""
你是智能问答Agent大脑。
规则:
1.企业内部知识调用RAG检索;实时信息调用webSearch;业务数据调用queryStaffAttendance;数学使用calc。
2.最多迭代5轮工具调用,信息足够直接输出答案,不要编造。
3.当需要知识库信息时,请调用ragRetrieve方法获取参考上下文。
""")
String chat(@UserMessage String userQuestion);
}
/**
* 创建会话Agent实例,每个session独立记忆
* @param sessionId 会话id
* @return assistant
*/
public SmartAgentAssistant createAgent(String sessionId){
ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(12);
return AiServices.builder(SmartAgentAssistant.class)
.chatLanguageModel(chatModel)
.chatMemory(chatMemory)
.tools(customBizTools) //注册工具
.build();
}
/**
* Agent对话入口
*/
public String agentChat(String sessionId, String question){
SmartAgentAssistant assistant = createAgent(sessionId);
return assistant.chat(question);
}
}
5. 简易工作流编排服务(代码版工作流,对应画布编排逻辑)
生产可替换 Camunda/Flowable;此处模拟流程节点:输入→意图判断→RAG 分支 / 工具分支→结果校验→输出
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.output.Response;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class SimpleWorkflowService {
private final RagRetrieveService ragRetrieveService;
private final AgentService agentService;
private final ChatLanguageModel chatModel;
public SimpleWorkflowService(RagRetrieveService ragRetrieveService,
AgentService agentService,
ChatLanguageModel chatModel) {
this.ragRetrieveService = ragRetrieveService;
this.agentService = agentService;
this.chatModel = chatModel;
}
/**
* 模拟工作流:用户提问 → 分支选择 → 执行 → 校验 → 返回
*/
public WorkflowResp executeWorkflow(String sessionId, String userQuery){
// 节点1:输入清洗
String cleanQuery = userQuery.trim();
// 节点2:意图判断(简化;生产可单独意图分类模型)
IntentType intent = detectIntent(cleanQuery);
String rawAnswer;
List<TextSegment> segments;
switch (intent){
case RAG_KNOWLEDGE:
segments = ragRetrieveService.retrieve(cleanQuery);
String context = ragRetrieveService.buildContext(segments);
String ragPrompt = buildRagPrompt(context, cleanQuery);
Response<AiMessage> resp = chatModel.generate(ragPrompt);
rawAnswer = resp.content().text();
break;
case AGENT_TOOL:
rawAnswer = agentService.agentChat(sessionId, cleanQuery);
break;
default:
rawAnswer = "知识库中未查询到相关信息,请换一种方式提问或联系人工。";
}
// 节点:结果校验
CheckResult check = validateAnswer(cleanQuery, rawAnswer);
WorkflowResp resp = new WorkflowResp();
resp.question = userQuery;
resp.rawAnswer = rawAnswer;
resp.pass = check.pass;
resp.checkReason = check.reason;
resp.finalAnswer = check.pass ? rawAnswer : "很抱歉,暂时无法为您解答该问题,请联系人工客服。";
return resp;
}
// 模拟意图枚举
public enum IntentType {
RAG_KNOWLEDGE, AGENT_TOOL, UNKNOWN
}
private IntentType detectIntent(String q){
// 生产替换为LLM意图识别逻辑
return IntentType.AGENT_TOOL;
}
// RAG prompt组装
private String buildRagPrompt(String context, String question){
return String.format("""
请严格基于【参考上下文】回答。
【参考上下文】
%s
如果没有信息直接回复未查询到,禁止编造。
用户问题:%s
""", context, question);
}
// 结果校验调用LLM校验器
private CheckResult validateAnswer(String question, String candidate){
// 调用校验Prompt,返回pass/reason
return new CheckResult(true,"校验通过");
}
// DTO
public static class WorkflowResp{
public String question;
public String rawAnswer;
public boolean pass;
public String checkReason;
public String finalAnswer;
}
public static class CheckResult{
public boolean pass;
public String reason;
public CheckResult(boolean pass,String reason){
this.pass=pass;this.reason=reason;
}
}
}
6. Controller 对外 HTTP 接口
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequestMapping("/api/qa")
public class QaController {
private final KnowledgeBaseIngestService ingestService;
private final SimpleWorkflowService workflowService;
public QaController(KnowledgeBaseIngestService ingestService, SimpleWorkflowService workflowService) {
this.ingestService = ingestService;
this.workflowService = workflowService;
}
更多推荐



所有评论(0)