Prompt高级推理:COT思维链、Self-Consistency与ReAct模式实战

导读 :在与大模型交互的过程中,简单的"一问一答"往往难以胜任复杂的推理任务。本文将深入介绍三种提升大模型推理能力的核心技术------思维链(Chain of Thought, COT) 、自我一致性(Self-Consistency) 和 ReAct 模式。从"让模型先想再答"的基本思路,到"多次采样投票取最优"的暴力美学,再到"推理与行动交织"的 Agent 底层逻辑,逐步带你掌握 Prompt 高级推理的完整技能树。


一、思维链 COT:让模型先想再答

1.1 什么是思维链?

思维链(Chain of Thought,简称 COT)的核心思想非常直观:强制让模型在输出最终答案之前,先把推理过程写出来。

举个简单的例子:

小明有 5 个苹果,给了小红 2 个,又从超市买了 3 个,后来发现有 1 个烂了。请问小明现在有几个苹果?

人类的大脑会自动进行分步计算:5 - 2 + 3 - 1 = 5。但没有思维链的大模型可能会"凭感觉"直接给出一个数字,准确率难以保证。

1.2 为什么 COT 有效?

大模型生成 Token 是一个自回归过程------后面的 Token 依赖前面已生成的内容。当模型先写出:

  • 步骤 1:5 - 2 = 3
  • 步骤 2:3 + 3 = 6
  • 步骤 3:6 - 1 = 5

再生成最终答案时,答案的生成依赖于前面正确的推理链路,整体准确率自然就提升了。这就好比考试时要求你"写出解题过程"------过程对了,答案大概率不会错。

1.3 Zero-Shot COT:一句话激活思维链

最简单的使用方式,不需要给任何示例,只需在 Prompt 末尾加上一句"魔法咒语":

复制代码
请一步一步思考。

示例对比:

不加 COT 的 Prompt:

复制代码
一个项目有三名开发,每人每天完成两个功能点,项目共60个功能点,
其中20%需要双人协作完成,完成项目需要多少天?

加上 COT 的 Prompt:

复制代码
一个项目有三名开发,每人每天完成两个功能点,项目共60个功能点,
其中20%需要双人协作完成,完成项目需要多少天?
让我们一步一步思考。

加上 COT 后,模型会自动拆解:先计算单人功能点数,再计算协作功能点的耗时,最后汇总得出正确的总天数。

常用的 COT 触发语句包括:

  • 让我们一步一步思考
  • 请先分析再给出结论
  • 请展示你的推理过程
  • Think step by step

1.4 Few-Shot COT:用示例教会模型推理

当零样本效果不够理想时,可以通过提供带推理过程的示例来引导模型学习思考模式。

以"判断代码是否存在并发安全问题"为例,我们项目中的 code-review.st 模板(位于 prompt/src/main/resources/prompts/code-review.st)就使用了类似的思路:

复制代码
请 review 以下 {language} 代码:

{code}

检查重点:
1. 空指针和异常处理
2. 性能问题(循环、IO、数据库查询)
3. 并发安全
4. 资源释放(IO流、连接等)
5. 代码可读性

对每个问题:标注【严重程度】,说明原因,给出修复示例。

在 CodeReviewService(com.jichi.prompt.service.CodeReviewService)中,我们通过 PromptTemplate 加载这个模板,并结合 System Message 引导模型按 COT 风格逐步分析:

复制代码
@Service
public class CodeReviewService {

    private final DashScopeChatModel chatModel;

    @Value("classpath:prompts/code-review.st")
    private Resource codeReviewPromptResource;

    public CodeReviewService(DashScopeChatModel chatModel) {
        this.chatModel = chatModel;
    }

    public String review(String code, String language) {
        PromptTemplate pt = new PromptTemplate(codeReviewPromptResource);
        String userPrompt = pt.render(Map.of(
                "language", language,
                "code", code
        ));

        return chatModel.call(new Prompt(
                List.of(
                        new SystemMessage("""
                                你是一个资深工程师,专注代码质量。
                                找出 Bug、性能问题和最佳实践违反,每个问题标注严重程度。
                                """),
                        new UserMessage(userPrompt)
                )
        )).getResult().getOutput().getText();
    }
}

通过 System Message 中"找出 Bug、性能问题和最佳实践违反,每个问题标注严重程度"的指令,模型会按照"操作拆解 -> 场景分析 -> 风险判断"的链路来逐一分析。

1.5 COT + 结构化输出:推理完毕打包带走

在实际工程中,我们往往需要模型先推理,再输出结构化的结果 ,以便程序直接消费。在项目中,BugAnalysisController(com.jichi.prompt.controller.BugAnalysisController)就是一个典型案例:

复制代码
@RestController
@RequestMapping("/api/bug")
public class BugAnalysisController {

    private final ChatClient chatClient;

    public BugAnalysisController(DashScopeChatModel chatModel) {
        this.chatClient = ChatClient.builder(chatModel)
                .defaultSystem("""
                        你是一个资深 Java 工程师,擅长 bug 分析。
                        分析代码时,先推理出 bug 类型和根因,再填写结构化结论。
                        不确定的字段填 null。
                        """)
                .build();
    }

    record BugAnalysis(
            String bugType,
            String rootCause,
            List<String> affectedScenarios,
            String severity,
            String fix
    ) {}

    @PostMapping("/analyze")
    public BugAnalysis analyzeBug(@RequestBody String code) {
        return chatClient.prompt()
                .user("分析这段代码的 bug:\n\n" + code)
                .call()
                .entity(BugAnalysis.class);
    }
}

注意 System Prompt 中的关键语句:"先推理出 bug 类型和根因,再填写结构化结论"------这就是 COT 与结构化输出的结合。模型会先进行推理分析,然后输出类似这样的结构化结果:

复制代码
{
  "bugType": "并发安全问题",
  "rootCause": "count++ 不是原子操作,多线程下会产生数据竞争",
  "affectedScenarios": ["高并发计数", "多线程累加"],
  "severity": "HIGH",
  "fix": "使用 synchronized 关键字或 AtomicInteger 替代 int 类型"
}

Spring AI 的 .entity(BugAnalysis.class) 会自动将模型的 JSON 输出反序列化为 Java Record,非常适合在企业内部构建代码审核助手。

1.6 COT 的适用场景与局限

适合使用 COT 的场景:

场景 原因
数学逻辑计算 需要中间步骤保证准确性
代码 Bug 分析 需要追踪执行路径
法律/合同分析 需要逐条审查条款
需求分析与拆解 需要先拆分再逐一评估
复杂决策 需要衡量多个因素

不适合使用 COT 的场景:

  • 简单翻译、简单分类
  • 纯创意写作
  • 追求极致响应速度的场景

需要注意的是,COT 会增加 Token 消耗。只有在对准确率有较高要求的场景下,才值得开启思维链。

1.7 内置思考模式:COT 的进化

如今主流模型已经将 COT 能力内置到模型内部 ,无需在 Prompt 中显式要求。在项目的 ThinkingController(com.jichi.prompt.controller.ThinkingController)中,我们通过开启 enableThinking 参数来使用内置思考模式:

复制代码
@RestController
@RequestMapping("/api/thinking")
public class ThinkingController {

    private final DashScopeChatModel chatModel;

    public ThinkingController(DashScopeChatModel chatModel) {
        this.chatModel = chatModel;
    }

    @GetMapping("/qwen3")
    public String deepAnalysis(@RequestParam String question) {
        return chatModel.call(new Prompt(
                new UserMessage(question),
                DashScopeChatOptions.builder()
                        .withModel("qwen3-235b-a22b")  // Qwen3 支持思考模式的模型
                        .withEnableThinking(true)       // 开启内置思考模式
                        .build()
        )).getResult().getOutput().getText();
    }
}

内置思考模式与手动 COT 的区别在于:手动 COT 的推理过程会出现在普通输出中,而内置思考模式(withEnableThinking(true))的推理过程对用户不可见,但效果通常更好。


二、Self-Consistency:多次推理取最优答案

2.1 核心思想:一次算不对,多算几次

Self-Consistency(自我一致性)是一种"稍显暴力但效果极佳"的技术。其核心逻辑非常朴素:

同一个问题让模型推理多次,然后取出现次数最多的答案------多数投票机制。

这就好比十个人做同一道数学题,八个人得出的答案都是 5,另外两个人分别算出 6 和 7,那我们有充分理由相信 5 是正确答案。

2.2 原理解析

大模型每次生成时本身带有一定的随机性(由 temperature 参数控制)。对同一个问题多次采样时:

  • 正确答案倾向于在多次采样中反复出现
  • 错误答案通常具有随机性,难以重复

因此,通过统计出现频率最高的答案,就能有效排除偶然的推理错误。

关键参数 :temperature 必须大于 0,否则每次输出完全相同,多次采样就失去了意义。

2.3 基础实现:并行采样 + 投票

项目中的 SelfConsistencyService(com.jichi.prompt.service.SelfConsistencyService)完整实现了这个模式:

复制代码
@Service
public class SelfConsistencyService {

    private final DashScopeChatModel chatModel;

    public SelfConsistencyService(DashScopeChatModel chatModel) {
        this.chatModel = chatModel;
    }

    /**
     * Self-Consistency:采样 N 次,多数投票
     *
     * @param question    问题
     * @param sampleCount 采样次数(建议 3-7 次)
     * @return 出现最多的答案
     */
    public String query(String question, int sampleCount) throws Exception {
        ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();

        // Self-Consistency 需要 temperature > 0,否则每次输出相同,没有意义
        DashScopeChatOptions options = DashScopeChatOptions.builder()
                .withTemperature(0.7)
                .build();

        List<CompletableFuture<String>> futures = new ArrayList<>();
        for (int i = 0; i < sampleCount; i++) {
            futures.add(CompletableFuture.supplyAsync(
                    () -> chatModel.call(new Prompt(
                            new UserMessage(question + "\n\n让我们一步一步思考。"),
                            options
                    )).getResult().getOutput().getText(),
                    executor));
        }

        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
                .get(60, TimeUnit.SECONDS);

        List<String> answers = futures.stream()
                .map(f -> {
                    try { return f.get(); }
                    catch (Exception e) { return null; }
                })
                .filter(Objects::nonNull)
                .toList();

        return majorityVote(answers);
    }

    private String majorityVote(List<String> answers) {
        return answers.stream()
                .collect(Collectors.groupingBy(a -> a, Collectors.counting()))
                .entrySet().stream()
                .max(Map.Entry.comparingByValue())
                .map(Map.Entry::getKey)
                .orElse(answers.get(0));
    }
}

实现要点:

  1. 使用 Executors.newVirtualThreadPerTaskExecutor() 创建虚拟线程池并行发起请求,避免串行等待
  2. 每次请求的 Prompt 末尾追加 "\n\n让我们一步一步思考。",结合 COT 提升单次推理质量
  3. temperature 设为 0.7 保证每次采样的多样性
  4. majorityVote 方法对所有结果进行 groupingBy 统计,取频次最高的作为最终答案
  5. 设置 60 秒超时,防止个别请求拖住整体

对应的 Controller 暴露了 REST 接口,默认采样 5 次:

复制代码
@RestController
@RequestMapping("/self-consistency")
public class SelfConsistencyController {

    private final SelfConsistencyService selfConsistencyService;

    public SelfConsistencyController(SelfConsistencyService selfConsistencyService) {
        this.selfConsistencyService = selfConsistencyService;
    }

    @GetMapping("/query")
    public String query(@RequestParam String question,
                        @RequestParam(defaultValue = "5") int sampleCount) throws Exception {
        return selfConsistencyService.query(question, sampleCount);
    }
}

2.4 结构化输出 + 自我一致性

在实际业务中,往往需要对结构化结果进行多次采样后聚合。项目中的 ContractAnalysisService(com.jichi.prompt.service.ContractAnalysisService)完整展示了这个模式------合同风险分析场景。

首先定义结构化输出模型,使用 Java Record + 枚举:

复制代码
// com.jichi.prompt.enums.Verdict
public enum Verdict { YES, NO, UNCERTAIN }

// com.jichi.prompt.entity.ContractRisk
public record ContractRisk(
    Verdict hasRisk,
    String riskType,
    int severity   // 1-10
) {}

然后在 ContractAnalysisService 中实现多次采样 + 聚合:

复制代码
@Service
public class ContractAnalysisService {

    private final DashScopeChatModel chatModel;
    private final BeanOutputConverter<ContractRisk> converter;

    public ContractAnalysisService(DashScopeChatModel chatModel) {
        this.chatModel = chatModel;
        this.converter = new BeanOutputConverter<>(ContractRisk.class);
    }

    public ContractRisk analyzeWithConsistency(String clause) throws Exception {
        int sampleCount = 5;
        ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();

        DashScopeChatOptions options = DashScopeChatOptions.builder()
                .withTemperature(0.5)
                .build();

        String userContent = "分析这个合同条款:\n" + clause
                + "\n\n请先逐步分析,再给出结论。\n\n" + converter.getFormat();

        List<CompletableFuture<ContractRisk>> futures = new ArrayList<>();
        for (int i = 0; i < sampleCount; i++) {
            futures.add(CompletableFuture.supplyAsync(() -> {
                String raw = chatModel.call(new Prompt(
                        List.of(
                                new SystemMessage("你是合同法律顾问,分析合同条款是否存在法律风险。先思考,再给出结论。"),
                                new UserMessage(userContent)
                        ),
                        options
                )).getResult().getOutput().getText();
                return converter.convert(raw);
            }, executor));
        }

        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
                .get(60, TimeUnit.SECONDS);

        List<ContractRisk> results = futures.stream()
                .map(f -> { try { return f.get(); } catch (Exception e) { return null; } })
                .filter(Objects::nonNull)
                .toList();

        return aggregateResults(results);
    }

聚合逻辑是 Self-Consistency 与结构化输出结合的关键------对不同字段分别采用投票和取均值策略:

复制代码
    private ContractRisk aggregateResults(List<ContractRisk> results) {
        // 1. 风险判定投票:统计 YES 和 NO 的次数,多数决定最终结论
        long yesCount = results.stream().filter(r -> r.hasRisk() == Verdict.YES).count();
        long noCount = results.stream().filter(r -> r.hasRisk() == Verdict.NO).count();
        Verdict majorityVerdict = yesCount >= noCount ? Verdict.YES : Verdict.NO;

        // 2. 风险等级取均值:对多数派结果的严重程度取平均
        double avgSeverity = results.stream()
                .filter(r -> r.hasRisk() == majorityVerdict)
                .mapToInt(ContractRisk::severity)
                .average()
                .orElse(5.0);

        // 3. 风险类型聚合:统计出现频率最高的风险类型
        String topRiskType = results.stream()
                .filter(r -> r.hasRisk() == majorityVerdict)
                .map(ContractRisk::riskType)
                .filter(Objects::nonNull)
                .collect(Collectors.groupingBy(t -> t, Collectors.counting()))
                .entrySet().stream()
                .max(Map.Entry.comparingByValue())
                .map(Map.Entry::getKey)
                .orElse("未知风险");

        return new ContractRisk(majorityVerdict, topRiskType, (int) Math.round(avgSeverity));
    }
}

注意这里使用了 BeanOutputConverter<ContractRisk> 来自动处理模型输出到 Java Record 的转换,converter.getFormat() 会在 Prompt 中追加 JSON Schema 格式说明,引导模型输出符合规范的 JSON。

2.5 置信度评估

多次采样还带来一个额外好处------可以计算置信度:

复制代码
置信度 = 最高票答案出现次数 / 总采样次数

例如 5 次采样中有 4 次得出 Verdict.YES(有风险),则置信度为 80%。

在生产环境中,可以设置置信度阈值:

  • 置信度 >= 80%:直接采信结果
  • 置信度 60%-80%:标记为"建议人工复核"
  • 置信度 < 60%:触发人工审核流程

这种机制避免了将不确定的结果直接推送给用户。

2.6 成本权衡

Self-Consistency 本质是用N 倍的 API 费用换取更高的准确率,因此需要根据场景权衡:

场景类型 是否值得使用 说明
合同审查、安全检测 值得 高准确率要求,错误代价高
关键决策辅助 值得 关键问题值得多花成本
情感分析、内容分类 不值得 低风险场景,成本过高
日常内容生成 不值得 无需高精度
新一代推理模型 不值得 模型本身准确率已足够高,边际收益低

采样次数建议 :3-5 次通常足够,超过 7 次边际收益递减明显。建议选择奇数次,方便投票决胜。项目中 SelfConsistencyController 默认使用 5 次采样。

2.7 与推理模型的关系

Self-Consistency 是 Prompt 层面的技术,不依赖特定模型。但对于已经内置深度推理能力的模型(如 Qwen3-235B 开启 enableThinking),这些模型在内部已经做了类似的"多路径探索",此时再叠加 Self-Consistency 的意义不大。

因此:

  • 普通/快速模型 + Self-Consistency = 性价比之选
  • 推理增强模型 (如 qwen3-235b-a22b + withEnableThinking(true))= 不需要额外加 Self-Consistency

三、ReAct 模式:推理与行动交织

3.1 什么是 ReAct?

ReAct 来自 2022 年的同名论文,全称是 Re asoning + Act ing,即推理与行动的交替执行。它是 Agent 系统中最核心的 Prompt 模式,也是后续 Agent 开发的底层逻辑基础。

与纯 COT 不同,ReAct 的循环模式是:

复制代码
思考(Thought) -> 行动(Action) -> 观察(Observation) -> 思考 -> 行动 -> ... -> 最终答案

COT vs ReAct 的本质区别:

  • COT:思考 -> 答案(信息全部来自模型内部知识)
  • ReAct:思考 -> 行动 -> 观察 -> 思考 -> ... -> 答案(可以获取外部实时数据)

3.2 一个直观的例子

用户问:"北京天气怎么样,适合穿什么?"

ReAct 的执行过程:

复制代码
[Thought] 用户问的是北京的实时天气,我需要查询天气数据
[Action]  调用天气工具 getWeather("北京")
[Observation] 返回结果:城市:北京,温度:18°C,天气:晴,风力:3级
[Thought] 18度的晴天,早晚可能偏凉
[Answer] 北京今天晴天,气温 18°C,风力 3 级,建议穿轻薄外套,方便早晚增减。

模型在每一步推理后,判断是否需要调用外部工具获取信息,然后根据工具返回的结果继续推理,直到信息充足后给出最终答案。

3.3 传统 ReAct Prompt 的写法

在框架封装之前,需要手动编写 ReAct 格式的 System Prompt:

复制代码
你是一个智能助手,可以使用以下工具完成任务:

【工具列表】
1. getWeather(city): 查询指定城市的实时天气
2. getStockPrice(symbol): 查询股票实时价格
3. calculate(expression): 计算数学表达式

【工作流程】
1. 先思考(Thought):分析用户问题,判断需要什么信息
2. 再行动(Action):调用合适的工具获取数据
3. 观察结果(Observation):根据工具返回的结果继续思考
4. 重复步骤 1-3,直到收集到足够信息
5. 给出最终答案(Final Answer)

【格式要求】
Thought: <你的思考过程>
Action: <工具名称>(参数)
Observation: <工具返回结果>
... (重复直到完成)
Final Answer: <最终回答>

【注意事项】
- 每次只调用一个工具
- 如果不需要工具就能回答,直接给出 Final Answer

3.4 框架封装:Spring AI 的 ReAct 托管

手动编写 ReAct Prompt 比较繁琐,Spring AI 框架已经将 ReAct 模式进行了封装,自动管理思考-行动-观察的循环。

第一步:定义工具

项目中使用 @Tool 和 @ToolParam 注解定义工具。以下是实际代码(位于 com.jichi.prompt.tools 包下):

复制代码
@Component
public class WeatherTools {

    @Tool(description = "查询指定城市的实时天气,返回温度、天气状况和风力")
    public String getWeather(
            @ToolParam(description = "城市名称,例如:北京、上海") String city) {
        return String.format("城市:%s,温度:18°C,天气:晴,风力:3级", city);
    }
}

@Component
public class StockTools {

    @Tool(description = "查询股票实时价格")
    public String getStockPrice(
            @ToolParam(description = "股票代码,例如:AAPL、600036") String symbol) {
        return String.format("股票代码:%s,当前价格:168.42 USD", symbol);
    }
}

@Component
public class CalculatorTools {

    @Tool(description = "计算数学表达式")
    public String calculate(
            @ToolParam(description = "要计算的数学表达式,例如:(10 + 5) * 3 / 2") String expression) {
        return expression + " = 计算结果(实际应接入表达式求值库)";
    }
}

第二步:注册工具到 ChatClient 并设置 System Prompt

在 AgentController(com.jichi.prompt.controller.AgentController)中,通过 defaultTools() 注册工具:

复制代码
@RestController
@RequestMapping("/agent")
public class AgentController {

    private final ChatClient agentClient;

    public AgentController(
            DashScopeChatModel chatModel,
            WeatherTools weatherTools,
            StockTools stockTools,
            CalculatorTools calculatorTools) {

        this.agentClient = ChatClient.builder(chatModel)
                .defaultSystem("""
                        你是一个智能助手,可以查天气、查股价、做计算。
                        根据用户问题决定是否需要使用工具,使用工具后结合结果给出准确答案。
                        """)
                .defaultTools(weatherTools, stockTools, calculatorTools)
                .build();
    }

    @GetMapping("/ask")
    public String ask(@RequestParam String question) {
        return agentClient.prompt()
                .user(question)
                .call()
                .content();
    }
}

第三步:直接提问,框架自动处理 ReAct 循环

复制代码
// GET /agent/ask?question=苹果公司(AAPL)的股价折合人民币是多少?
String answer = agentClient.prompt()
        .user("苹果公司(AAPL)的股价折合人民币是多少?")
        .call()
        .content();

Spring AI 在内部自动完成了以下过程:

  1. 发送请求给模型
  2. 模型决定调用 getStockPrice("AAPL") -> 获取美元股价
  3. 模型决定调用 getExchangeRate("USD", "CNY") -> 获取汇率
  4. 模型决定调用 calculate("168.42 * 7.24") -> 计算人民币价格
  5. 模型组织自然语言回复给用户

整个多步推理过程由框架自动托管,开发者只需定义好工具即可。

3.5 金融场景:多工具组合实战

项目中还有一个更专业的金融 Agent 示例------FinanceAgentController(com.jichi.prompt.controller.FinanceAgentController),使用 FinanceTools 将股票、汇率、计算三个工具合并到一个类中:

复制代码
@Component
public class FinanceTools {

    @Tool(description = "查询股票实时价格")
    public String getStockPrice(@ToolParam(description = "股票代码") String symbol) {
        return symbol + " 当前价格:168.42 USD";
    }

    @Tool(description = "查询货币汇率")
    public String getExchangeRate(
            @ToolParam(description = "源货币代码") String from,
            @ToolParam(description = "目标货币代码") String to) {
        return from + "/" + to + " = 7.24";
    }

    @Tool(description = "计算数学表达式")
    public String calculate(@ToolParam(description = "数学表达式") String expression) {
        return expression + " ≈ 1219.36";
    }
}

@RestController
@RequestMapping("/finance-agent")
public class FinanceAgentController {

    private final ChatClient agentClient;

    public FinanceAgentController(DashScopeChatModel chatModel, FinanceTools financeTools) {
        this.agentClient = ChatClient.builder(chatModel)
                .defaultSystem("""
                        你是一个金融助手,可以查询实时股价、汇率,并做数学计算。
                        遇到需要数据的问题,先调工具获取数据,再给出完整答案。
                        """)
                .defaultTools(financeTools)
                .build();
    }

    @GetMapping("/ask")
    public String ask(@RequestParam String question) {
        return agentClient.prompt()
                .user(question)
                .call()
                .content();
    }
}

ReAct 真正强大之处在于自动串联多个工具调用。查询"苹果公司股价折合人民币是多少"时,模型会自动拆解为三步:

复制代码
Step 1: 调用 getStockPrice("AAPL") -> 获取股价 168.42 USD
Step 2: 调用 getExchangeRate("USD", "CNY") -> 获取汇率 7.24
Step 3: 调用 calculate("168.42 * 7.24") -> 计算得 1219.36
Final Answer: 苹果公司当前股价为 168.42 美元,按当前汇率 1 美元约等于 7.24 人民币,折合约 1219.36 元人民币。

3.6 循环控制

ReAct 理论上可以进行无限次的思考-行动循环,因此在生产环境中务必设置最大循环次数 ,防止死循环导致资源耗尽。在 Spring AI 中可以通过 toolCallingChatOptions 或 Advisor 来限制:

复制代码
ChatClient client = ChatClient.builder(chatModel)
    .defaultTools(tools)
    .build();

// 调用时可通过 ChatOptions 控制最大工具调用轮次
client.prompt()
    .user(question)
    .options(DashScopeChatOptions.builder()
        .withMaxTokens(2048)  // 限制输出长度,间接控制循环
        .build())
    .call()
    .content();

3.7 COT vs ReAct 对比总结

对比维度 COT ReAct
信息来源 模型内部知识 模型知识 + 外部工具/API
适用场景 逻辑推演、数学计算 实时查询、执行动作、多步任务
调用成本 较低(单次调用) 较高(多次 API 交互)
是否需要工具 不需要 需要 @Tool 定义并注册到 ChatClient
典型应用 Bug 分析、合同审查 智能助手、金融查询、自动化操作

四、总结

本文介绍了三种提升大模型推理能力的关键技术,它们形成了一个递进的体系:

  1. COT(思维链) :最基础的推理增强手段。通过强制模型"先推理再回答",利用自回归生成的特性,让后续 Token 依赖前面正确的推理步骤,从而提升复杂问题的准确率。使用门槛极低,一句"让我们一步一步思考"即可激活。在项目中,BugAnalysisController 的 System Prompt 中 "先推理出 bug 类型和根因,再填写结构化结论" 就是 COT 的典型应用。

  2. Self-Consistency(自我一致性) :在 COT 基础上的进一步增强。通过多次并行采样、投票取最优,利用概率统计的力量过滤掉偶然的推理错误。项目中 SelfConsistencyService 使用虚拟线程并行采样 + majorityVote 投票,ContractAnalysisService 则展示了结构化输出场景下的多维度聚合策略。适用于对准确率要求极高的场景(如合同审查、安全检测),但需要权衡 N 倍的 API 成本。

  3. ReAct(推理+行动) :从"纯思考"升级为"思考+行动"。模型不再局限于内部知识,而是可以调用外部工具获取实时信息,并在"思考-行动-观察"的循环中逐步解决问题。项目中 AgentController 和 FinanceAgentController 通过 Spring AI 的 ChatClient.defaultTools() 注册 @Tool 注解的工具类,框架自动托管 ReAct 循环,开发者只需关注工具实现。

在实际项目中,这三种技术可以灵活组合:ReAct 的每一步推理都可以使用 COT 来保证质量,而关键决策节点还可以叠加 Self-Consistency 来提升置信度。理解它们的原理和适用边界,才能在不同场景下做出最优选择。

相关推荐
霸道流氓气质5 小时前
Prompt 版本控制与 A/B 测试实战:语义版本管理、一致性哈希分流与 Thompson Sampling 的 Java 生产级实现
java·prompt·哈希算法
蟕初的梦想5 小时前
Claude Haiku 5.5 效能实测与场景应用指南
数据库·人工智能·大模型
论文复现现场6 小时前
金融大模型微调需要几张 RTX 4090?QLoRA 配置、工期估算与断点续训
大数据·金融·大模型·分布式训练·模型微调·qlora·rtx4090
VIP_CQCRE6 小时前
Visual Studio 接入 AI 助手:LMLocal × Ace Data Cloud 配置指南
大模型·api·ai编程·visual studio·acedatacloud
deepseek236 小时前
Gemini 4 Argon拆解:单次输出100万Token不是上下文游戏,长周期Agent的经济账怎么算
大模型·llm·谷歌·ai agent·gemini
BlackStar_L8 小时前
第五章 Coding Agent 与通用 Agent
大模型·llm·agent
欣欣之王来了9 小时前
国外主流大模型深度对比:GPT、Claude、Gemini技术细节与实战选型指南
人工智能·ai·大模型
孙启超12 小时前
【AI工程师精讲】04:思维链:CoT 为什么有效,以及它什么时候在骗你
人工智能·ai·大模型
jason.zeng@15022071 天前
(六)Prompt 优化
python·ai·langchain·prompt·ai编程·llama