系列第八篇:国产大模型 Agent 实战与高级推理模式
前言
前七篇文章中,我们的示例代码都以 OpenAI GPT-4o 为底座模型。但在国内企业落地时,几乎所有团队都面临三个现实约束:
- 合规性:数据出境限制,敏感行业(能源、金融、政务)必须使用国产模型
- 成本:GPT-4o 的 Token 单价是国产模型的 3~5 倍
- 延迟:调用海外 API 的网络延迟不可忽视
好消息是,2025~2026 年国产大模型的能力已经大幅提升,Tool Calling、长上下文、Function Calling 等能力全面对齐国际水平。
本文将覆盖:四大国产模型的 Agent 适配实战 + 三种高级推理模式的原理与实现。
一、国产大模型 Agent 能力横评
1.1 选型维度
选择 Agent 底座模型,不能只看"跑分",更要看与 Agent 场景的适配度。核心维度:
| 维度 | 为什么重要 |
|---|---|
| Tool Calling 能力 | Agent 的核心就是工具调用,模型必须能稳定输出结构化的函数调用 |
| 指令遵循度 | Agent 的 System Prompt 通常很长很复杂,模型必须严格遵守每一条规则 |
| 上下文窗口 | 多轮对话 + 工具返回 + RAG 注入,上下文可能轻松超过 8K tokens |
| 推理速度 | Agent 场景一个请求可能触发 3~5 次 LLM 调用,延迟会叠加 |
| 价格 | 生产环境日均数千次调用,单价差 1 分钱,月成本差数千 |
1.2 四大主流国产模型对比(2026 Q3)
┌──────────────────────────────────────────────────────────────────────┐
│ 国产大模型 Agent 能力横评(2026 Q3) │
│ │
│ 维度 通义千问 智谱GLM DeepSeek 文心一言 │
│ Qwen2.5-72B GLM-4-Plus DeepSeek-V3 ERNIE-4.5 │
│ ───────────────────────────────────────────────────────────── │
│ Tool Calling ★★★★★ ★★★★☆ ★★★★★ ★★★★☆ │
│ 指令遵循 ★★★★☆ ★★★★☆ ★★★★★ ★★★★☆ │
│ 上下文窗口 128K 128K 128K 128K │
│ 推理速度 快 中 快 中 │
│ Input价格 ¥2/1M ¥5/1M ¥2/1M ¥30/1M │
│ Output价格 ¥6/1M ¥20/1M ¥8/1M ¥90/1M │
│ 私有化部署 ✅ 开源 ✅ 开源 ✅ 开源 ❌ 仅API │
│ 长文本理解 ★★★★★ ★★★★☆ ★★★★★ ★★★★☆ │
│ │
│ 综合评价: │
│ · 性价比之王: DeepSeek-V3(能力顶尖,价格最低) │
│ · 私有化首选: Qwen2.5-72B(开源 + 能力强 + 社区活跃) │
│ · 生态完善: 智谱GLM-4(SDK 完善,文档齐全) │
│ · 企业背书: 文心一言(百度生态,但价格最高) │
│ │
└──────────────────────────────────────────────────────────────────────┘
1.3 一个关键认知:API 兼容性
几乎所有国产大模型都兼容 OpenAI API 格式。这意味着:你为 GPT-4o 写的 Agent 代码,只需改三行配置就能切换到国产模型——不需要改业务代码。
// 之前的 OpenAI 配置
OpenAiChatModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.baseUrl("https://api.openai.com/v1")
.modelName("gpt-4o")
.build();
// 切换到国产模型:只改这三行
// ↓↓↓ ↓↓↓ ↓↓↓
这个特性极其重要——它意味着 模型可替换 是架构设计的第一原则。
二、四大国产模型接入实战
2.1 通义千问(Qwen)
接入方式一:通过阿里云百炼 API(推荐)
/**
* 通义千问 Agent 配置
*
* 阿里云百炼平台提供 OpenAI 兼容 API,
* 可以直接使用 LangChain4j 的 OpenAI 适配器。
*
* 优势:
* - 无需额外 SDK,复用 OpenAI 客户端
* - 支持 Tool Calling(function_call 参数)
* - 支持流式输出(SSE)
*
* 注意事项:
* - Qwen 的 Tool Calling 格式与 OpenAI 完全一致
* - 但 System Prompt 中建议用中文描述工具用途,效果更好
*/
@Bean
public ChatLanguageModel qwenModel() {
return OpenAiChatModel.builder()
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
.modelName("qwen-plus") // 或 qwen-max、qwen-turbo
.temperature(0.3)
.timeout(Duration.ofSeconds(60))
.maxRetries(3)
.build();
}
/**
* Qwen 模型选型指南:
*
* qwen-turbo → 速度最快,适合简单任务(意图分类、摘要)
* qwen-plus → 均衡之选,适合大多数 Agent 场景
* qwen-max → 能力最强,适合复杂推理(多步 Tool Calling)
*/
接入方式二:私有化部署(Ollama / vLLM)
对于数据敏感型企业,可以把 Qwen 模型部署在自己的服务器上:
/**
* 私有化部署的 Qwen 接入
*
* 部署方案选择:
* 1. Ollama: 最简单,一行命令启动,适合开发测试
* ollama run qwen2.5:72b
*
* 2. vLLM: 生产级方案,高吞吐、支持并发
* python -m vllm.entrypoints.openai.api_server \
* --model Qwen/Qwen2.5-72B-Instruct \
* --port 8000 \
* --max-model-len 32768 \
* --gpu-memory-utilization 0.9
*
* 3. TGI (Text Generation Inference): HuggingFace 官方方案
*
* 硬件要求(Qwen2.5-72B):
* - 最低:4 × A100 80GB(INT4 量化)
* - 推荐:8 × A100 80GB(FP16 无量化)
* - 如果资源有限:用 Qwen2.5-14B(1 × A100 即可)
*/
@Bean
public ChatLanguageModel privateQwenModel() {
return OpenAiChatModel.builder()
.apiKey("not-needed") // 私有部署不需要 API Key
.baseUrl("http://gpu-server:8000/v1") // vLLM 地址
.modelName("Qwen/Qwen2.5-72B-Instruct")
.temperature(0.3)
.timeout(Duration.ofSeconds(120)) // 私有部署延迟可能较高
.build();
}
2.2 DeepSeek
/**
* DeepSeek Agent 配置
*
* DeepSeek-V3 是目前国产模型中 Tool Calling 能力最强的之一。
* 在 Agent 场景的实测中,它的工具调用准确率与 GPT-4o 基本持平,
* 但价格只有 GPT-4o 的 1/5。
*
* 独特优势:
* 1. DeepSeek 的 "深度思考" 模式(DeepThink)特别适合
* 复杂的多步推理任务
* 2. 原生支持 JSON Mode 输出,结构化返回非常稳定
* 3. 128K 上下文窗口,长文本场景表现优秀
*/
@Bean
public ChatLanguageModel deepSeekModel() {
return OpenAiChatModel.builder()
.apiKey(System.getenv("DEEPSEEK_API_KEY"))
.baseUrl("https://api.deepseek.com/v1")
.modelName("deepseek-chat") // 即 DeepSeek-V3
.temperature(0.3)
.timeout(Duration.ofSeconds(60))
.maxRetries(3)
.build();
}
/**
* DeepSeek 的深度思考模式
*
* 通过特殊参数开启,模型会在回答前进行更深入的推理。
* 适合复杂的多步工具调用场景。
*
* 注意:深度思考模式会增加 Token 消耗(约 2~3 倍)和延迟,
* 建议只在复杂任务中使用。
*/
@Bean
public ChatLanguageModel deepSeekReasoningModel() {
return OpenAiChatModel.builder()
.apiKey(System.getenv("DEEPSEEK_API_KEY"))
.baseUrl("https://api.deepseek.com/v1")
.modelName("deepseek-reasoner") // 深度思考版本
.temperature(0.3)
.timeout(Duration.ofSeconds(180)) // 推理时间更长
.build();
}
2.3 智谱 GLM-4
/**
* 智谱 GLM-4 Agent 配置
*
* GLM-4 的 Tool Calling 接口与 OpenAI 略有差异,
* 需要使用 LangChain4j 的 Zhipu 专用适配器。
*
* 智谱的优势:
* 1. SDK 和文档最完善(中文文档最友好)
* 2. 内置 Web 搜索工具(可作为 Agent 的补充知识源)
* 3. 支持 Agent 应用模式(平台级的 Agent 托管)
*/
@Bean
public ChatLanguageModel glmModel() {
// 使用 LangChain4j 的智谱专用适配器
return ZhipuAiChatModel.builder()
.apiKey(System.getenv("ZHIPU_API_KEY"))
.model("glm-4-plus")
.temperature(0.3f)
.maxRetries(3)
.build();
}
/**
* GLM-4 的 Web 搜索工具集成
*
* 智谱平台内置了 Web 搜索能力,可以让 Agent 联网获取实时信息。
* 这在某些场景下比 RAG 更灵活——Agent 自主决定何时搜索。
*/
@Bean
public EnergyAgent glmAgentWithWebSearch() {
ZhipuAiChatModel model = ZhipuAiChatModel.builder()
.apiKey(System.getenv("ZHIPU_API_KEY"))
.model("glm-4-plus")
.webSearch(true) // 开启内置 Web 搜索
.build();
return AiServices.builder(EnergyAgent.class)
.chatLanguageModel(model)
.tools(energyTools)
.build();
}
2.4 多模型路由器(生产推荐架构)
在实际生产中,不应该只用一个模型。不同复杂度的任务应该路由到不同模型:
/**
* 生产级多模型路由器
*
* 架构思路:
* · 简单任务(意图分类、摘要提取)→ Qwen-Turbo(快、便宜)
* · 中等任务(单步工具调用)→ DeepSeek-V3(性价比高)
* · 复杂任务(多步推理、报告生成)→ Qwen-Max(能力最强)
* · 兜底方案 → 任一模型故障时自动切换备用
*
* 成本效果:
* · 相比全部使用 Qwen-Max:总成本降低约 65%
* · 相比全部使用 GPT-4o:总成本降低约 85%
*/
@Component
public class MultiModelRouter {
private final ChatLanguageModel fastModel; // qwen-turbo
private final ChatLanguageModel balancedModel; // deepseek-chat
private final ChatLanguageModel strongModel; // qwen-max
private final HealthChecker healthChecker;
public MultiModelRouter() {
this.fastModel = OpenAiChatModel.builder()
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
.modelName("qwen-turbo")
.temperature(0.1)
.build();
this.balancedModel = OpenAiChatModel.builder()
.apiKey(System.getenv("DEEPSEEK_API_KEY"))
.baseUrl("https://api.deepseek.com/v1")
.modelName("deepseek-chat")
.temperature(0.3)
.build();
this.strongModel = OpenAiChatModel.builder()
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
.modelName("qwen-max")
.temperature(0.3)
.build();
}
/**
* 根据任务类型路由到合适的模型
*
* 同时包含故障转移逻辑:如果首选模型不可用,
* 自动降级到备用模型。
*/
public ChatLanguageModel route(TaskType taskType) {
ChatLanguageModel primary = switch (taskType) {
case INTENT_CLASSIFICATION,
CONVERSATION_SUMMARY,
USER_PROFILE_EXTRACTION ->
fastModel;
case SINGLE_TOOL_CALL,
DATA_QUERY,
RAG_JUDGMENT ->
balancedModel;
case MULTI_STEP_REASONING,
COMPOSITE_ANALYSIS,
REPORT_GENERATION ->
strongModel;
};
// 健康检查:如果首选模型不可用,降级到备用
if (!healthChecker.isHealthy(primary)) {
log.warn("模型 {} 不可用,启动降级策略",
getModelName(primary));
return getFallback(primary);
}
return primary;
}
private ChatLanguageModel getFallback(
ChatLanguageModel failedModel) {
// 降级策略:strong → balanced → fast
if (failedModel == strongModel) return balancedModel;
if (failedModel == balancedModel) return fastModel;
return balancedModel; // fast 挂了用 balanced
}
}
多模型路由的成本对比:
┌────────────────────────────────────────────────────────────────┐
│ 月成本对比(日均 5000 次对话) │
│ │
│ 方案 月成本 相比 GPT-4o 节省 │
│ ───────────────────────────────────────────────── │
│ 全部 GPT-4o ¥45,000 - │
│ 全部 Qwen-Max ¥12,000 -73% │
│ 全部 DeepSeek-V3 ¥8,000 -82% │
│ 多模型路由(推荐) ¥5,200 -88% │
│ │
│ 假设:每次对话平均 3 轮 LLM 调用 │
│ 简单任务占 40%,中等任务占 40%,复杂任务占 20% │
│ │
└────────────────────────────────────────────────────────────────┘
三、高级推理模式(一):Plan-and-Execute
3.1 ReAct 的局限性
前几篇文章中,我们用的 ReAct(Reasoning + Acting)是最基础的推理模式——想一步,做一步。它在简单任务上效果很好,但在复杂任务上有一个根本问题:
缺乏全局规划。
举个例子,用户说:“帮我做一份本季度的能耗分析报告,包含各楼栋对比、同比环比、异常事件分析,最后给出优化建议。”
ReAct 的处理方式可能是:
- 查了 A 栋数据 → 发现还要查 B 栋 → 查了 B 栋 → 发现还要查 C 栋…
- 查完所有数据后 → 发现还要查去年同期做同比…
- 做了同比后 → 发现还要查上季度做环比…
整个过程像"走一步看一步",效率低,而且容易遗漏步骤。
3.2 Plan-and-Execute 原理
Plan-and-Execute 的核心思想是:先制定完整计划,再逐步执行。
┌────────────────────────────────────────────────────────┐
│ Plan-and-Execute 流程 │
│ │
│ 用户输入 │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ Planner │ "先想清楚要做什么" │
│ │ │ │
│ │ 输出: │ │
│ │ Step 1: 收集各楼栋本季度能耗数据 │
│ │ Step 2: 收集去年同期数据(同比) │
│ │ Step 3: 收集上季度数据(环比) │
│ │ Step 4: 数据对比分析 │
│ │ Step 5: 检索本季度异常事件记录 │
│ │ Step 6: 生成分析报告 │
│ │ Step 7: 给出优化建议 │
│ └────┬─────┘ │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ Executor │ "按计划一步步执行" │
│ │ │ │
│ │ Step 1 ✓ │ → 调用工具查 A/B/C 栋本季度数据 │
│ │ Step 2 ✓ │ → 调用工具查去年同期数据 │
│ │ Step 3 ✓ │ → 调用工具查上季度数据 │
│ │ Step 4 ✓ │ → LLM 做对比分析 │
│ │ Step 5 ✓ │ → 调用工具检索异常事件 │
│ │ Step 6 ✓ │ → LLM 生成报告 │
│ │ Step 7 ✓ │ → LLM 给出建议 │
│ └────┬─────┘ │
│ │ │
│ ▼ │
│ 最终报告 │
│ │
└────────────────────────────────────────────────────────┘
3.3 Plan-and-Execute 实现
/**
* 计划步骤定义
*/
public record PlanStep(
int stepNumber,
String description, // "收集各楼栋本季度能耗数据"
StepType type, // TOOL_CALL / LLM_REASONING / COMPOSITE
String requiredTool, // 如果需要工具调用
List<String> dependsOn // 依赖的前置步骤编号
) {
public enum StepType {
TOOL_CALL, // 需要调用外部工具
LLM_REASONING, // 纯 LLM 推理(分析、总结)
COMPOSITE // 工具调用 + LLM 推理
}
}
/**
* 计划生成器(Planner)
*
* 用一个专门的 LLM 调用生成执行计划。
*
* 关键设计:
* - 计划生成器不执行任何操作,只"规划"
* - 计划是结构化的(JSON),不是自然语言
* - 支持步骤间的依赖关系(DAG)
*/
@Service
public class Planner {
private final ChatLanguageModel plannerModel;
public Planner(MultiModelRouter router) {
// 规划任务用最强的模型——计划的质量决定执行的质量
this.plannerModel = router.route(TaskType.COMPOSITE_ANALYSIS);
}
/**
* 为复杂任务生成执行计划
*/
public List<PlanStep> createPlan(String userQuery,
List<String> availableTools) {
String prompt = String.format("""
你是一个任务规划专家。请为用户的复杂任务制定详细的执行计划。
## 可用工具
%s
## 规划要求
1. 每个步骤必须明确是"工具调用"还是"LLM推理"
2. 标注步骤间的依赖关系(哪些步骤可以并行,哪些必须串行)
3. 步骤粒度适中——不要太粗(无法执行)也不要太细(浪费调用)
4. 确保计划覆盖了用户需求的所有方面
按 JSON 格式返回:
{
"steps": [
{
"stepNumber": 1,
"description": "步骤描述",
"type": "TOOL_CALL|LLM_REASONING|COMPOSITE",
"requiredTool": "工具名或null",
"dependsOn": []
}
]
}
## 用户任务
%s
""",
String.join("\n", availableTools),
userQuery);
String result = plannerModel.generate(
UserMessage.from(prompt)).content().text().trim();
return parsePlan(result);
}
}
/**
* 计划执行引擎(Executor)
*
* 按顺序执行计划中的每个步骤,
* 并将前置步骤的输出作为当前步骤的输入。
*/
@Service
public class PlanExecutor {
private final ChatLanguageModel executorModel;
private final Map<String, Function<Map<String, Object>, Object>>
toolRegistry;
/**
* 执行完整计划
*
* @param plan 执行计划
* @param userQuery 原始用户问题
* @return 每个步骤的执行结果
*/
public PlanExecutionResult execute(List<PlanStep> plan,
String userQuery) {
Map<Integer, StepResult> stepResults = new LinkedHashMap<>();
List<String> executionLog = new ArrayList<>();
for (PlanStep step : plan) {
log.info("执行计划 Step {}: {}",
step.stepNumber(), step.description());
executionLog.add(String.format("Step %d: %s",
step.stepNumber(), step.description()));
// 收集前置步骤的输出作为上下文
String previousContext = step.dependsOn().stream()
.mapToInt(Integer::parseInt)
.filter(stepResults::containsKey)
.mapToObj(i -> stepResults.get(i).output())
.collect(Collectors.joining("\n\n"));
StepResult result;
try {
result = switch (step.type()) {
case TOOL_CALL ->
executeToolStep(step, previousContext);
case LLM_REASONING ->
executeReasoningStep(step, userQuery,
previousContext);
case COMPOSITE ->
executeCompositeStep(step, userQuery,
previousContext);
};
} catch (Exception e) {
log.error("Step {} 执行失败: {}",
step.stepNumber(), e.getMessage());
result = StepResult.failed(
step.stepNumber(), e.getMessage());
}
stepResults.put(step.stepNumber(), result);
executionLog.add(String.format(" → %s",
result.success() ? "成功" : "失败: " + result.error()));
}
// 最后一个步骤的输出就是最终结果
StepResult finalStep = stepResults.get(
plan.get(plan.size() - 1).stepNumber());
return new PlanExecutionResult(
finalStep != null ? finalStep.output() : "",
executionLog,
stepResults
);
}
private StepResult executeToolStep(PlanStep step,
String previousContext) {
// 调用注册的工具
var toolFunc = toolRegistry.get(step.requiredTool());
if (toolFunc == null) {
return StepResult.failed(step.stepNumber(),
"工具未注册: " + step.requiredTool());
}
// 用 LLM 从上下文中提取工具参数
String argsJson = extractToolArgs(
step.requiredTool(), step.description(), previousContext);
Map<String, Object> args = JsonUtils.parseMap(argsJson);
Object result = toolFunc.apply(args);
return StepResult.success(step.stepNumber(),
String.valueOf(result));
}
private StepResult executeReasoningStep(PlanStep step,
String userQuery,
String previousContext) {
String prompt = String.format("""
请根据以下上下文完成分析任务。
原始任务:%s
当前步骤:%s
前序步骤结果:
%s
请给出详细的分析结果。
""", userQuery, step.description(), previousContext);
String result = executorModel.generate(
UserMessage.from(prompt)).content().text().trim();
return StepResult.success(step.stepNumber(), result);
}
}
3.4 计划重规划(Re-planning)
这是 Plan-and-Execute 最强大的特性——执行过程中发现问题,可以动态修改计划。
/**
* 自适应重规划
*
* 场景:Step 3 执行失败(某个数据源不可用),
* 需要修改后续计划以适应新的情况。
*/
@Service
public class AdaptivePlanner {
private final Planner planner;
private final PlanExecutor executor;
/**
* 带重规划的执行循环
*
* 工作流程:
* 1. 生成初始计划
* 2. 逐步执行
* 3. 某步骤失败 → 判断是否需要重规划
* 4. 重规划时:保留已完成步骤的结果,修改后续步骤
* 5. 继续执行新计划
*/
public PlanExecutionResult executeWithReplanning(
String userQuery, List<String> availableTools) {
// 1. 初始规划
List<PlanStep> plan = planner.createPlan(
userQuery, availableTools);
int maxReplans = 2; // 最多重规划 2 次
int replanCount = 0;
while (replanCount <= maxReplans) {
// 2. 执行计划
PlanExecutionResult result = executor.execute(
plan, userQuery);
// 3. 检查是否有失败步骤
Optional<StepResult> failedStep = result.stepResults()
.values().stream()
.filter(r -> !r.success())
.findFirst();
if (failedStep.isEmpty()) {
return result; // 全部成功,结束
}
// 4. 重规划
replanCount++;
if (replanCount > maxReplans) {
log.warn("达到最大重规划次数,返回当前结果");
return result;
}
log.info("Step {} 失败,触发重规划 (第{}次)",
failedStep.get().stepNumber(), replanCount);
// 构建重规划请求:包含已完成步骤和失败原因
String replanPrompt = String.format("""
原计划执行过程中遇到问题:
原计划:
%s
已完成的步骤:
%s
失败步骤:%s
失败原因:%s
请基于当前情况重新规划剩余步骤。
""",
formatPlan(plan),
formatCompletedSteps(result),
failedStep.get().stepNumber(),
failedStep.get().error()
);
plan = planner.createPlan(replanPrompt, availableTools);
}
return executor.execute(plan, userQuery);
}
}
四、高级推理模式(二):Reflection(反思)
4.1 什么是 Reflection?
Reflection 的核心思想极其简洁:Agent 执行完一个动作后,回头审视自己的输出,判断是否有问题,如果有则修正。
这就像人类写作——第一稿写完后通读一遍,发现逻辑不通或数据有误,然后修改。没有 Reflection 的 Agent 就像一个"从不检查自己作业的学生"。
4.2 实现 Reflection 循环
/**
* Reflection Agent
*
* 工作原理:
*
* 生成 ──→ 评审 ──→ 修改 ──→ 评审 ──→ ... ──→ 通过
* │ │ │ │
* │ ▼ │ ▼
* │ "这里有个 │ "还有问题吗?"
* │ 数据错误" │ "没有了" → 输出
* │ │
* └───────────────────┘
*
* 关键设计:
* - Generator 和 Reviewer 使用不同的 Prompt(甚至不同模型)
* - 最大迭代次数限制(防止无限循环)
* - Reviewer 输出结构化反馈,而非笼统的"好/不好"
*/
@Service
public class ReflectionAgent {
private final ChatLanguageModel generatorModel;
private final ChatLanguageModel reviewerModel;
private static final int MAX_ITERATIONS = 3;
/**
* 带反思循环的内容生成
*
* @param task 生成任务描述
* @param context 参考资料(工具返回值、RAG 结果等)
* @return 经过反思优化的最终输出
*/
public ReflectionResult generate(String task, String context) {
String currentDraft = null;
String feedback = null;
List<ReflectionRound> rounds = new ArrayList<>();
for (int i = 0; i < MAX_ITERATIONS; i++) {
// ===== 生成/修改阶段 =====
currentDraft = generateDraft(task, context, feedback);
// ===== 评审阶段 =====
ReviewResult review = reviewDraft(task, currentDraft, context);
rounds.add(new ReflectionRound(
i + 1, currentDraft, review.feedback(),
review.issues().size(), review.passed()));
if (review.passed()) {
log.info("Reflection 通过: 第 {} 轮", i + 1);
return new ReflectionResult(currentDraft, rounds);
}
// 将评审反馈传递给下一轮生成
feedback = review.feedback();
log.info("Reflection 第 {} 轮发现 {} 个问题,继续修改",
i + 1, review.issues().size());
}
// 达到最大迭代次数,返回当前版本
log.warn("Reflection 达到最大迭代次数 {}", MAX_ITERATIONS);
return new ReflectionResult(currentDraft, rounds);
}
/**
* 生成/修改草稿
*/
private String generateDraft(String task, String context,
String previousFeedback) {
String prompt;
if (previousFeedback == null) {
// 首轮:从头生成
prompt = String.format("""
请完成以下任务:
任务:%s
参考资料:
%s
请生成高质量的输出。
""", task, context);
} else {
// 后续轮:根据反馈修改
prompt = String.format("""
请根据以下反馈修改你的输出。
任务:%s
你之前的输出:
%s
评审反馈:
%s
请针对性地修复反馈中指出的问题,保持其他部分不变。
""", task, context, previousFeedback);
}
return generatorModel.generate(
UserMessage.from(prompt)).content().text().trim();
}
/**
* 评审草稿
*
* Reviewer 的输出必须是结构化的反馈,包含:
* - 是否通过(pass/fail)
* - 具体问题列表(每个问题有位置和描述)
* - 修改建议
*/
private ReviewResult reviewDraft(String task, String draft,
String context) {
String prompt = String.format("""
你是一个严格的质量评审员。请评审以下输出是否满足任务要求。
## 任务
%s
## 参考资料(事实来源)
%s
## 待评审输出
%s
## 评审维度
1. 数据准确性:所有数值是否与参考资料一致?
2. 完整性:是否覆盖了任务要求的所有方面?
3. 逻辑性:分析和结论是否逻辑自洽?
4. 格式规范:是否清晰易读?
按 JSON 返回:
{
"passed": true/false,
"overallScore": 0~10,
"issues": [
{
"dimension": "数据准确性|完整性|逻辑性|格式规范",
"description": "问题描述",
"suggestion": "修改建议"
}
],
"feedback": "给生成者的综合反馈(简洁、可操作)"
}
""", task, context, draft);
String result = reviewerModel.generate(
UserMessage.from(prompt)).content().text().trim();
return parseReview(result);
}
}
/**
* Reflection 结果
*/
public record ReflectionResult(
String finalOutput,
List<ReflectionRound> rounds
) {
public int totalIterations() { return rounds.size(); }
public boolean passedWithinLimit() {
return rounds.stream().anyMatch(r -> r.issueCount() == 0);
}
}
public record ReflectionRound(
int roundNumber,
String draft,
String feedback,
int issueCount,
boolean passed
) {}
五、高级推理模式(三):Self-Consistency(自洽性验证)
5.1 原理
Self-Consistency 是解决 “Agent 回答不稳定” 的利器。核心思想:
对同一个问题,让 Agent 用不同路径推理 N 次,然后取多数一致的答案。
这就像你问三个专家同一个问题——如果两人都说 A,一人说 B,那 A 的可信度更高。
问题:"A栋本月能耗是否异常?"
路径1: 查本月数据 → 查上月数据 → 对比 → "异常,超出32%"
路径2: 查本月数据 → 查去年同期 → 对比 → "异常,超出28%"
路径3: 查本月数据 → 查30天均值 → 对比 → "正常,仅超出8%"
投票结果:2/3 认为"异常" → 最终回答"异常"
置信度:66.7%
5.2 实现
/**
* Self-Consistency 推理引擎
*
* 适用场景:
* - 需要高可靠性的判断(如告警决策)
* - 模型对某类问题回答不稳定时
*
* 注意:成本是普通推理的 N 倍(N = 推理路径数)
* 建议只在关键决策点使用,而非每次对话都用。
*/
@Service
public class SelfConsistencyEngine {
private final ChatLanguageModel model;
private static final int NUM_PATHS = 3; // 推理路径数
/**
* 自洽性推理
*
* @param question 需要判断的问题
* @param context 上下文信息
* @return 经过多数投票的结果
*/
public ConsistencyResult reason(String question, String context) {
List<String> answers = new ArrayList<>();
// 用不同的推理提示获取多个答案
String[] reasoningStyles = {
"请用数据分析的方式回答",
"请从对比历史趋势的角度回答",
"请从规则判断的角度回答"
};
for (String style : reasoningStyles) {
String prompt = String.format("""
%s
上下文信息:
%s
问题:%s
请给出你的判断(只回答结论,不要解释过程)。
""", style, context, question);
String answer = model.generate(
UserMessage.from(prompt)).content().text().trim();
answers.add(answer);
}
// 多数投票
return majorityVote(question, answers);
}
/**
* 多数投票算法
*
* 对自由文本答案做投票的难点:
* 答案措辞不同但含义相同(如"异常"和"偏高"),
* 需要用 LLM 做语义聚类后再投票。
*/
private ConsistencyResult majorityVote(String question,
List<String> answers) {
// 用 LLM 对答案做语义聚类
String clusterPrompt = String.format("""
以下是三个专家对同一问题的回答。
请将含义相似的回答归为一组,并统计每组的数量。
问题:%s
回答1:%s
回答2:%s
回答3:%s
按 JSON 返回:
{
"clusters": [
{
"representativeAnswer": "该组的代表性回答",
"count": 支持此回答的数量,
"memberIndices": [1, 2]
}
]
}
""", question, answers.get(0), answers.get(1), answers.get(2));
String result = model.generate(
UserMessage.from(clusterPrompt)).content().text().trim();
JsonNode node = JsonUtils.parse(result);
JsonNode clusters = node.get("clusters");
// 找到票数最多的聚类
JsonNode majority = clusters.get(0);
for (int i = 1; i < clusters.size(); i++) {
if (clusters.get(i).get("count").asInt()
> majority.get("count").asInt()) {
majority = clusters.get(i);
}
}
int majorityCount = majority.get("count").asInt();
double confidence = (double) majorityCount / NUM_PATHS;
return new ConsistencyResult(
majority.get("representativeAnswer").asText(),
confidence,
answers,
majorityCount >= 2 // 至少 2/3 一致才算可信
);
}
}
public record ConsistencyResult(
String finalAnswer,
double confidence, // 0.0~1.0
List<String> allAnswers,
boolean isConsistent // 是否达到多数一致
) {}
六、三种推理模式的对比与选择
┌──────────────────────────────────────────────────────────────────┐
│ 三种高级推理模式对比 │
│ │
│ 维度 ReAct Plan-and-Execute Reflection S-C │
│ ───────────────────────────────────────────────────────────── │
│ 适用场景 简单工具调用 复杂多步任务 高质量输出 关键决策│
│ LLM调用次数 2~5次 5~10次 2~6次 3~9次 │
│ 成本 低 中~高 中 高 │
│ 延迟 2~5s 8~20s 5~15s 5~12s │
│ 可靠性 中 高 高 最高 │
│ 实现复杂度 低 中 中 中 │
│ │
│ 选择建议: │
│ · 日常对话、简单查询 → ReAct(默认) │
│ · "做一份报告"、"分析+通知+生成" → Plan-and-Execute │
│ · 报告内容、决策建议 → Reflection │
│ · "该不该触发告警?"等高风险判断 → Self-Consistency │
│ │
│ 生产最佳实践:组合使用 │
│ Plan-and-Execute 负责全局编排 │
│ → 每个步骤内部用 ReAct │
│ → 关键输出用 Reflection 检查 │
│ → 高风险决策点用 Self-Consistency 验证 │
│ │
└──────────────────────────────────────────────────────────────────┘
组合使用示例
/**
* 高级 Agent:组合多种推理模式
*
* 架构:
* Plan-and-Execute(全局编排)
* └── 每个步骤内部:ReAct(工具调用)
* └── 报告生成步骤:Reflection(质量保障)
* └── 告警决策步骤:Self-Consistency(可靠性保障)
*/
@Service
public class AdvancedAgent {
private final AdaptivePlanner planner;
private final PlanExecutor executor;
private final ReflectionAgent reflectionAgent;
private final SelfConsistencyEngine consistencyEngine;
/**
* 处理复杂任务
*/
public String handleComplexTask(String userQuery) {
// Step 1: 规划
List<PlanStep> plan = planner.createPlan(userQuery, availableTools);
// Step 2: 执行(内部用 ReAct)
PlanExecutionResult result = planner.executeWithReplanning(
userQuery, availableTools);
// Step 3: 对报告类输出做 Reflection
if (containsReportGeneration(plan)) {
ReflectionResult refined = reflectionAgent.generate(
"生成能耗分析报告",
result.toContextString());
return refined.finalOutput();
}
// Step 4: 对告警决策做 Self-Consistency
if (containsAlertDecision(plan)) {
ConsistencyResult consistent = consistencyEngine.reason(
"是否需要触发告警?",
result.toContextString());
if (!consistent.isConsistent()) {
return result.finalOutput()
+ "\n\n[注意: 告警判断存在分歧,建议人工复核]";
}
}
return result.finalOutput();
}
}
七、八篇文章完整知识图谱
┌─────────────────────────────────────────────────────────────────┐
│ Java AI Agent 实战系列 · 完整路线图 │
│ │
│ 第一篇 ── 单体 Agent 构建 │
│ │ Tool Calling + RAG + Memory │
│ │ │
│ 第二篇 ── Multi-Agent 协作 + MCP 协议 │
│ │ LangGraph4j 编排 + MCP 工具标准化 │
│ │ │
│ 第三篇 ── 评估体系 + A2A 协议 │
│ │ 四维评估 + LLM-as-Judge + 跨组织通信 │
│ │ │
│ 第四篇 ── 长期记忆 + 用户画像 │
│ │ 三层记忆架构 + 画像自动提取 │
│ │ │
│ 第五篇 ── 可观测性 + 成本优化 │
│ │ 链路追踪 + 会话回放 + Token 精算 │
│ │ │
│ 第六篇 ── RAG 深度优化 │
│ │ 语义切分 + 混合检索 + 重排序 │
│ │ │
│ 第七篇 ── Agent 安全攻防 │
│ │ Prompt 注入防御 + 工具权限沙箱 + 幻觉检测 │
│ │ │
│ 第八篇 ── 国产大模型 + 高级推理模式 (本篇) │
│ 四大模型实战 + Plan-Execute + Reflection + S-C │
│ │
│ 能力进阶路线: │
│ 能构建 → 能协作 → 能评估 → 能记忆 → 能运维 → 能检索 │
│ → 能防御 → 能落地(国产模型)+ 能深度推理 │
│ │
└─────────────────────────────────────────────────────────────────┘
374



被折叠的 条评论
为什么被折叠?



