基于AI Agent、RAG、工具调用与工作流编排的智能问答系统完整实施方案

一、方案整体概述

1.1 项目背景与目标

传统智能问答系统普遍存在知识库固化、无法实时联网更新、不会调用外部工具、复杂问题拆解能力弱、问答准确率低等问题,无法满足企业复杂业务咨询、智能客服、内部知识问答、文档答疑等场景的高阶需求。

本方案融合AI智能代理(Agent)、检索增强生成(RAG)、大模型工具调用、可视化工作流编排四大核心技术,搭建一套轻量化、可扩展、可定制的通用智能问答系统。系统具备自主问题拆解、知识库精准检索、外部工具联动、流程自动化执行、多轮对话记忆、答案溯源纠错能力,可适配企业内部知识库问答、客户智能客服、公文答疑、技术文档问答、行业智能咨询等全场景。

1.2 核心能力亮点

  • RAG精准知识库问答:依托私有文档、业务数据构建专属知识库,解决大模型幻觉、知识滞后问题,答案可溯源、可审核。
  • AI Agent自主决策:无需人工干预,自主判断问题类型、选择处理方式、拆解复杂任务、迭代优化回答结果。
  • 通用工具调用能力:支持联网搜索、数据查询、接口调用、公式计算、文档解析、代码执行等第三方工具拓展。
  • 可视化工作流编排:拖拽式配置问答流程,支持条件分支、循环、并行执行,适配各类复杂问答场景。
  • 多轮对话与记忆:支持上下文记忆、对话复盘、历史问答复用,贴合真实交互场景。
  • 全链路可观测:支持检索日志、模型调用记录、工具执行记录、流程运行日志查询,便于运维优化。

1.3 整体架构设计

系统采用五层分层架构,从底层数据层到上层应用层层层解耦,支持模块化迭代升级,架构清晰、扩展性强。

  1. 数据资源层:包含私有知识库(PDF、Word、Excel、Txt、网页文档、业务台账)、实时互联网数据、企业业务API数据、结构化数据库数据。
  1. 数据处理层:实现文档清洗、文本拆分、向量化嵌入、向量库存储、数据增量更新、脏数据过滤。
  1. 核心引擎层:包含RAG检索引擎、AI Agent决策引擎、工具调用引擎、工作流调度引擎、对话记忆引擎。
  1. 模型服务层:集成通用大模型、行业微调模型、嵌入向量模型,提供文本生成、语义理解、向量计算能力。
  1. 应用交互层:包含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天)

针对复杂业务问答场景,通过可视化画布编排标准化问答工作流,以「企业政策智能问答」为例,标准工作流配置步骤如下:

  1. 输入节点:接收用户提问,清洗无效字符、标准化问题格式;
  1. 意图判断节点:Agent识别问题类型,生成分支路径;
  1. 分支1(知识库问题):触发RAG检索→重排序→上下文拼接→模型生成答案;
  1. 分支2(实时问题):触发联网搜索→数据清洗→有效信息提取→模型整合作答;
  1. 分支3(业务数据问题):触发业务工具调用→数据查询→数据解析→结构化输出;
  1. 结果校验节点:校验答案完整性、准确性,异常则触发重试或兜底回复;
  1. 溯源标注节点:自动标注答案来源文档、检索时间、工具调用记录;
  1. 输出节点:输出标准化问答结果,保存对话日志。

编排完成后保存流程、一键发布,支持后续随时修改迭代流程,无需代码开发。

阶段七:系统联调、测试与优化(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 500GAgent、工作流编排、API 服务、文档解析服务
向量数据库 MilvusCPU 16 核,内存 64G,SSD 1TB100 万以内向量规模;向量越大内存越高
业务数据库 MySQLCPU 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

核心开源组件参考(自研二次开发基线)

  1. RAG:LangChain4j / LangChain
  2. Agent + 工具调用:LangChain4j、Spring‑AI‑Alibaba、LlamaIndex
  3. 工作流编排:Camunda / Flowable(后端流程引擎);前端自研拖拽画布;轻量原型可用 Dify / Flowise 做验证
  4. 文档解析:Apache‑Tika、PyPDF、MarkItDown(解析 PDF/Word/Excel/PPT)

1.3 网络与安全配置

  1. 向量库、MySQL 禁止公网暴露,内网访问;
  2. 工具调用增加白名单,防止 Agent 访问内部高危接口;
  3. 模型 API 密钥配置环境变量,禁止硬编码;
  4. 接口增加鉴权 token、限流;
  5. 对话日志敏感信息脱敏。

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_k4‑6初筛召回数量
Rerank 后 top_k2‑3重排序之后送入 LLM 上下文
相似度阈值0.65‑0.72知识库质量差调低,质量高调高
Agent 最大迭代轮次4‑5防止无限循环调用工具
单轮上下文最大 token4096防止 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;
    }
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐