目录
[1. 定义](#1. 定义)
[2. 为什么要用?](#2. 为什么要用?)
[3. Spring AI 两种实现方式](#3. Spring AI 两种实现方式)
[方式 1:ChatClient 的 .entity ()(最简洁,推荐)](#方式 1:ChatClient 的 .entity ()(最简洁,推荐))
[方式 2:BeanOutputConverter(灵活可控,适合复杂场景)](#方式 2:BeanOutputConverter(灵活可控,适合复杂场景))
[1. 输入阶段(Prompt)](#1. 输入阶段(Prompt))
[2. 推理阶段(核心:概率计算)](#2. 推理阶段(核心:概率计算))
[3. 采样阶段(参数控制:temperature/top_p/top_k)](#3. 采样阶段(参数控制:temperature/top_p/top_k))
[4. 输出阶段(循环直到结束)](#4. 输出阶段(循环直到结束))
[5. 结构化输出的额外步骤](#5. 结构化输出的额外步骤)
四、三大核心参数详解(temperature/top_p/top_k)
[1. Temperature(温度:控制创造力)](#1. Temperature(温度:控制创造力))
[2. Top-K(限制候选词数量)](#2. Top-K(限制候选词数量))
[3. Top-P(核采样:动态累积概率)](#3. Top-P(核采样:动态累积概率))
[4. 场景化参数推荐](#4. 场景化参数推荐)
一、什么是结构化输出?
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 | 发散、有想象力 |
五、总结
- 结构化输出 :大模型返回 JSON,Spring AI 一键转 Java Bean,类型安全、稳定高效Spring。
- 两种写法 :
.entity()简洁、BeanOutputConverter灵活。 - 三大参数 :temperature 控创意、top_k 控数量、top_p 控概率,场景化设置即可。
- 千问调优 :先 API 参数调优,复杂场景用 SFT 微调,temperature≤0.5是结构化输出关键。