一、什么是结构化输出?

1. 定义

结构化输出(Structured Output):让大模型不返回自由文本,而是严格按指定格式(如 JSON)输出,程序可直接解析成对象,免手动字符串处理、免正则、免 JSON.parse 异常Spring。

2. 为什么要用?

  • 类型安全:直接映射到 Java Bean,编译期校验字段
  • 稳定性高:模型输出固定字段,无多余解释
  • 开发高效:告别String→手动解析→try-catch
  • 易集成:直接对接数据库、API、前端 JSON

3. Spring AI 两种实现方式

方式 1:ChatClient 的 .entity ()(最简洁,推荐)

底层封装了BeanOutputConverter,一行代码直接返回 Bean。

// 直接返回 Weather 对象,无需手动转换
Weather weather = chatClient.prompt("查询北京今日天气")
    .call()
    .entity(Weather.class); // 自动JSON→Bean

方式 2:BeanOutputConverter(灵活可控,适合复杂场景)

手动创建转换器,可自定义 Schema、清洗规则。

// 1. 初始化转换器
BeanOutputConverter<Weather> converter = new BeanOutputConverter<>(Weather.class);
// 2. 提示词强制JSON格式(注入Schema要求)
String prompt = """
    查询 %s 今日天气,仅返回JSON,不要解释。
    %s
    """.formatted("北京", converter.getFormat());
// 3. 调用模型 + 转换
String json = chatClient.prompt(prompt).call().content();
Weather weather = converter.convert(json);

代码案例:

package org.example.ai_demo.entity;
import lombok.Data;
@Data // Lombok:自动生成getter/setter/toString/无参构造
public class Weather {
    private String city;        // 城市
    private String temperature; // 温度
    private String weatherDesc; // 天气状况(晴/雨)
    private String wind;        // 风向风力
}
package org.example.ai_demo.controller;
import org.example.ai_demo.entity.Weather;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.converter.BeanOutputConverter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class WeatherController {
    private final ChatClient chatClient;
    // 注入ChatClient(Spring AI自动配置)
    public WeatherController(ChatClient.Builder builder) {
        this.chatClient = builder.build();
    }
    // 方式1:.entity() 简洁版(推荐)
    @GetMapping("/weather/simple")
    public Weather getWeatherSimple(@RequestParam String city) {
        return chatClient.prompt("查询" + city + "今日天气,仅返回JSON")
                .call()
                .entity(Weather.class);
    }
    // 方式2:BeanOutputConverter 完整版
    @GetMapping("/weather/full")
    public Weather getWeatherFull(@RequestParam String city) {
        // 初始化转换器
        BeanOutputConverter<Weather> converter = new BeanOutputConverter<>(Weather.class);
        // 构造提示词(强制JSON + 注入Schema)
        String prompt = String.format("""
                查询 %s 的今日天气,严格返回JSON,不要任何额外文字。
                输出格式要求:%s
                """, city, converter.getFormat());
        // 调用模型并转换
        String jsonResult = chatClient.prompt(prompt).call().content();
        return converter.convert(jsonResult);
    }
}

要记得引入依赖:

<!-- Spring AI 核心 -->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-core</artifactId>
    <version>1.0.0-M1</version>
</dependency>
<!-- 通义千问适配器(阿里云) -->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-alibaba-starter</artifactId>
    <version>1.0.0-M1</version>
</dependency>
<!-- Lombok(@Data 必须) -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<!-- Web(控制器) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

三、大模型是如何工作的?

大模型(如通义千问)的问答过程,本质是逐词预测、概率采样、拼接输出的循环:

1. 输入阶段(Prompt)

你输入问题:"查询北京今日天气" → 模型把文字转成Token(词 / 字) → 输入神经网络。

2. 推理阶段(核心:概率计算)

模型计算下一个 Token 的概率分布(比如:"北京""今日"概率 90%,"明天"概率 8%,"昨天"概率 2%)。

3. 采样阶段(参数控制:temperature/top_p/top_k)

根据温度、top_p、top_k筛选候选 Token,随机选一个(控制输出严谨度 / 创意度)。

4. 输出阶段(循环直到结束)

选中的 Token 加入输出 → 作为新输入,重复步骤 2-3 → 直到遇到结束符(</s>) → 输出完整回答。

5. 结构化输出的额外步骤

在 Prompt 中加入JSON Schema 约束 → 模型按 Schema 生成 JSON → Spring AI 的BeanOutputConverter自动反序列化为 Java BeanSpring 框架。

四、三大核心参数详解(temperature/top_p/top_k)

1. Temperature(温度:控制创造力)

  • 范围0 ≤ temperature ≤ 2(推荐 0.1–1.0)
  • 作用:调整概率分布的尖锐度
    • 低(0.1–0.3):概率集中,输出严谨、稳定、少幻觉(适合代码、事实问答、RAG)
    • 中(0.4–0.7):平衡准确与多样(日常对话、文案、翻译,默认 0.7)
    • 高(0.8–1.2):概率分散,输出创意、发散、易跑题(写诗、故事、 brainstorm)
  • 公式logits_after = logits / temperature → softmax 转概率

2. Top-K(限制候选词数量)

  • 范围1 ≤ top_k ≤ 100(常用 10–50)
  • 作用:只保留概率最高的 K 个 Token,其余概率置 0 → 从 K 个中采样
    • top_k=1:贪心搜索,永远选概率最高的,输出固定
    • top_k=50:保留前 50 个候选,平衡稳定与多样
  • 优缺点:避免极低概率词选中,但 K 固定,无法适配不同分布

3. Top-P(核采样:动态累积概率)

  • 范围0 ≤ top_p ≤ 1(常用 0.7–0.9)
  • 作用:累积概率≥P时截断候选 → 只从高概率集合中采样
    • top_p=0.9:保留累积概率 90% 的候选(动态数量,适配分布)
    • top_p=1.0:不截断,全候选采样
  • 优势:比 top_k 更灵活,优先选高概率词,兼顾多样性

4. 场景化参数推荐

场景 Temperature Top-P Top-K 说明
代码生成 / SQL 0.2–0.4 0.7 10 严谨、语法正确
知识库 / RAG 问答 0.1–0.3 0.8 20 少幻觉、忠于参考
日常对话 / 文案 0.5–0.7 0.9 50 平衡准确与流畅
创意写作 / 写诗 0.8–1.0 0.95 80 发散、有想象力

五、总结

  1. 结构化输出:大模型返回 JSON,Spring AI 一键转 Java Bean,类型安全、稳定高效Spring。
  2. 两种写法.entity()简洁、BeanOutputConverter灵活。
  3. 三大参数temperature 控创意、top_k 控数量、top_p 控概率,场景化设置即可。
  4. 千问调优:先 API 参数调优,复杂场景用 SFT 微调,temperature≤0.5是结构化输出关键。

觉得上面的内容有用吗?快来点个赞吧!

点赞() 我要打赏

温馨提示 : 本站内容来自会员投稿以及互联网,所有源码及教程均为作者总结编辑,请大家在使用过程中提前做好备份,以免发生无法预知的错误,源码类教程请勿直接用于生产环境!

 可能感兴趣的文章