LangChain4j 1.23.0(GitHub Release published_at 2026-10-28T16:54:13Z,Asia/Shanghai 2026-10-29 00:54)把 PR #6765 的 Confidence Cascade 打进正式包:子 Agent 按便宜到强能力排成档位,每档答完后用 DecisionModel 打 yes/no 概率,达到接受门槛就停,否则升档;最后一档按设计不打分。本机用 Spring Boot 3.5.6 + langchain4j-agentic-patterns 1.23.0-beta33,门槛固定 0.5:本地 DecisionModel 返回 0.90 时只跑 faq(faqCalls=1 expertCalls=0 gradeCalls=1);返回 0.20 时升到 expert,且 planner 日志写明末档不打分(faqCalls=1 expertCalls=1 gradeCalls=1)。
档位在演示里是带计数的普通 Java 方法(非真实大模型),DecisionModel 是固定概率并打印请求的本地实现,用来对照 planner 的升档与打分次数。官方 IT 用 TypeSafe + OpenAI chat model;生产应换成 TypeSafeDecisionModel、OpenAiDecisionModel 或同版本新增的 OllamaDecisionModel。API 标了 @Experimental,文档写明可能随 DecisionModel 变更。
发布里这一条在讲什么
1.23.0 发行说明 Notable Changes 首条之外,同列还有 Confidence Cascade(#6765)、Decision agents(#6820)、AiServiceInvocationSummaryEvent、以及 langchain4j-test 的 LLM judges。Cascade 文档在 tutorials agents.md 的 “Confidence cascade agentic pattern” 一节,实现类是 dev.langchain4j.agentic.patterns.cascade.ConfidenceCascadePlanner,坐标:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-agentic-patterns</artifactId>
<version>1.23.0-beta33</version>
</dependency>
稳定线 langchain4j / langchain4j-core 是 1.23.0;agentic 与 patterns 仍走 beta 号 1.23.0-beta33(BOM 1.23.0 会按模块对齐)。文档要求至少两个 subagent,cascade 本身必须是带参数的 typed agent 接口;参数名不能叫 candidateAnswer(打分输入里留给候选答案)。
按 planner 源码与文档,每档完成后会发一道固定文案的 YesNoQuestion:name=accepted,text=Does the answer fully and correctly address the request?;输入是 cascade 参数加上字段 candidateAnswer。可选的 acceptance criterion 会写进该题的 yesWhen。概率 ≥ 门槛则接受并返回;否则调下一档。没有后续仍处于 active 的档位时,当前答案直接返回且不再调用 DecisionModel。文档原话把 grade 定位为相关性与完整性信号,校验收束门槛时要按所用 DecisionModel 自己的标定重做。
官方组装方式
文档示例用 FAQ 小模型档 + Expert 大模型档,再挂 TypeSafe 决策模型(节选):
SupportCascade supportCascade = AgenticServices.plannerBuilder(SupportCascade.class)
.subAgents(faqAgent, expertAgent)
.outputKey("answer")
.planner(() -> new ConfidenceCascadePlanner(decisionModel, 0.5))
.build();
String answer = supportCascade.ask("How do I descale my Brewmaster 3000 coffee machine?");
带接受标准时第三个构造参数写入 yesWhen:
new ConfidenceCascadePlanner(decisionModel, 0.5,
"The answer gives concrete instructions that solve the user's problem, "
+ "instead of saying that it cannot help or redirecting the user elsewhere");
planner 实例保存单次调用状态,文档要求用 supplier 每次新建,例如 () -> new ConfidenceCascadePlanner(decisionModel, 0.5);DecisionModel 可以共享。
本机对照:门槛 0.5 下的四组场景
父工程 Spring Boot 3.5.6,JDK 21.0.12.1,Maven 3.9.9,编译开启 -parameters。Cascade 接口返回 ResultWithAgenticScope<String>,方便读各档 invocation。DecisionModel 的 doDecide 打印 question 与 input,再按场景返回固定 yes 概率。
SupportCascade cascade = AgenticServices.plannerBuilder(SupportCascade.class)
.subAgents(faq, expert)
.outputKey("answer")
.planner(() -> new ConfidenceCascadePlanner(model, 0.5))
.build();
ResultWithAgenticScope<String> result = cascade.ask("How do I descale my Brewmaster 3000?");
运行摘录如下(与本机 Spring Boot 3.5.6 日志一致)。
场景 A:grade=0.90,停在 faq。
=== scenario A: grade 0.90 >= threshold 0.5 → stop at faq ===
[tier] faq call#1 request=How do I descale my Brewmaster 3000?
[grade] name=accepted text=Does the answer fully and correctly address the request? yesWhen=null input=FieldsInput{names=[request, candidateAnswer]} -> yesProbability=0.9
Accepting the answer of the tier 'faq', graded 0.9
[result] answer=Use vinegar and water to descale the Brewmaster 3000.
[result] faqCalls=1 expertCalls=0 gradeCalls=1
[result] faqInvocations=1 expertInvocations=0
场景 B:grade=0.20,升档;末档 expert 不打分。
=== scenario B: grade 0.20 < threshold 0.5 → escalate; last tier not graded ===
[tier] faq call#1 request=How do I descale my Brewmaster 3000?
[grade] name=accepted text=Does the answer fully and correctly address the request? yesWhen=null input=FieldsInput{names=[request, candidateAnswer]} -> yesProbability=0.2
Rejecting the answer of the tier 'faq', graded 0.2, escalating to 'expert'
[tier] expert call#1 request=How do I descale my Brewmaster 3000?
Returning the answer of the tier 'expert' without grading it, since no later tier is active
[result] answer=For a dual-router home network, set one as gateway and the other as AP.
[result] faqCalls=1 expertCalls=1 gradeCalls=1
[result] faqInvocations=1 expertInvocations=1
升档路径上,每跨过一档付一次 Decision 调用;落到最后一档时省掉这次打分,与文档 “The last tier is never graded” 一致。场景 B 的 expert 答案是 stub 写死的网络说明,和 descale 问题无关,只用来证明末档输出会被原样返回。
场景 C:同样 grade=0.20,构造时传入 acceptance criterion,grade 日志里 yesWhen 变为该字符串,升档计数与 B 相同。
[grade] name=accepted text=Does the answer fully and correctly address the request? yesWhen=The answer gives concrete steps and does not say it cannot help input=FieldsInput{names=[request, candidateAnswer]} -> yesProbability=0.2
Rejecting the answer of the tier 'faq', graded 0.2, escalating to 'expert'
[result] faqCalls=1 expertCalls=1 gradeCalls=1
场景 D:三档 faq→expert→senior,连续两次 0.10,gradeCalls=2,senior 直接返回。
Rejecting the answer of the tier 'faq', graded 0.1, escalating to 'expert'
Rejecting the answer of the tier 'expert', graded 0.1, escalating to 'senior'
Returning the answer of the tier 'senior' without grading it, since no later tier is active
[result] answer=senior answer
[result] faqCalls=1 expertCalls=1 seniorCalls=1 gradeCalls=2
和 Decision Router、Decision Agent 的分工
同版文档写:Decision Router 在编排前按请求选子 Agent;Confidence Cascade 在看到答案后再决定是否继续升档;Decision Agent(#6820)把决策结果当成普通值交给后续代码或其他 Agent。需要“先看答案再花钱”时用 Cascade;能从请求本身判断难度时用 Router。同一发行里还有 Ollama 决策模型与图片输入等,本文只复现 Cascade 的档位与打分次数。
文档还提醒:请求与各档答案对 DecisionModel 都是不可信输入,Cascade 做的是成本与质量权衡,不是安全审核边界;必须强制落到更强档或人工时,要用 activation condition 等机制单独保证。执行状态在打分之后才落盘,打分过程中崩溃会重跑当前档。
资料来源
- LangChain4j 1.23.0 Release(published_at 2026-10-28T16:54:13Z)
- PR #6765 Introduce Confidence Cascade agentic pattern(merged 2026-10-21T15:19:12Z,Asia/Shanghai 2026-10-21 23:19)
- PR #6820 Introduce decision agents
- 源码标签
1.23.0:docs/docs/tutorials/agents.md(Confidence cascade 一节)、ConfidenceCascadePlanner.java - Maven:
dev.langchain4j:langchain4j-agentic-patterns:1.23.0-beta33、langchain4j-core:1.23.0;运行环境 Spring Boot 3.5.6、JDK 21.0.12.1、Maven 3.9.9
一起交流
分享你的思考,让讨论更进一步。