一、💡 一句话理解
第 6 天核心结论
结构化输出,就是让模型返回可以被 Java 程序直接接收和处理的数据,而不是一段只能给人阅读的自然语言。JSON Schema 则是这份数据的“结构说明书”,规定字段名、字段类型、必填项和允许的取值。
本篇对应 0-学习路线 第 6 天:结构化输出、JSON Schema。
今天只完成一件事:让 ChatClient 把用户问题识别成一个 Java 对象,并通过 HTTP 接口返回稳定的 JSON 结构。
本篇不提前学习:
- SSE 流式响应
- 会话记忆和 Redis
- Function Calling / Tool Calling
- RAG 和 Agent 工作流
二、🧭 理论:它是什么
2.1 结构化输出是什么
第 4 天的普通调用通常这样写:
String answer = chatClient
.prompt("我的订单什么时候发货?")
.call()
.content();返回值是 String。这适合直接展示给用户,但不适合让后端继续做判断。
例如,业务代码想知道用户到底是在问订单、物流,还是售后。模型如果返回下面这段文字:
用户主要是在咨询订单的发货状态,建议查询订单信息。人可以看懂,但 Java 代码很难稳定判断。后端不能可靠地通过“包含订单两个字”来实现业务分支。
结构化输出会要求模型返回类似下面的对象:
{
"intent": "ORDER_STATUS",
"summary": "用户想查询订单的发货状态",
"needHumanConfirm": false
}这时 Java 可以直接读取:
CustomerIntent result = ...;
if ("ORDER_STATUS".equals(result.intent())) {
// 后续第 11~20 天再接入订单查询工具
}这里的核心变化是:
自然语言字符串
→ 结构明确的 JSON
→ Java 对象
→ 后端可以继续判断、保存或路由2.2 JSON 是什么
JSON 是一种用文本表示数据的格式。它主要由对象、数组、字符串、数字、布尔值和 null 组成。
下面是一个 JSON 对象:
{
"name": "张三",
"age": 28,
"vip": true,
"tags": ["java", "agent"]
}可以先这样理解:
| JSON 内容 | 白话理解 | Java 中常见的对应类型 |
|---|---|---|
{ ... } | 一组带名称的字段 | 对象、Map |
[ ... ] | 一组有顺序的数据 | List |
"张三" | 字符串 | String |
28 | 数字 | int、long、BigDecimal |
true / false | 是或否 | boolean |
null | 没有值 | null |
JSON 只负责表达数据,不负责说明“哪些字段必须存在”“年龄必须是整数”或“状态只能取哪几个值”。这些约束需要 JSON Schema 描述。
2.3 JSON Schema 是什么
JSON Schema 是一份用于描述和校验 JSON 数据的 JSON 文档。
可以把它类比成 Java 的类定义,但要注意:这只是帮助理解的类比。Java 类主要用于定义程序中的对象,JSON Schema 主要用于描述 JSON 数据应该长什么样,并让校验器判断数据是否符合要求。
例如,下面的 Schema 规定:数据必须是对象,必须包含 intent、summary 和 needHumanConfirm 三个字段,intent 只能从指定枚举值中选择。
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"intent": {
"type": "string",
"enum": [
"ORDER_STATUS",
"LOGISTICS",
"INVENTORY",
"AFTER_SALE",
"POLICY",
"OTHER"
]
},
"summary": {
"type": "string"
},
"needHumanConfirm": {
"type": "boolean"
}
},
"required": [
"intent",
"summary",
"needHumanConfirm"
]
}Schema 和数据的关系是:
JSON Schema:规定应该长什么样
↓ 校验
JSON 数据:实际返回了什么JSON Schema 官方教程将待校验的 JSON 称为 instance,将描述结构和约束的文档称为 schema。type、properties 和 required 是最常用的基础关键字。JSON Schema 官方入门教程
2.4 结构化输出和普通 JSON 的区别
“让模型返回 JSON”和“让模型返回符合 Schema 的结构化输出”不是一回事。
| 做法 | 能保证什么 | 不能保证什么 |
|---|---|---|
| 普通文本 | 模型返回一段文本 | 不保证是 JSON |
| Prompt 要求返回 JSON | 模型可能更容易返回 JSON | 仍可能多说解释、缺字段或类型错误 |
| JSON mode | 通常保证结果是合法 JSON | 不一定保证字段完全符合你的业务结构 |
| JSON Schema 结构化输出 | 在支持的模型接口中约束字段结构 | 不保证业务事实一定正确,也不替代业务校验 |
所以结构化输出解决的是“返回数据的形状”,不是“数据内容一定真实”。
例如,模型可能按照 Schema 正确返回:
{
"intent": "ORDER_STATUS",
"summary": "订单已经签收",
"needHumanConfirm": false
}但模型并没有查询订单系统,summary 中的事实仍然不能直接当成真实订单状态。真正的订单状态要等后续接入订单查询工具后,以业务系统返回的数据为准。
三、⚙️ 理论:它是怎么工作的
3.1 结构化输出的完整链路
在 Spring AI 中,结构化输出大致经过下面的过程:
Java 定义目标类型 CustomerIntent
↓
Spring AI 根据 Java 类型生成 JSON Schema
↓
把格式要求加入 Prompt,或发送给模型的原生结构化输出接口
↓
模型生成 JSON 文本
↓
Spring AI 解析 JSON
↓
转换为 CustomerIntent Java 对象
↓
Controller 返回业务 JSONSpring AI 官方当前的高层 API 使用 .entity(...) 获取目标类型,而不是使用 .content() 获取原始字符串:
CustomerIntent result = chatClient
.prompt()
.user("识别用户意图:我的订单什么时候发货?")
.call()
.entity(CustomerIntent.class);CustomerIntent.class 就是告诉 Spring AI:“我希望模型的结果最终转换成这个 Java 类型”。Spring AI 会根据这个类型生成 Schema,并将模型输出反序列化成对象。Spring AI Structured Output
3.2 ChatClient 的 .content() 和 .entity()
这两个方法都位于 .call() 之后,但返回目标不同:
| 写法 | 返回结果 | 适用场景 |
|---|---|---|
.content() | 模型生成的 String | 普通问答、聊天回复 |
.entity(Result.class) | 指定的 Java 对象 | 分类、抽取、路由、结构化业务结果 |
.responseEntity(Result.class) | Java 对象加完整响应信息 | 同时需要 Token、请求元数据和结构化结果 |
本篇使用 .entity(CustomerIntent.class),因为第 6 天的目标是先完成“模型输出 → Java 对象”的转换。
entity(...) 需要完整响应后才能解析对象,因此它属于 .call() 路径,不适用于 .stream() 流式输出。流式输出返回的是文本片段,不能在每个片段到达时直接得到完整 Java 对象。Spring AI Structured Output
3.3 Spring AI 如何从 Java 类型生成 Schema
本篇定义一个 Java record:
public record CustomerIntent(
String intent,
String summary,
boolean needHumanConfirm
) {
}它表达了三件事:
intent是字符串。summary是字符串。needHumanConfirm是布尔值。
在实际调用时,Spring AI 的 BeanOutputConverter 可以根据 Java 类或 record 生成 JSON Schema,并将模型输出转换为目标类型。BeanOutputConverter API
可以把它记成:
Java record
→ BeanOutputConverter
→ JSON Schema
→ 模型 JSON 输出
→ CustomerIntent这里不是把模型“变成了 Java 程序”,而是由 Java 类型作为目标格式,帮助模型和后端约定结果形状。
3.4 JSON Schema 中最常用的关键字
本篇只掌握后续 Agent 开发最常用的一小组关键字:
| 关键字 | 作用 | 示例 |
|---|---|---|
type | 限定数据类型 | "type": "object" |
properties | 定义对象有哪些字段 | "properties": { "name": ... } |
required | 指定必须存在的字段 | "required": ["name"] |
enum | 限定允许的固定值 | "enum": ["ORDER_STATUS", "OTHER"] |
items | 描述数组中每个元素的结构 | "items": { "type": "string" } |
description | 给字段补充说明 | "description": "用户意图" |
有两个容易混淆的点:
第一,字段出现在 properties 中,不代表它一定必填。是否必填要看它是否出现在同一层级的 required 数组中。
第二,字段是必填的,不代表字段内容一定正确。required 只能说明字段不能缺失,不能证明订单状态真实存在,也不能替代权限校验。
3.5 两种结构化输出方式
Spring AI 当前提供两条主要路径。
3.5.1 Prompt-based 结构化输出
默认的 .entity(...) 路径会把 Schema 或格式说明加入提示词,让模型按照要求输出;模型返回后,Spring AI 再解析成 Java 对象。
Java 类型
→ 生成 Schema
→ Schema 作为格式要求加入 Prompt
→ 模型返回 JSON 文本
→ Spring AI 转换为 Java 对象优点是兼容性较好,适合本篇使用的 OpenAI 兼容模型配置。缺点是它属于“要求模型遵守”,默认不是 API 层面的强制约束。
Spring AI 官方将这种转换描述为 best effort:模型不一定完全按照要求返回,因此业务代码仍需处理解析失败和校验失败。Spring AI Output Converters
3.5.2 Provider-native 结构化输出
如果模型供应商原生支持 JSON Schema 结构化输出,可以使用:
CustomerIntent result = chatClient
.prompt()
.user("识别用户意图:我的订单什么时候发货?")
.call()
.entity(CustomerIntent.class, spec -> spec.useProviderStructuredOutput());这会把 Schema 作为模型 API 的结构化输出参数发送,而不是只放在 Prompt 文本里。它通常更可靠,但依赖具体模型和供应商的支持情况。Spring AI 当前文档说明,原生支持检测依赖底层 Chat Options;如果模型不支持,不能把这段代码当成所有供应商都必然有效。Spring AI Provider-Native Structured Output
本篇的完整实践先使用默认 .entity(...),因为它不依赖某个具体供应商的原生能力。确认当前模型支持原生 Schema 后,再在单独的实验中开启 useProviderStructuredOutput()。
3.6 Schema 校验和自动纠错
Spring AI 当前支持在实体解析时开启 Schema 校验:
CustomerIntent result = chatClient
.prompt()
.user("识别用户意图:我的订单什么时候发货?")
.call()
.entity(CustomerIntent.class, spec -> spec.validateSchema());当模型返回的数据缺字段、类型错误或结构不符合 Schema 时,Spring AI 会把校验错误补充到下一次请求中并重试。当前官方文档说明,默认最多尝试 3 次;启用校验后需要完整响应,因此不支持流式解析。Spring AI Schema Validation
它解决的是“结构不符合要求”,不是“业务结果一定正确”。例如:
- 可以校验
needHumanConfirm是否为布尔值。 - 可以校验
intent是否属于枚举值。 - 不能证明订单是否真的已经发货。
- 不能替代登录态、权限和数据库校验。
四、🚀 实践:从准备到验证
4.1 前置准备
4.1.1 已完成前置学习
本篇沿用:
- 3.Spring AI ChatClient 中的
ChatClient.Builder注入方式。 - 4.Prompt、System Prompt、Prompt 模板 中的
.system(...)和.user(...)写法。 - 2.大模型 API、请求参数与响应结构 中的模型地址、API Key 和响应基本概念。
如果第 4 天的 GET /test1 还不能返回模型回答,请先修复第 4 天的调用链,再继续本篇。
4.1.2 已有 Spring Boot 项目和 Spring AI 依赖
沿用当前项目的 pom.xml。至少需要已经配置第 4 天使用的 Spring AI OpenAI Starter:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>不要为了本篇重复添加第二份同名依赖。Spring AI 版本由当前项目的 BOM 或版本管理方式统一决定。
本文代码使用当前 Spring AI 结构化输出 API;如果你的项目版本较旧,先以项目实际版本的官方文档为准。
4.1.3 沿用已有模型配置
继续使用第 4 天已经验证过的 application.properties 和 IntelliJ IDEA 运行配置。例如,配置文件中可以保留模型连接信息:
spring.ai.openai.api-key=${DEEPSEEK_API_KEY}
spring.ai.openai.base-url=https://api.deepseek.com
spring.ai.openai.chat.model=deepseek-v4-flash如果你的实际模型名、地址或供应商不同,以当前项目已经验证成功的配置为准,不要机械复制上面的值。
API Key 继续放在 IntelliJ IDEA 的运行配置环境变量中,不写入 Java 源码,也不要提交到 Git。
4.1.4 今天的实践目标
新增一个接口:
POST /test2请求正文:
{
"question": "我的订单什么时候发货?"
}接口内部调用模型完成意图识别,最终返回:
{
"intent": "ORDER_STATUS",
"summary": "用户想查询订单的发货状态",
"needHumanConfirm": false
}4.2 可以拿来干什么
4.2.1 用于意图识别和任务路由
用途:把用户自然语言转换成固定的意图枚举,方便后端决定下一步进入哪个业务分支。
前置:需要已经注入 ChatClient,并定义目标 Java 类型:
public record CustomerIntent(
String intent,
String summary,
boolean needHumanConfirm
) {
}调用代码:
CustomerIntent result = chatClient
.prompt()
.system("""
你是企业售后系统的意图识别助手。
只做意图识别,不查询订单,不修改数据,不创建工单。
intent 只能是 ORDER_STATUS、LOGISTICS、INVENTORY、AFTER_SALE、POLICY、OTHER。
""")
.user("请识别用户问题:我的订单什么时候发货?")
.call()
.entity(CustomerIntent.class);输入是用户问题,处理过程是模型根据系统规则选择意图,输出是 CustomerIntent 对象。
适用场景:售后路由、客服分类、FAQ 分类、后续 Tool Calling 前的任务判断。本篇只完成分类,不执行任何业务工具。
4.2.2 用于从文本中抽取固定字段
用途:从一段自然语言中提取订单号、问题类型和是否需要人工确认等字段。
前置:定义字段结构,字段名要稳定,缺失情况要在 Prompt 中明确说明:
public record AfterSaleRequest(
String orderNo,
String issueType,
String description,
boolean needHumanConfirm
) {
}调用代码:
AfterSaleRequest result = chatClient
.prompt()
.system("""
你是售后信息抽取助手。
只从用户输入中提取已有信息,不要猜测不存在的订单号。
没有订单号时,orderNo 返回空字符串。
""")
.user("用户输入:订单 A20260821001 收到的商品有破损,我想申请售后。")
.call()
.entity(AfterSaleRequest.class);输入是自然语言,处理过程是模型按 Java 类型对应的结构返回字段,输出是 AfterSaleRequest。
适用场景:表单预填、客服信息归一化、接口参数准备。实际创建售后工单时,仍要进行订单存在性、用户归属、权限和幂等校验。
4.2.3 用于让模型结果进入普通 Java 分支
用途:结构化结果可以直接进入 Java 的 switch 或条件判断,而不需要对自然语言做字符串匹配。
前置:已经得到 CustomerIntent 对象:
CustomerIntent result = ...;业务代码可以这样写:
String nextStep = switch (result.intent()) {
case "ORDER_STATUS" -> "准备进入订单查询流程";
case "LOGISTICS" -> "准备进入物流查询流程";
case "INVENTORY" -> "准备进入库存查询流程";
case "AFTER_SALE" -> "准备进入售后流程";
case "POLICY" -> "准备进入制度知识库";
default -> "转为人工或普通问答";
};输入是模型已经转换好的 CustomerIntent,处理过程是 Java 根据枚举值路由,输出是下一步业务动作描述。
适用场景:Agent 工作流的意图路由。但第 6 天只练习“识别并返回结构”,不在本篇实现真实工具调用和多步骤工作流。
4.3 完整实践:用结构化输出识别售后意图
4.3.1 创建请求类型和结果类型
要解决的问题:定义 HTTP 输入和模型输出的两个边界对象。
在 AiController 中使用两个 record:
public record IntentRequest(String question) {
}
public record CustomerIntent(
String intent,
String summary,
boolean needHumanConfirm
) {
}IntentRequest 是前端传给后端的数据,CustomerIntent 是模型输出后由 Spring AI 转换得到的数据。
4.3.2 编写完整 Controller
文件位置:
src/main/java/com/afyke/ai/controller/AiController.java如果当前项目已经存在 AiController,请在原文件中合并 /test2 方法,不要创建第二个同名 Controller。下面是本篇最小可运行版本:
package com.afyke.ai.controller;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AiController {
private final ChatClient chatClient;
public AiController(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
@GetMapping("/test1")
public String test1() {
return chatClient
.prompt("Spring Boot 和 Spring AI 有什么关系?")
.call()
.content();
}
@PostMapping("/test2")
public CustomerIntent test2(@RequestBody IntentRequest request) {
return chatClient
.prompt()
.system("""
你是企业售后系统的意图识别助手。
你的任务是识别用户问题,不要查询订单,不要修改数据,不要创建工单。
intent 只能使用以下值:
ORDER_STATUS、LOGISTICS、INVENTORY、AFTER_SALE、POLICY、OTHER。
判断规则:
- 询问订单状态、发货状态、订单是否完成:ORDER_STATUS
- 询问快递、物流、配送进度:LOGISTICS
- 询问商品库存、是否有货:INVENTORY
- 申请退货、退款、换货或售后:AFTER_SALE
- 询问企业制度、流程或售后规则:POLICY
- 无法归入以上类别:OTHER
summary 使用简短中文说明用户的问题。
只有涉及退款、退货、换货、创建工单等可能改变业务状态的请求时,
needHumanConfirm 才返回 true;普通查询返回 false。
""")
.user(user -> user
.text("请识别下面的用户问题:{question}")
.param("question", request.question()))
.call()
.entity(CustomerIntent.class);
}
public record IntentRequest(String question) {
}
public record CustomerIntent(
String intent,
String summary,
boolean needHumanConfirm
) {
}
}代码中的关键点:
ChatClient.Builder的注入方式沿用第 4 天。.system(...)放稳定的分类规则,沿用第 5 天的 Prompt 设计。.user(...)放本次 HTTP 请求传入的具体问题。.entity(CustomerIntent.class)要求 Spring AI 将模型输出转换为CustomerIntent。needHumanConfirm只是模型返回的判断结果,不是安全权限控制。
4.3.3 编写验证请求
要解决的问题:向后端传入一个真实问题,验证模型结果能否转换成稳定 JSON。
在项目根目录的 request.http 中添加:
#### 4.3.3.1 第 6 天:结构化输出和 JSON Schema
POST http://localhost:8080/test2
Content-Type: application/json
{
"question": "我的订单什么时候发货?"
}再补充一个售后问题,用于观察 needHumanConfirm 的变化:
#### 4.3.3.2 第 6 天:售后意图
POST http://localhost:8080/test2
Content-Type: application/json
{
"question": "商品有破损,我想申请退货退款。"
}4.3.4 启动项目
按照当前项目已有工作流,在 IntelliJ IDEA 中运行 AiApplication。
启动前确认:
DEEPSEEK_API_KEY已配置在运行配置环境变量中。- 第 4 天的模型调用已经验证成功。
8080端口没有被其他程序占用。
如果使用 Maven Wrapper,也可以在项目根目录执行:
./mvnw spring-boot:run4.3.5 预期结果
第一个请求应返回类似:
{
"intent": "ORDER_STATUS",
"summary": "用户想查询订单的发货状态",
"needHumanConfirm": false
}第二个请求应返回类似:
{
"intent": "AFTER_SALE",
"summary": "用户想申请退货退款",
"needHumanConfirm": true
}模型生成的 summary 文字可能不同,但验收重点是:
- HTTP 状态为
200。 - 返回结果是 JSON 对象,而不是 Markdown 或解释性长文本。
- 存在
intent、summary、needHumanConfirm三个字段。 intent使用约定的枚举值。needHumanConfirm是布尔值,不是字符串"true"或"false"。
4.3.6 查看 Java 类型转换结果
如果在 Controller 中临时打印:
CustomerIntent result = ...;
System.out.println(result.intent());
System.out.println(result.summary());
System.out.println(result.needHumanConfirm());就可以看到模型返回的 JSON 已经被 Spring AI 转换为 Java record,后端不需要自己从字符串中查找字段。
完整调用链如下:
POST /test2
→ Spring MVC 读取 IntentRequest
→ ChatClient 组装 system/user 消息
→ Spring AI 根据 CustomerIntent 生成格式要求
→ 模型返回 JSON
→ Spring AI 解析为 CustomerIntent
→ Spring MVC 序列化为 HTTP JSON4.3.7 增强结构校验
如果当前项目使用的 Spring AI 版本支持 validateSchema(),可以将最后一段调用改成:
.call()
.entity(CustomerIntent.class, spec -> spec.validateSchema());它适合对结构正确性要求更高的场景:模型返回缺字段、字段类型错误或不符合 Schema 时,Spring AI 会进行 Schema 校验并尝试自我纠正。
如果当前项目编译时提示 validateSchema() 不存在,说明项目使用的 Spring AI 版本与当前文档 API 不一致。先保留基础写法:
.call()
.entity(CustomerIntent.class);不要为了绕过版本问题而复制不匹配的依赖版本;先检查项目 BOM 和当前版本对应的 Spring AI 官方文档。
4.3.8 常见报错排查
4.3.8.1 401 Unauthorized
原因通常是 API Key 未读取、环境变量名称不一致,或运行配置没有应用到当前启动任务。
检查:
application.properties中是否使用${DEEPSEEK_API_KEY}。- IntelliJ IDEA 运行配置中是否存在同名环境变量。
- 是否误把占位符文本当成真实 Key。
- 是否把 Key 写进了源码但配置仍然读取另一个变量。
4.3.8.2 model not found 或模型不可用
原因通常是模型名与供应商当前提供的名称不一致,或者当前账号没有权限使用该模型。
处理方式:
- 沿用第 4 天已经验证成功的模型名称。
- 以模型供应商当前官方文档为准。
- 不要把示例中的模型名当成永久不变的固定值。
4.3.8.3 JSON 解析失败
常见返回可能是:
Here's the result:
```json
{ ... }
这说明模型在 JSON 外面添加了说明文字或 Markdown 代码围栏。`BeanOutputConverter` 默认要求返回内容可以直接解析为目标 JSON,不能只依赖“模型应该听话”。
处理顺序:
1. 在 `system` 和 `user` 中明确要求“只返回 JSON,不要解释”。
2. 缩小 Schema 和 Prompt,先确保最小字段可以正确返回。
3. 使用当前 Spring AI 支持的 `validateSchema()` 做校验和重试。
4. 如果模型经常输出代码围栏,再考虑自定义 `StructuredOutputConverter`,不要用字符串截取掩盖所有解析问题。
##### 4.3.8.4 字段缺失或类型错误
例如模型返回:
```json
{
"intent": "ORDER_STATUS",
"summary": "查询订单",
"needHumanConfirm": "false"
}
这里 needHumanConfirm 是字符串,不是 JSON 布尔值。应检查:
- Java 字段类型是否写成了
boolean。 - Prompt 是否明确了字段含义和类型。
- 是否开启了 Schema 校验。
- 当前模型是否支持 provider-native structured output。
4.3.8.5 把结构化输出误当成业务安全控制
下面的做法是不安全的:
if (result.needHumanConfirm()) {
// 直接创建售后工单
}结构化输出只能告诉程序模型返回了一个布尔字段,不能证明用户有权限,也不能证明操作经过了人工确认。
第 19 天学习权限校验和人工确认,第 20 天验收 Tool Calling 时,再把这些判断放到 Java 服务和数据库事务中完成。
五、📌 总结
- 快速回顾:普通
.content()返回字符串,结构化输出使用.entity(...)返回 Java 类型。 - 快速回顾:JSON 是数据格式,JSON Schema 是描述和校验 JSON 结构的规则。
- 快速回顾:
type、properties、required和enum是今天最重要的 Schema 关键字。 - 快速回顾:Spring AI 可以根据 Java
record生成 Schema,并把模型 JSON 转换成 Java 对象。 - 快速回顾:默认结构化输出是 best effort;需要更强可靠性时,再考虑
validateSchema()或模型原生结构化输出。 - 快速回顾:结构正确不等于事实正确,结构化输出不替代权限、数据库和业务校验。
- 快速回顾:
entity(...)需要完整响应,不与今天的 SSE 流式输出混用。
记忆句:Java 类型定义结果形状,JSON Schema 描述约束,模型返回 JSON,Spring AI 转成对象,业务代码再做真实校验。
第 6 天验收:
- 能解释 JSON 和 JSON Schema 的区别。
- 能说出
type、properties、required、enum的用途。 - 能使用
.entity(CustomerIntent.class)获得结构化 Java 对象。 - 能通过
POST /test2返回固定字段的 JSON。 - 能区分结构校验、事实校验和权限校验。
相关笔记:0-学习路线、2.大模型 API、请求参数与响应结构、3.Spring AI ChatClient、4.Prompt、System Prompt、Prompt 模板