资讯详情

【Spring AI 实战 · 阶段二·篇1】Function Calling:给法律助手装上“计算器“

📅 2026/10/1 6:51:29 | 华诺云谱 👁 阅读
【Spring AI 实战 · 阶段二·篇1】Function Calling:给法律助手装上“计算器“
系列说明一个 Java 后端视角的 Spring AI 渐进式实战教程载体为开源项目「劳小司 · 智能法律助手」。序章技术栈全景与 AI 学习指南阶段一 · 流式对话内核篇1 SSE 流式·停止·思考可见化 / 篇2 会话记忆压缩与滚动体验阶段二 · 工具调用篇1 Function Calling 与法律计算器本文/ 篇2 联网搜索与工具预算阶段三 · RAG 知识库篇1 起步与底账化 / 篇2 Agentic RAG 与引用可信度 / 篇3 检索质量与体验阶段四 · 多模型路由篇1 五路级联路由阶段五 · 安全与质量门篇1 安全层与强制检索 / 篇2 质量门与评估门禁 / 篇3 指代消解与阻塞隔离阶段六 · 产品化与用户体系篇1 认证·配额·门禁 / 篇2 前端·移动端·身份 / 篇3 劳动法专精与多模态阶段七 · 存储演进与部署篇1 存储迁移 / 篇2 部署契约本篇涉及tool/CommonTools.java、tool/LaborTools.java、tool/GeneralLegalTools.java、service/CalculatorService.java。一、今天要做什么流式聊天做得再顺模型也只是在说。用户问我工作 3 年 4 个月、月薪 1.2 万被违法辞退能赔多少你希望它算出准确数字而不是凭语感给个大概。这就是 Function Calling工具调用的价值让模型自己去调你的 Java 方法。流程是你把方法连同它是干嘛的、要什么参数告诉模型 → 模型判断该不该调、生成参数 → 框架执行你的方法 → 把结果回灌给模型 → 模型组织成自然语言回答。二、Tool 新写法一个注解搞定Spring AI 1.x 的工具写法比早期简洁很多。对比一下旧写法Function Bean新写法Tool定义每个工具 Bean FunctionReq,StringDescription Request POJO一个Tool注解的普通方法参数手写 Request 类ToolParam直接标注在方法参数上Schema手工维护框架从方法签名自动生成 JSON Schema调用.toolNames(字符串)魔法值传对象引用编译期可查ComponentpublicclassCommonTools{Tool(description计算数学表达式的值支持加减乘除和括号如 12*58)publicStringcalculate(ToolParam(description数学表达式如 12*58)Stringexpression){returnString.valueOf(newExprParser(expression).parse());}}通用工具时间、计算在ModelRegistry构建每个客户端时通过ChatClient.builder(chatModel).defaultTools(commonTools)全局挂载之后所有对话自动携带。三、法律计算器复杂规则沉淀 ServiceLLM 只提参数劳动法工具组LaborTools有十几个经济补偿金N、违法解除赔偿金2N、代通知金1、加班费、未签合同二倍工资、试用期合法性、年休假、失业金、工伤补助金、社保/公积金补缴、仲裁时效……关键设计——单源架构这些计算的复杂规则三倍社平封顶、21.75 月计薪天数、分段累计全部沉淀在一份CalculatorService里Tool方法只负责接收 LLM 提取的参数并转调Tool(description计算劳动合同解除或终止时的经济补偿金N依据《劳动合同法》第47条不包含代通知金1与违法解除赔偿金2N)publicStringcalculateSeverance(ToolParam(description在本单位工作年限年可带小数如 3.5)doubleworkYears,ToolParam(description解除前 12 个月平均月工资元)doublemonthlySalary,ToolParam(description本地区上年度职工月平均工资元用于三倍封顶不传则不封顶,requiredfalse)DoublelocalAvgSalary,ToolContexttoolContext){ToolBasis.register(toolContext,《中华人民共和国劳动合同法》,第四十七条);returncalculatorService.severance(workYears,monthlySalary,localAvgSalary).text();}为什么这么分因为同一套计算逻辑前端工具箱ToolController和模型工具调用要复用同一份。如果规则散在 Prompt 里让模型心算或者前后端各写一份迟早漂移。把规则收敛到 Service 单点是法律这种算错就是事故领域的底线。四、参数自愈把格式错误回抛给模型日期类参数yyyy-MM-ddLLM 偶尔会填错格式。我们的做法不是抛 500而是把错误信息作为工具返回值回给模型让它自己修正重试try{returncalculatorService.limitation(eventDate).text();}catch(IllegalArgumentExceptione){returne.getMessage();// 日期格式应为 yyyy-MM-dd → 模型看到后重新提取参数}这是 Function Calling 的一个实用技巧工具返回值是给模型看的一句清晰的纠错提示能让模型自我修复比后端硬兜底更聪明。五、工具描述是门艺术别写必须调用Tool的description决定模型会不会用、用得对不对。本项目有条明确约定只澄清适用范围与参数口径不写必须调用/禁止心算这类硬约束。比如 2N 那条写的是与经济补偿金N互斥不并得——这是在帮模型区分场景而不是命令它。理由模型能力随版本升级今天需要禁止心算兜底明天模型自己就会了把选择权留给模型描述只负责消除歧义。工具一多描述质量直接决定调用准确率——描述写得含糊模型就乱调或干脆不调。六、ToolBasis计算型回答也要登记引用依据法律回答必须可溯源哪怕结论是算出来的。ToolBasis.register(toolContext, 法名, 条号)把每个计算器引用的法条登记进请求级的CitationRegistry这样质量门审校时计算型回答也能校验其法条依据阶段五·篇2 展开引用卡能展示这个补偿金额是依据第 47 条算的。向量检索对某法第 X 条原文这类精确引用天然偏弱所以另有getArticle工具按法名 条号确定性回表逐字返回原文 章属 版本加固引用链路。七、踩坑备忘① JDK 15 移除了 Nashorn别指望 ScriptEngine 算表达式。早期想用ScriptEngineManager().getEngineByName(js)求值12*58JDK 17 上直接 NPE引擎为 null。解决手写一个极简递归下降解析器ExprParser顺便复习编译原理文法→递归函数——expr term ((|-) term)*、term factor ((*|/) factor)*、factor ( expr ) | number三层方法调用天然保证先乘除后加减、括号最优先。② 工具越多越耗 token还越容易误导模型。所以工具按领域分组通用 / 劳动 / 通用法律并通过route-tools按路线差异化挂载——闲聊路线一个法律工具都不挂专业路线才全量挂载。这个成本控制在篇2 细讲。③ 参数类型要能被模型稳定产出。double比BigDecimal友好可选参数标requiredfalse并在描述里写清不传则如何否则模型可能反复追问或漏填。八、小结要点一句话Tool一个注解 ToolParam框架自动生成 Schema单源架构规则沉淀 CalculatorService前后端复用不漂移参数自愈错误回抛给模型让它自己修正重试描述艺术只消歧义不写硬约束选择权给模型ToolBasis计算结论也登记法条依据可溯源九、下篇预告工具会算了但模型的知识仍停在训练截止日——2026 年新出的政策它不知道。下一篇我们接上联网搜索并解决一个新麻烦工具一多怎么防止模型先查本地再联网双重烧钱工具预算登场。源码与体验Gitee国内快https://gitee.com/spaserby/laoxiaosi.git GitHub https://github.com/spaserby/laoxiaosi.git 在线演示https://laoxiaosi.noctisblue.com本系列全套代码皆开源觉得这篇有帮助欢迎顺手点颗 ⭐
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑