尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

AgentScope Java实战:给Agent装上工具与知识库

AgentScope Java实战:给Agent装上工具与知识库 我不打算从“AgentScope 是什么”这种教科书定义开始——能点进这个标题的人多半已经在动手写了。这篇是 AgentScope Java 实战系列的第三篇。前两篇我们搞定了 Agent 的“大脑”基础结构模型接入、消息协议、多轮对话链路这次要解决的是一件更实在的事怎么让 Agent 不只是“会聊天”而是真正“会干活”。干活靠什么靠手也靠书架。手是工具Tool书架是知识Knowledge。在这套比喻里AgentScope Java 的知识与工具层就是给 Agent 装上这两样东西的地方。这篇内容我会围绕三层展开讲为什么知识与工具层要分开设计、AgentScope Java 里工具注册和知识检索具体怎么写、以及我在实际项目中踩过的坑和排查经验。如果你已经跑通了前面两篇的基础对话流程这篇跟着敲完你就能得到一个能调用外部 API、能基于自有文档回答问题的完整 Agent 雏形。1. 先搞清楚知识与工具层到底管什么1.1 “手”和“书架”分别解决什么问题在 Agent 这个领域模型本身只负责“思考”不负责“执行”和“记忆外的事实”。如果你让大模型算一笔复杂的账、查一个实时的天气、翻一份公司内部制度文档它要么瞎编要么说“我不知道”。知识与工具层就是来解决这两个短板的。工具层解决的是“动作”问题。Agent 判断当前需要执行一个外部操作时比如查数据库、调用接口、发邮件、执行一段计算通过工具层把意图翻译成真实的函数调用再把结果回传给模型继续推理。没有工具层Agent 就是一个只会纸上谈兵的清谈客。知识层解决的是“事实”问题。模型训练数据有截止时间也不包含你私有领域的内容。通过知识层把文档切片、向量化、存入检索库在对话时先做相似度检索把相关知识片段拼进提示词上下文模型回答就有了依据。没有知识层Agent 就是个没有常识积累的健忘者。这两层在 AgentScope Java 里是作为 Agent 的独立组件存在的。在官方设计里你可以分别往 Agent 上挂载 Tool 列表和 Knowledge 列表Agent 运行时统一调度。关键词统一调度。这也是在代码里设计和在文档里看图最大的区别——你要理解 Agent 拿到一个问题后是在什么样的循环机制里去使用这些组件的。1.2 AgentScope Java 的运行时循环ReAct 模式AgentScope Java 的 Agent 内核遵循的是业界主流的 ReAct 模式Reasoning Acting。简单说模型在每一轮推理中会经历一个循环观察接收用户的 query以及当前已有的对话历史。推理模型判断自己是否需要调用工具、是否需要查知识库然后输出一个结构化的决策比如“我要调用 get_weather 这个工具参数是北京”。行动Agent 运行时解析模型的决策执行工具调用或知识检索。观察结果把工具返回的结果或知识检索到的片段作为新的消息回填给模型。再推理模型结合回填内容生成面向用户的最终回答或者继续发出下一轮工具调用。这个循环会一直持续到模型认为信息已经足够给出最终答复为止。你的知识和工具在这套循环中的角色是“中间件”它们不决定 Agent 说什么但决定 Agent 能“看到”什么、能“做到”什么。理解这个循环至关重要。我见过不少人一上来就写一堆工具方法结果 Agent 根本不会主动调用原因就是没理解 ReAct 循环里模型需要看到“工具的使用说明书”而不是只看到“工具的实现代码”。工具层和知识层的本质是给模型提供“接口契约”和“检索入口”而不是给 Java 工程师提供一堆函数。2. 工具层实现怎么给 Agent 装上“手”2.1 工具注册从 Java 方法到模型可见的“说明书”在 AgentScope Java 里工具不是随便写个 public 方法就能被调用的。它需要经过一道“注册”工序把我们熟悉的 Java 方法转换成模型可以理解的结构化描述。这个描述通常包括三件事工具名tool name、功能描述description、参数结构parameters schema。先看一个最基础的工具定义。假设我们要给 Agent 一个“查询城市天气”的工具public class WeatherTool { AgentTool( name get_weather, description 查询指定城市的实时天气情况当用户询问天气时必须调用此工具, parameters { ToolParam(name city, type String.class, description 城市名称如北京、上海, required true) } ) public String getWeather(String city) { // 这里实际去调用天气 API或者查缓存 return 北京今日晴气温 22℃~31℃风力 3 级; } }这里用了注解标注框架在 Agent 启动时会扫描这些注解自动生成 JSON Schema 并注入到模型的系统提示词里。模型看到的不是这段 Java 代码而是类似这样的一份 JSON 描述简化版{ type: function, function: { name: get_weather, description: 查询指定城市的实时天气情况当用户询问天气时必须调用此工具, parameters: { type: object, properties: { city: { type: string, description: 城市名称如北京、上海 } }, required: [city] } } }模型看到这份 JSON 后当用户说“北京明天需要带伞吗”模型就会在推理中输出类似“调用工具 get_weather参数 city北京”的结构化指令Agent 运行时解析并反射调用你的 getWeather() 方法拿到返回值后拼接成一条工具结果消息再次交给模型。这里有几个细节要单独拎出来说第一description 是给模型看的不是给程序员看的。很多团队写工具描述敷衍了事写个“查询天气”四个字。但模型是靠描述来决定什么时候调用工具的描述越明确调用率越准。我总结的写法是触发条件 工具能力 示例。比如“当用户询问任何城市的当前天气或未来天气预报时必须调用此工具获取实时数据如‘北京天气怎么样’、‘上海明天会不会下雨’”。模型不是人它不会脑补你的意图你得把触发场景写透。第二参数描述里要写明格式要求。模型会根据工具描述生成参数值。如果参数要求是“YYYY-MM-DD”格式的日期你不在描述里写清楚模型很可能生成“2025-01-15”之外的格式比如“1月15日”或“今天”导致你的工具解析失败。这就是典型的“模型与工程之间的契约摩擦”需要用参数描述来消除。第三编码问题。Java 方法签名里的中文描述、中文返回值在转成 JSON Schema 和回填上下文时都需要确认框架使用的是什么字符集。我在本地实测中遇到过框架默认设置下中文参数被转成乱码的情况解决办法是在 Agent 配置里显式指定 UTF-8 的消息编码。这个问题在后续会细说。2.2 工具执行流程Agent 怎么调用你的方法模型输出“我要调用工具 get_weathercity 参数值为北京”这只是一种中间指令Agent 运行时需要把它“翻译”成真实的 Java 方法调用。AgentScope Java 的执行流程大致是这样的模型返回一个带有工具调用块function call block的消息内容包含工具名和参数 JSON。框架根据工具名在注册表里查找对应的 Java 方法。框架用 JSON 反序列化工具把参数 JSON 转换成 Java 方法所需的类型。这里涉及类型映射如果 Schema 里定义的是 string 而你的方法参数是 int框架会尝试转换。转换失败时会抛出工具执行异常。框架通过反射调用你的方法捕获返回值。返回值被包装成一条工具消息标记上对应的工具调用 ID追加到消息序列中。Agent 带着新的消息序列再次调用模型让模型基于工具结果生成后续内容。这个流程里最容易出问题的就是第三步“类型映射”。我遇到过最典型的一个坑工具定义参数是 Integer 类型模型在生成参数时给了 temperature : 20带引号的字符串框架的 JSON 反序列化默认抛异常。解决思路一是把参数描述写清楚二是给工具方法增加容错入参比如用 String 接收再进行内部转换或者自定义反序列化器。后面“常见问题”部分我会展开讲。顺带一提AgentScope Java 的工具调用是同步的。也就是说Agent 循环中每发起一次工具调用都要等结果返回后才进入下一轮推理。对于单机 demo 这没问题但如果你要接入外部 API 且接口响应很慢比如超过 30 秒整个 Agent 的响应时间会很难看。我现在的做法是把耗时的工具方法放到独立线程池里异步执行通过 CompletableFuture 返回结果这样工具“执行中”的等待不会阻塞框架主线程。不过要注意AgentScope Java 官方对异步工具调用是否完全兼容取决于版本需要你自己在目标版本里实测。2.3 多工具管理与选择策略单个工具好说当你有十几个、几十个工具时怎么让模型在适当的时候选对工具就成了核心问题。这个问题的本质还是在描述层面做文章。我在项目里给 Agent 挂了十几个工具后发现了两个现象现象一工具越多模型越容易“挑花眼”。有一次我同时注册了 get_weather、search_hotel、book_room 三个工具用户问“北京今天冷吗”模型居然同时调用了 get_weather 和 search_hotel。原因是 search_hotel 的描述里写了“包含地理位置和天气信息”触发条件写得过于宽泛模型被误导了。现象二工具名或描述相似度高模型容易选错。比如 get_room_price 和 gen_room_price_quote 这两个工具模型经常混淆。解决思路有两个方向。一个是调整描述粒度把每个工具的触发场景写细工具之间的边界写清楚。另一个是分组/命名空间。AgentScope Java 在较新版本里支持工具分组Tool Group可以把一组相关工具作为一个整体注册给 Agent比如“酒店服务工具组”、“天气工具组”模型先决定调哪组再在组内选具体工具。这相当于多了一层路由能显著降低误调用率。还有一个工程小技巧给工具调用记录加一层日志。排查时最关键的线索就是“模型当时为什么选择了这个工具”。我在项目里会专门打印一轮完整的消息序列包括系统提示词截断版、用户 query、模型中间推理、工具调用指令、工具返回结果。这样能直观看到模型“看到的”是什么从而定位描述问题。后面排查部分会再展开。3. 知识层实现怎么给 Agent 搭一个“书架”3.1 知识加载与切分从文档到向量知识层的目标不是把整本书塞给模型而是把书拆成“词条”模型需要什么就“翻到哪里”。这个过程分三步加载、切分、向量化。先说加载。AgentScope Java 支持从本地文件、URL、数据库等来源加载知识文档。文件格式常见的有 txt、pdf、markdown。pdf 是个大坑因为格式五花八门有的文字能被提取出来有的是扫描图片需要 OCR。我的经验是尽量让客户提供 markdown 或 txt 格式的源文件实在只有 pdf 就先用第三方工具转一遍文本再交给知识层。否则你的知识层处理时间会被 PDF 解析拖垮。再说切分。文档切分的粒度直接决定了检索效果。切太大了一个片段里塞的内容太多向量化的语义会“糊掉”检索时召回一堆不相关的片段切太小了上下文片段碎片化模型拼不回完整的逻辑链。我常用的切分配置是按段落先粗切再按固定窗口微调比如 min_chunk_size 200 字符max_chunk_size 800 字符重叠区 overlap 50 字符。重叠区是为了保证跨段落的语义在检索时不丢失——如果一句话被拦腰斩断切分衔接处就会丢失核心信息。最后是向量化。AgentScope Java 本身不内置 embedding 模型它通过接入外部嵌入模型服务来生成向量。业界常做的方案是调用 OpenAI 的 text-embedding-3-small如果你接受数据出网或者本地跑一个 BGE 系列模型通过 ONNX 或者 FastAPI 包装。国内团队用的多的是部署本地开源 embedding 模型因为私有化部署场景里数据不出域是硬性要求。关于向量的存储和检索AgentScope Java 提供了一套统一的检索接口底层可以用向量数据库实现常用的有 Chroma、Milvus、FAISS。本地开发我用 FAISS 偏多因为它轻量、无服务端依赖。生产环境则建议用 Milvus 或云上的向量库支持水平扩展和持久化。3.2 检索召回TopK 怎么选才能既准又不“撑爆”上下文知识检索的经典流程是把用户问题向量化然后在向量库里做近邻检索返回最相似的 K 个片段。这里有几个关键词值得讨论相似度阈值、TopK 大小、重排Rerank。相似度阈值决定了“宁缺毋滥”。如果用户问的内容和知识库里的文档完全不搭检索出来一堆低相似度的片段拼进上下文只会干扰模型判断。我实际用的阈值是 cosine 相似度 0.7具体还要看你用的 embedding 模型的相似度分布。低于这个阈值的片段一律过滤掉。注意这个阈值不是拍脑袋拍的要根据你的知识库在真实 query 下的召回分布来调。方法很简单准备 50 条真实用户问题跑一遍检索把召回的相似度打印出来找到明显分层的那个阈值点。TopK 大小要考虑模型的上下文窗口。假设模型上下文是 8K token系统提示词 历史对话已经占了一半那知识片段最多只能放 2K~3K token。按平均每个片段 150~250 个 token中文大概是 200~300 字具体取决于分词器TopK 设在 5~8 比较稳妥。K 太大会挤占对话空间K 太小又可能漏掉关键信息。一个工程建议不要让知识片段“裸奔”每个片段前面加一个元数据头比如来源文档名、章节号、日期模型看到这些能更好地判断片段的可信度和时效性。**重排Rerank**是目前业界事实上的标配。向量检索是第一道粗筛重排模型再对召回的片段和用户问题做精细语义相关性打分把最相关的 few 个片段挪到最前面。原因是向量检索的语义匹配能力有限有时候召回的前几名并不一定是最相关的。我在实测中加了一个轻量 Rerank 模型比如 BGE-reranker之后回答准确率从 60% 左右提升到了 75% 以上。AgentScope Java 的相关设计里有没有内置 Rerank 我不确定取决于你用的版本和扩展包但即使没有你也可以在检索后处理环节自己加一个 Rerank 服务接口原理上完全可行。// 知识检索的伪代码示意 KnowledgeQuery query KnowledgeQuery.builder() .queryText(userQuestion) .topK(8) .similarityThreshold(0.7) .build(); ListKnowledgeFragment fragments knowledgeStore.search(query); // 可选在 fragments 进入上下文前做后处理 ListKnowledgeFragment reranked rerankService.rerank(userQuestion, fragments);3.3 让 Agent 学会“查书架”知识引用与来源说明知识层的另一个重要设计是“引用溯源”。Agent 基于知识片段回答问题时应该告诉用户“这是基于哪份文档说的”。这不仅是用户体验问题还是工程调试的依据——当回答出错时你能快速定位是检索出了问题、知识片段本身有问题还是模型理解有偏差。我的做法是在每个知识片段上捆绑一个 source 字段。比如public class KnowledgeFragment { private String content; // 片段正文 private String source; // 来源如doc://hr-policy/第三章/第2节 private double score; // 相似度得分 }在拼装系统提示词时我要求模型在引用知识库内容时附加 source格式如“根据《员工手册》第三章第 2 节”。为了强制模型遵守这个约定我会在系统提示词里明确写一条规则“当回答基于知识库内容时必须在句末附带来源标识。若信息不在知识库中必须明确回答‘知识库中未找到相关信息’不得猜测。”实测下来这种显式约束比放任模型自由发挥有效得多。另外说一句知识检索和工具调用不是割裂的。在很多实际场景里它们是协作的。最常见的模式是工具负责拿到“活数据”比如实时库存、账户余额知识库负责提供“静态规则”比如库存流转制度、审批流程说明模型综合两者给出回答。比如用户问“我能不能申请设备采购预付款”知识库提供《财务报销制度》条款工具查询用户的采购单状态Agent 把两者结合回答“根据制度第 X 条你符合条件但当前采购单状态为待审批”。在 AgentScope Java 里这种协作天然支持因为工具结果和知识片段都会作为消息序列的一部分被模型同时看到。4. 实操过程在 AgentScope Java 里把工具和知识接起来4.1 工程配置与依赖我假设你已经有一个能跑通前面两篇基础对话的 AgentScope Java 工程。如果没有赶紧回头把基础链路通一遍不然后面每一步都会卡壳。接下来你需要添加的知识与工具层相关依赖核心是 agent-tool 和 knowledge 相关的模块。不同版本包名会变建议以你项目中实际引入的 SDK 版本号为基准别直接照抄网上的旧代码。一个常见的初始化片段是这样// 初始化工具注册中心 ToolRegistry toolRegistry new ToolRegistry(); toolRegistry.register(new WeatherTool()); toolRegistry.register(new OrderQueryTool()); // 初始化知识库 KnowledgeStore knowledgeStore new KnowledgeStore(vectorStore); knowledgeStore.load(hr-policy.md); // 创建 Agent 并挂载两层能力 Agent agent Agent.builder() .model(modelConfig) .tools(toolRegistry) .knowledge(knowledgeStore) .reActLoop(true) .build(); // 发起对话 AgentResponse response agent.chat(北京明天是晴天吗);这段代码看着简单但配置上有几个“隐形开关”直接影响能否跑通开关一reActLoop或等价命名如 enable_tool_call_loop。默认情况下 Agent 可能只做单轮模型调用不自动执行工具结果回填。如果你发现调用了工具但模型拿不到结果、或者模型压根不发起工具调用先检查这个开关有没有打开。这是工具层失效的第一大原因。开关二system prompt 模板。AgentScope Java 里工具有效工作的前提是系统提示词里包含工具使用规则。有的版本会自动拼接有的版本需要你在系统提示词模板里加占位符。你需要检查生成的系统提示词里是否能看到工具名和 JSON Schema。看不到就是注册没成功或者提示词模板没配置。开关三模型的能力开关。不是所有模型都支持 function calling。有些模型尤其是本地部署的某些开源模型能力较弱需要额外在提示词里用 ReAct 文本格式引导而不是用原生的 function calling 协议。AgentScope Java 是否能做降级处理取决于版本。如果模型不支持 function call 格式你会看到模型始终不输出工具调用指令或者直接答非所问。4.2 系统提示词的组装策略工具和知识层能不能生效一半靠代码一半靠提示词。AgentScope Java 会把工具 JSON Schema 自动拼进系统提示词但你最好在系统提示词里再加上一层“使用策略”让模型知道在什么情况下优先用什么、以及各种边界规则。我习惯在系统提示词里固定加这么几段内容工具使用规则 1. 当问题涉及实时数据、用户私有数据、需要执行操作的场景时必须先调用对应工具不得凭已有知识臆测。 2. 工具调用失败时如实告知用户调用失败的原因不要伪装成功。 3. 多个工具可从不同维度提供信息时可以连续调用多个工具后再统一回答。 知识库使用规则 1. 回答与公司制度、产品说明、政策流程相关的问题时必须优先引用知识库片段。 2. 引用时标注来源编号格式 [来源xxx] 3. 知识库片段无法覆盖用户问题时明确说“知识库中未找到相关信息”禁止编造。你可能会问工具 JSON Schema 里不已经写了描述吗为什么还要在系统提示词里重复规则实测下来的原因是JSON Schema 里的描述通常比较简洁模型对“何时该用”的判断容易摇摆而系统提示词里的规则部分用自然语言写得更详细能显著提高模型遵守工具的稳定性。这两者是互相补充的关系不是冗余关系。4.3 从单工具到双能力一个完整的端到端例子为了让你更直观地看到全链路我给一个完整的例子用户问“小明上周提交的采购申请批了吗”这个场景需要同时用到工具查审批状态和知识查审批制度里“审批时限”条款。第一步工具注册两个方法public class ApprovalTool { AgentTool( name query_approval_status, description 根据申请人姓名或申请单号查询审批状态。当用户询问审批进度、审批结果时必须调用。, parameters { ToolParam(name applicant, type String.class, description 申请人姓名, required true) } ) public String queryApprovalStatus(String applicant) { // 模拟查询数据库 return 申请单号 AP20240115状态审批中当前节点财务复核提交时间2024-01-15; } }第二步知识库加载审批制度文档检索“审批时限”相关片段。第三步Agent 的 ReAct 循环会这样走用户: 小明上周提交的采购申请批了吗 模型: 我需要先查一下审批状态。调用工具 query_approval_status(applicant小明)。 Agent执行工具返回: 申请单号 AP20240115状态审批中当前节点财务复核。 模型再次推理: 审批还在进行中。我需要补充知识库中关于审批时限的信息判断这个进度是否正常。 Agent检索知识库返回: 《采购审批制度》第5条一般采购审批时限为7个工作日复杂采购审批时限为15个工作日。 模型生成最终回答: 小明的采购申请AP20240115还在审批中当前在财务复核节点。根据《采购审批制度》第5条一般采购审批时限为7个工作日目前还在正常时限内建议继续等待。这个过程看起来顺理成章但请注意模型做“先查工具、再查知识库”的决策不是天然就会的。在第一次运行时你极可能遇到模型只调工具、不查知识库或者干脆跳过工具凭印象直接回答。这时候你就要对系统提示词下功夫明确引导“涉及进度查询先调工具涉及制度规定再查知识库”。这属于 Agent 工程里最常见的“模型行为调教”环节。4.4 检索质量与回答质量的验证方法工具和知识层接上后最大的问题就是怎么验证效果。聊得热闹不如可量化。我给自己定的一套验证 checklist 是这样的召回验证用 20~30 条真实问题做测试集逐条跑知识检索人工判断召回的前 5 个片段里有没有正确答案。如果召回率低于 70%说明切分粒度、embedding 模型或向量库索引需要调整。工具调用准确率测试模型发起工具调用的时机和参数是否正确。统计“应该调用时没调用”和“不该调用时乱调用”两类错误分析错误原因是描述不清晰还是规则缺失。端到端回答质量把问答对交给业务方打分重点看事实准确性、来源标注合规性、表述是否自然。这一步往往能发现知识库里真正缺了哪块内容。我特别建议记录失败案例而不是只统计准确率。每一条“模型没调用工具”“检索回了错误片段”“回答与知识库不符”的案例都是调整提示词、切分参数、阈值的直接依据。做过几轮迭代后你会发现准确率的提升瓶颈往往不在模型而在知识库质量和工具描述质量。这个判断和很多人的直觉相反但确实是工程现实。5. 常见问题与排查技巧实录5.1 错误排查的“总思路”先看消息序列再谈代码Agent 出问题时我最反感的是直接去改代码。Agent 的行为是由上下文的“输入”决定的代码只负责把上下文组织好。所以排查的第一步永远是打印完整的消息序列看模型在这一轮看到了哪些消息然后推测问题的根源在哪个环节。我在项目里加的调试日志模板如下[MESSAGE EXCHANGE LOG] System Prompt (前1000字符): ... User Query: ... Assistant Reasoning: 我需要查询该用户的订单状态 Tool Call Request: query_order(applicant张三) Tool Response: {orderId: 123, status: 已发货} Final Answer: 您的订单已发货拿到这个日志后问题定位基本可以按下面的顺序问下去模型有没有发起工具调用没有 → 检查工具是否注册成功 / 系统提示词里是否有工具描述 / 模型是否支持 function calling。工具调用参数对不对不对 → 检查参数描述清晰度 / 类型映射配置。工具执行有没有报错有 → 看堆栈重点检查反射调用和类型转换。工具结果有没有正确回填没有 → 检查 reActLoop 开关 / 消息 ID 关联逻辑。最终回答有没有用到工具结果没用 → 提示词里缺少“必须基于工具结果回答”的规则。这套排查顺序能覆盖 90% 的工具层问题。知识层的问题排查类似用户反馈回答不对 → 看检索召回的是什么片段 → 检查切分和向量化质量 → 检查 TopK 和阈值 → 检查提示词是否要求引用知识库。5.2 工具层高频问题速查表我整理了一张表都是我在实际项目里真实遇到过的坑每条后面都跟了解决思路。问题现象根因分析解决方案模型完全不调用工具把工具名当普通文本回复1. 模型不支持 function calling 协议 2. 工具描述在提示词里不可见1. 换支持 function calling 的模型 2. 检查提示词拼接确认 JSON Schema 已注入工具被调用但参数是乱码字符编码不一致中文参数在 JSON 转换中被破坏统一配置 UTF-8 编码检查框架默认 charset 设置工具调用报类型转换异常Schema 中参数类型与实际入参类型不匹配参数描述里写明格式样例或改用 String 接收 内部解析工具返回值太长模型上下文被撑爆工具返回了大段明细数据工具层做摘要后返回只回传必要字段工具调用成功但模型不用结果系统提示词未强制要求基于工具结果回答提示词中显式声明回答必须基于最近一次工具返回的数据多个相似工具模型频繁选错工具描述边界模糊给每个工具补全差异化触发场景描述必要时用工具分组工具方法里有状态改变如写库模型重复调用模型在推理中重复生成同一工具调用工具层增加幂等性设计调用前检查是否已执行过同一请求这里面的“模型重复调用“是特别隐蔽的一个问题。有一次我们给 Agent 挂了“发送短信”工具结果模型在输出最终回答之前连续生成了两次调用指令导致用户收到两条短信。排查后发现是模型对工具结果的处理策略不明确——它不确定工具调用已经完成于是又试了一次。解决办法是在工具返回消息里增加一个状态字段明确标记“短信已发送成功无需重复调用”并在系统提示词里写“工具调用成功后不要再次调用相同工具”。5.3 知识层高频问题速查表知识检索是“看起来简单、调起来磨人”的模块。我把常见问题也整理成表问题现象根因分析解决方案检索结果和问题完全无关1. 切分粒度太粗或太细 2. embedding 模型与语料领域不匹配调整切分参数换用领域相关的 embedding 模型或用真实问题验证召回召回片段正确但模型没用知识片段被拼接在上下文末尾模型没读到调整知识片段在提示词中的位置或减短历史对话长度相似度高但答案错误知识片段本身不完整或者多片段拼接造成歧义给知识片段增加上下文补充窗口前后扩展一段让模型读到完整语义中文问答效果差部分 embedding 模型对中文支持弱换用中文优化过的模型如 BGE 系或者微调切分策略适配中文分词文档更新后检索结果仍是旧内容向量缓存未失效知识库更新时同步删除旧 chunk 的向量重建索引多个相似文档片段互相矛盾知识库中存在冲突内容模型难以取舍在元数据里增加版本号/发布日期提示词中要求优先选择“最新版本”5.4 关于系统提示词的两点独家心得最后补两个我踩过几轮才悟出来的技巧它们不属于 AgentScope Java 的 API 范畴但对工具层和知识层能否正常工作影响巨大。技巧一给模型一个“别乱动”的兜底选项。在系统提示词里加上“如果工具结果和知识库内容与问题无关或冲突直接说明无法回答不要强行调用工具”。这条规则能让模型的调用行为更克制减少误调用和幻觉。我把它称为“刹车规则”。没有这条规则时模型会倾向于“尽量调点什么”反而把简单问题搞复杂。技巧二用“链式思考示例”在前面加一个 few-shot 样例。单纯写规则模型可能还是不知道具体怎么把工具和知识串起来。我在系统提示词里加了一个简短的 few-shot 示例模拟用户问一句、模型内部推理、调用工具、查知识库、最终回答的完整过程。模型看到这种示例后复现的稳定性会明显提升。这是低成本但高回报的调教手段。Agent 开发有个特点你写下的每一行代码都是在为模型的决策做“场景铺垫”。工具和知识层不是简单的接口封装它们定义了 Agent 能力的边界。手上有工具书架上有知识Agent 就不再是只会复述训练数据的聊天机器人而是一个能查数据、能执行操作、能依据内部文档做判断的“数字员工”。如果你照着前面的步骤把工具和知识层接上了我建议你做的第一件事不是继续加功能而是拿一套真实业务问题去跑一遍回归测试把每一轮的回答和消息日志存下来。这些数据会告诉你你的 Agent 离“可信可用”还差多少调整。下一轮迭代你会感谢今天埋下的这个测试基础。
返回列表