chat - 模型的结构化输出
2026年8月20日 下午11:44:50
结构化输出(Structured Output),是指让大模型按给定的数据结构(JSON Schema)返回结果,再反序列化为 Java 对象。适合信息提取、数据入库、结果校验等场景。
Solon AI 的结构化输出有三个特点:
- 类型即契约:直接用一个 Java Bean 声明输出结构,框架自动生成 JSON Schema
- 接口标准无关:Schema 以指令方式注入提示语,不依赖模型的原生 json mode,任何模型都能用
- 容错提取:响应消息自带容错的 JSON 提取与
toBean一步转换
1、定义输出的 Java Bean
用普通的 Java 类 + @Param 注解即可(@Param 的描述、必填、默认值会并入生成的 Schema 字段):
public class ResumeInfo {
@Param(description = "姓名", required = true)
private String name;
@Param(description = "年龄")
private Integer age;
@Param(description = "邮箱")
private String email;
@Param(description = "技能列表", defaultValue = "[]")
private List<String> capabilities;
// get set ...
}
2、三层 API:在哪里声明 outputSchema
结构化输出的 schema 可以在三个层面声明,作用范围从大到小:
- 模型级:构建 ChatModel 时指定,对该模型的所有请求生效
ChatModel chatModel = ChatModel.of("https://api.openai.com/v1/chat/completions")
.apiKey(apiKey)
.model("gpt-4o")
.outputSchema(ResumeInfo.class) //模型级
.build();
- 请求级:在某次请求的选项里指定,只影响本次请求(两种写法均可,Consumer 形式更简洁)
AssistantMessage message = chatModel
.prompt("请从下面的简历文本中提取关键信息:..." + resumeText)
.options(o -> o.outputSchema(ResumeInfo.class)) //请求级
.call()
.getMessage();
- 智能体级:构建 Agent 时指定(需引入
solon-ai-agent依赖)
ReActAgent resumeAgent = ReActAgent.of(chatModel)
.name("ResumeExtractor")
.instruction("请从用户提供的文本中提取关键信息")
.outputSchema(ResumeInfo.class) //智能体级
.outputKey("extracted_resume") //结果同时写入会话上下文
.build();
如果只有 schema 字符串(比如来自外部配置),也可以直接用 outputSchema(String) 重载。
3、结果提取与反序列化
响应消息 AssistantMessage 提供了三个层次的取值能力:
AssistantMessage message = chatModel.prompt("...").call().getMessage();
//a) 原始内容(含思维链时也会包含)
String rawContent = message.getContent();
//b) 容错提取的 JSON 片段(自动剥离 markdown 围栏与前后缀文本)
String json = message.getJsonContent();
//c) 一步转为 Java Bean
ResumeInfo info = message.toBean(ResumeInfo.class);
其中 getJsonContent() 会定位首个 {(或 [)与末个 }(或 ])之间的内容,模型偶尔加上 ```json 围栏或说明文字也不会失败。
4、传输机制:为什么不依赖模型的 json mode
Solon AI 在组装请求时,如果发现选项里有 outputSchema,会把它包装成指令片段追加到提示语里:
<output_schema>
{...生成的 JSON Schema...}
</output_schema>
这个动作由 ChatDialect.prepareOutputSchemaInstruction(...) 完成,属于接口标准(方言)层的能力。因此:
- 不需要模型支持原生的
response_format: json_schema,Ollama、OpenAI、DashScope、Gemini、Anthropic 等都能用 - 有特殊要求的模型,可通过定制方言覆写该行为
另外,String、数字、布尔、枚举、日期等简单类型会被自动忽略 schema 生成(它们不需要结构约束)。
5、智能体的结构化输出与下游联动
智能体场景下,outputKey 会把提取结果写入会话上下文,供工作流的下游节点消费:
AgentSession session = InMemoryAgentSession.of("demo");
AssistantMessage message = resumeAgent
.prompt(Prompt.of(resumeText))
.session(session)
.call()
.getMessage();
//从会话上下文取结构化结果
String extracted = (String) session.getContext().get("extracted_resume");
6、生产化建议
- 用
temperature(0.1)抑制格式漂移;解析失败可配合重试使用(Agent 有retryConfig(maxRetries, retryDelayMs)) - schema 只能约束"形状",管不住"算术"——求和、统计之类的计算应放到 Java 里做
- 需要强校验的入库场景,建议在
toBean之后再走一遍业务校验