LangChain4j Agent:多步推理自主调用,放手让“实习生”自己安排工作

发布时间:2026/10/12 10:40:58
LangChain4j Agent:多步推理自主调用,放手让“实习生”自己安排工作
LangChain4j Agent多步推理自主调用放手让实习生自己安排工作作者鱼宵 LangChain4j实战精通营 · 第 9 篇上一课你问大模型订单 1001 和 1002 一共多少钱它大概率会张口心算199 加 299.5等于……498.5 吧。听着挺顺可你敢把钱交给它算吗大模型心算大数字本来就不靠谱万一哪天它把 199.5 记成 199、加出 498 你都不知道错在哪。这就是今天要解决的**别让模型心算也别你写死流程而是放手让它自己安排工作——该查谁、该用哪个工具算它自己看着办但每一步都走真实代码。**这就是 Agent。你只丢一句两个订单总金额多少它自己先查 1001、再查 1002、再调加法工具然后报出 498.5。代码全在仓库lesson-09/clone 下来跑一遍控制台那三步调用链就是最好的面试现场。一、核心原理从你指挥一步到它自己排步骤一句话Agent 大模型 一组工具 一个观察→思考→行动的循环。你只给目标模型自己规划下一步直到任务完成。1. 和上一课的工具调用差在哪第 6 课我们见过 Function Calling你说查一下订单 1001模型调一次工具就交差——步骤是你定的。Agent 是升级版你说算一下 1001 和 1002 一共多少模型自己想得先查 1001再查 1002然后才能加——步骤是它自己排的。维度单轮工具调用L6Agent本课谁定步骤你的代码写死模型看中间结果动态决定调用轮数一轮调一次就答多轮查 N 次算 M 次状态无带状态上一步结果是下一步输入风险低高可能多调、漏调、瞎调2. 多步推理链长什么样拿本课任务订单 1001 和 1002 的总金额是多少走一遍用户两个订单总金额多少 ↓ 模型想需要两个金额先查 1001 [调工具] getOrderAmount(1001) → [返回] 199.0 ↓ 模型想再查 1002 [调工具] getOrderAmount(1002) → [返回] 299.5 ↓ 模型想两个数齐了按规矩用加法工具 [调工具] calcTotal(199.0, 299.5) → [返回] 498.5 ↓ 模型想数据齐了总结 最终回答1001199 元和 1002299.5 元总金额 498.5 元。这条链你的代码里一行都没写——是模型看着每一步的返回自己决定下一步干什么。3. 为什么专门给它一个加法工具你可能会问不就是 199299.5 吗模型自己加一下不行不行。大模型数字运算是已知短板钱的计算必须走确定性代码。所以我们故意做了个calcTotal工具并在规则里写死涉及求和必须调它不许心算——既观察到完整三步链又把心算这个幻觉路口堵死。这背后是个分工原则LLM 负责决策先查谁代码负责计算加多少。4. 护栏放手不等于放任Agent 会犯三类错瞎调工具该查文档却查订单、编造数据不问工具直接编个金额、死循环反复调同一个工具。本课的护栏写在SystemMessage里温度降到 0.2、哪类问题用哪个工具写死、“求和必须调 calcTotal”。生产再加工具调用次数上限、敏感操作人工确认、每次调用落审计日志。二、动手编译 跑 fat jar环境Windows JDK 17 DEEPSEEK_API_KEY。控制台课跑完自动退出。java-version[bool][Environment]::GetEnvironmentVariable(DEEPSEEK_API_KEY)cd langchain4j-journey\lesson-09$env:JAVA_HOMEC:\Program Files\Java\jdk-17mvn clean install-DskipTests java-Dfile.encodingUTF-8-jar target\lesson-09-1.0.0.jar中文输出怕乱码就重定向落盘cmd/cjava -Dfile.encodingUTF-8 -jar target\lesson-09-1.0.0.jar run.log 21Get-Contentrun.log-Encoding UTF8重点看控制台里[工具调用]和[工具返回]交替出现的那几行——那就是 Agent 自主编排的现场。三、关键代码三个工具 一个大脑接口工程给模型配了三个工具查订单、查制度文档、算总价。先看两个核心工具类。工具一查订单方法里那行打印就是监控摄像头packagecom.langchain4j.lesson09.tools;importdev.langchain4j.agent.tool.P;importdev.langchain4j.agent.tool.Tool;importorg.springframework.stereotype.Component;importjava.util.Map;/** 查订单工具模拟订单库生产换成查 MySQL。 */ComponentpublicclassOrderTools{/** 模拟订单库订单号 → 金额元 */privatestaticfinalMapString,DoubleORDER_DBMap.of(1001,199.0,1002,299.5,1003,599.0);// Tool 说明会原样发给模型——写清楚是它选对工具的前提Tool(根据订单号查询订单金额单位元。参数 orderId 是字符串形式的订单号如 \1001\)publicdoublegetOrderAmount(P(订单号如 1001)StringorderId){System.out.printf([工具调用] OrderTools.getOrderAmount(orderId\%s\)%n,orderId);DoubleamountORDER_DB.get(orderId);if(amountnull){// 查不到如实返回让模型自己处理订单不存在别抛异常糊弄System.out.printf([工具返回] 订单 %s 不存在%n,orderId);return-1;}System.out.printf([工具返回] 订单 %s 金额 %.1f 元%n,orderId,amount);returnamount;}}工具三算总价存在的意义就是堵死心算packagecom.langchain4j.lesson09.tools;importdev.langchain4j.agent.tool.P;importdev.langchain4j.agent.tool.Tool;importorg.springframework.stereotype.Component;/** 算总价工具钱的加法必须走确定性代码不许模型心算。 */ComponentpublicclassCalcTools{Tool(计算两个金额的总和返回相加结果。涉及钱的加法请一律用本工具计算不要心算)publicdoublecalcTotal(P(第一个金额元)doubleamountA,P(第二个金额元)doubleamountB){System.out.printf([工具调用] CalcTools.calcTotal(a%.1f, b%.1f)%n,amountA,amountB);doubletotalamountAamountB;System.out.printf([工具返回] 合计 %.1f 元%n,total);returntotal;}}还有个DocTools查公司制度结构和 OrderTools 一样就是 Map 里存考勤/年假两条仓库里有完整版。主类装配大脑接口护栏写在 SystemMessage 里packagecom.langchain4j.lesson09;importcom.langchain4j.lesson09.tools.CalcTools;importcom.langchain4j.lesson09.tools.DocTools;importcom.langchain4j.lesson09.tools.OrderTools;importdev.langchain4j.model.chat.ChatModel;importdev.langchain4j.service.AiServices;importdev.langchain4j.service.SystemMessage;importorg.springframework.boot.CommandLineRunner;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;/** * 第 9 课启动类Agent 多步推理。跑完自动退出。 * 运行java -Dfile.encodingUTF-8 -jar target\lesson-09-1.0.0.jar */SpringBootApplicationpublicclassAgentDemoApplicationimplementsCommandLineRunner{privatefinalChatModelchatModel;privatefinalOrderToolsorderTools;privatefinalDocToolsdocTools;privatefinalCalcToolscalcTools;publicAgentDemoApplication(ChatModelchatModel,OrderToolsorderTools,DocToolsdocTools,CalcToolscalcTools){this.chatModelchatModel;this.orderToolsorderTools;this.docToolsdocTools;this.calcToolscalcTools;}publicstaticvoidmain(String[]args){SpringApplication.run(AgentDemoApplication.class,args);}/** * Agent 的大脑接口AiServices 动态生成实现。 * SystemMessage 就是护栏——什么任务调哪个工具、钱必须用工具算。 */interfaceOrderAssistant{SystemMessage(你是星辰科技的订单助手。规则\n1. 要知道某个订单金额时调用 OrderTools.getOrderAmount\n2. 涉及金额求和时必须调用 CalcTools.calcTotal 计算绝对不要自己心算\n3. 被问公司制度时调用 DocTools.searchCompanyDoc\n4. 全部步骤完成后用一句简洁的中文总结最终答案。)Stringchat(StringuserMessage);}Overridepublicvoidrun(String...args){System.out.println( LangChain4j 第 9 课Agent 多步推理演示 );// 三个工具一起交给模型它自己看着说明书决定用谁OrderAssistantassistantAiServices.builder(OrderAssistant.class).chatModel(chatModel).tools(orderTools,docTools,calcTools).build();// 任务得选单步完不成的才看得到多步编排Stringtask订单 1001 和 1002 的总金额是多少;System.out.println(【用户任务】task);System.out.println(----- 下面是 Agent 自主执行的过程 -----);StringfinalAnswerassistant.chat(task);// 一行背后可能查两次、算一次System.out.println(----- Agent 最终回答 -----);System.out.println(finalAnswer);System.out.println( 演示结束 );}}盯一句.tools(orderTools, docTools, calcTools)三个工具一起交出去模型在对话里看见它们的说明书自己挑着用。assistant.chat(task)这一行背后就是那串查→回填→再查→再回填→算→总结的循环。四、实测输出498.5 三步链心算被规则挡住以下是 2026-10-05 本机真实运行DeepSeek温度 0.2已省略 banner LangChain4j 第 9 课Agent 多步推理演示 【用户任务】订单 1001 和 1002 的总金额是多少 ----- 下面是 Agent 自主执行的过程每步工具调用都会打印 ----- [工具调用] OrderTools.getOrderAmount(orderId1001) [工具返回] 订单 1001 金额 199.0 元 [工具调用] OrderTools.getOrderAmount(orderId1002) [工具返回] 订单 1002 金额 299.5 元 [工具调用] CalcTools.calcTotal(a199.0, b299.5) [工具返回] 合计 498.5 元 ----- Agent 最终回答 ----- 订单 1001199 元和 1002299.5 元的总金额为 498.5 元。 演示结束进程自然退出 逐行读证据三步链全对——先查 1001199.0再查 1002299.5然后调calcTotal求和498.5。顺序你的代码里没写、任务里也没说是它看着需要两个金额自己排的。最值得停下来看的是第三步199299.5 它没有自己张嘴算而是真的调了加法工具——这就是SystemMessage里必须调用 calcTotal不要心算被执行的铁证。看出护栏的作用了吗把它从规则里删掉下一节挑战题就让你看模型怎么开始心算。排查模型直接编数字没调工具多半是温度太高或规则不够硬只查一个订单就回答可能是 maxTokens 太小中途截断本课给了 500401 是 Key 没生效。五、挑战题改一改看看会怎样⭐换成单步任务把 task 改成订单 1003 的金额是多少重跑看是不是只调一次工具就答了。对比体会单步 vs 多步——考试题必须选一步完不成的才看得到编排。⭐⭐删掉心算护栏把SystemMessage里必须调用 CalcTools.calcTotal……绝对不要自己心算那行删掉重跑看模型是不是开始自己加可能对也可能错。跑出来你就懂那行规则多值钱。⭐⭐⭐逼它换工具把任务改成公司考勤时间是几点顺便查下 1001 多少钱观察它这次是不是改调了DocTools又混着调OrderTools——多工具混用才是 Agent 的日常。六、生产环境进阶三个加分项1. 加工具调用次数上限防死循环。Agent 可能反复调同一个工具停不下来。生产要配最大工具调用轮数或在工具类里加计数器超了就强制收尾——别让它把你的 token 烧穿。2. 敏感操作要人工确认。Agent 一旦有退款“下单”删数据这类写操作权限不能让它一把梭。关键动作加一道人工审核模型只决策、不直接落库。3. 每步调用落审计日志。谁、什么时候、调了哪个工具、传了什么参、返回了啥——全记下来。出了问题能回溯也能反过来调优工具说明和护栏。七、面试回答模板面试官Agent 和单轮 Function Calling 到底差在哪一句话FC 是单轮、代码定流程Agent 是多轮、模型定顺序、带中间状态。展开FC 你说查订单 1001模型调一次就答Agent 你只给目标两个订单总金额多少模型自己规划先查 1001、再查 1002、然后算每一步的返回是下一步的输入。本课实测它自主跑完三步链报出 498.5顺序不是代码写死的。指向本课第一节 lesson-09 实测输出追问为什么不让模型自己心算非要给它一个加法工具大模型数字运算是已知短板钱的计算必须走确定性代码工具。我们在 SystemMessage 里写死求和必须调 calcTotal不许心算实测它真的调了工具而不是自己加。背后分工原则LLM 负责决策先查谁代码负责计算加多少。指向本课第三节CalcTools 第四节追问Agent 会乱调工具护栏该加在哪三道低温 0.2 稳住推理、SystemMessage 写死哪类问题用哪个工具、钱必须走工具、工具方法查不到就如实返回别抛技术异常。生产再加调用次数上限防死循环、敏感操作人工确认、每步落审计日志。指向本课第四节踩坑 第六节八、总结表坑现象解法模型不调工具直接编张口报个金额温度降到 0.2SystemMessage 把必须用工具写死只查一个订单就答多步链断了maxTokens 给够本课 500强调查完再总结任务选成单步看不到编排考试题必须一步完不成如两订单求和Agent 多轮烧 token中途截断每轮都计输出 tokenmaxTokens 放宽Tool 说明太简略模型按错工具说明写清干什么参数长啥样带示例ToolErrorHandlingNotice WARN启动一堆警告demo 忽略生产配 toolExecutionErrorHandler九、关于这个系列本文是「Java 后端实战精通营」系列第 9 篇原则实战驱动、由浅到深、面试向每篇文章的结论都可以亲手验证。LangChain4j 实战精通营10 课https://gitee.com/j67mk2/langchain4j-journey本文对应源码位置lesson-09/控制台工程内含三个工具类OrderTools/DocTools/CalcToolsAgentDemoApplication大脑接口装配系列文章一览按发布顺序篇主题1LangChain4j 第一个对话程序手写 LLM 调用链路看清模型怎么开口2LangChain4j 提示词工程模板 few-shot 温度提示词从写死到复用3LangChain4j 结构化输出让模型吐出 Java 对象JSON 不再手写解析4LangChain4j 对话记忆让模型记住聊过什么三种方式实测对比5LangChain4j 流式输出打字机效果 SSE回答不再干等三秒6LangChain4j 工具调用Function Calling 让模型动手查数据多工具连调实测7LangChain4j 向量检索文本怎么变成可搜索的坐标8LangChain4j RAG 流水线手写问答全流程给 AI 开卷考试9LangChain4j Agent多步推理自主调用放手让实习生自己安排工作10LangChain4j 企业智能客服RAG 工具 记忆 流式 兜底验收 5 项全过下一篇预告《LangChain4j 企业智能客服RAG 工具 记忆 流式 兜底验收 5 项全过》——今天是单测 Agent下一课把整个课程串成一个完整项目对话 工具调用 RAG 知识问答 多轮记忆 流式输出组装成一个能上线的企业客服还附 5 项验收清单。跑完有任何报错把控制台输出发评论区一起排查。标签建议LangChain4j、Agent、FunctionCalling摘要建议≤256 字直接让大模型心算两个订单总金额听着顺但数字不可靠错了都不知道哪步错。本文用 AiServices Tool 组装 Agent给模型查订单、查文档、算总价三个工具只丢一句1001 和 1002 总金额多少它自己先查 199、再查 299.5、然后调加法工具报出 498.5——三步链全对心算被规则挡住。附删护栏、换单步任务等挑战题与面试模板源码在 gitee lesson-09 可 clone 直接跑。