Spring AI Structured-Output源码分析

Spring AI Structured-Output源码分析

  • 在 Spring AI 中,StructuredOutputConverter(常用的实现类是 BeanOutputConverter)的核心作用是将大模型的非结构化文本输出 转换为 Java 的结构化对象(POJO)
  • StructuredOutputConverter extends Converter<String, T>, FormatProvider
    • FormatProvider:负责将你 Java Bean 的 JSON Schema
    • Converter:负责将模型返回的字符串 通过 Jackson 反序列化转换为你的Java Bean
  • 其实结构化对象本质实现原理也是基于:JSON 解析器 + Prompt 工程 + 结果解析 机制

实现思考&源码分析

如何告知大模型需要转换格式?

  • 原理

StructuredOutputConverter 接口有一个方法 getFormat()。当你调用这个方法时,它会生成一段自然语言的指令 ,这段指令中包含了你 Java Bean 的 JSON Schema。你需要手动或自动将这段指令拼接到发给 AI 的 Prompt 中。

  • 源码
    • 将你 Java Bean 的格式为 JSON Schema,并放到请求上下文中
java 复制代码
@GetMapping("/chat-format")
public BeanEntity simpleChatFormat(@RequestParam(value = "query", defaultValue = "写诗歌") String query) {
  return chatClient.prompt(query).call()
    .format(converter.getFormat()) // 显式注入格式指令
    .entity(BeanEntity.class) // 这里内部会自动调用 format()
    ;
}

//org.springframework.ai.chat.client.DefaultChatClient.DefaultCallResponseSpec#entity(java.lang.Class<T>)
public <T> T entity(Class<T> type) {
  var outputConverter = new BeanOutputConverter<>(type);
  return doSingleWithBeanOutputConverter(outputConverter);
}

@Nullable
private <T> T doSingleWithBeanOutputConverter(StructuredOutputConverter<T> outputConverter) {
  //1. 根据泛型 T 的类型,生成标准的 JSON Schema:详见BeanOutputConverter.getFormat()
  //2. 将生成的生成标准的 JSON Schema放入到上下文中,key为:"spring.ai.chat.client.output.format"
  var chatResponse = doGetObservableChatClientResponse(this.request, outputConverter.getFormat())
    .chatResponse();
  var stringResponse = getContentFromChatResponse(chatResponse);
  //3.大模型返回的字符串反序列化为JavaBean,详见:BeanOutputConverter.convert()
  return outputConverter.convert(stringResponse);
}
  • JSON Schema添加到Prompt提示词中,在Advisor链中最后一个ChatModelCallAdvisor实现
java 复制代码
@Override
public ChatClientResponse adviseCall(ChatClientRequest chatClientRequest, CallAdvisorChain callAdvisorChain) {
  //1.增强格式指令,即提示词增强
  ChatClientRequest formattedChatClientRequest = augmentWithFormatInstructions(chatClientRequest);
  ChatResponse chatResponse = this.chatModel.call(formattedChatClientRequest.prompt());
  return ChatClientResponse.builder()
    .chatResponse(chatResponse)
    .context(Map.copyOf(formattedChatClientRequest.context()))
    .build();
}

private static ChatClientRequest augmentWithFormatInstructions(ChatClientRequest chatClientRequest) {
  //2.从请求上下文获取JSON Schema格式指令
  String outputFormat = (String) chatClientRequest.context().get(ChatClientAttributes.OUTPUT_FORMAT.getKey());
	//3.其实逻辑很简单:用户文本 + 换行 + JSON Schema格式指令
  Prompt augmentedPrompt = chatClientRequest.prompt()
    .augmentUserMessage(userMessage -> userMessage.mutate()
                        .text(userMessage.getText() + System.lineSeparator() + outputFormat)
                        .build());
  return ChatClientRequest.builder()
    .prompt(augmentedPrompt)
    .context(Map.copyOf(chatClientRequest.context()))
    .build();
}

大模型返回结果后是如何转换为对应的实体?

  • 原理

转换发生在应用层(你的服务内部),而不是模型层。模型返回的仍然是 String(一段 JSON 文本),Spring AI 在接收到这段文本后,调用 convert() 方法将其反序列化,详见:BeanOutputConverter.convert()。

  • 源码
java 复制代码
public T convert(@NonNull String text) {
  try {
    // 1. 预处理:清洗文本
    // 大模型经常喜欢返回 ```json { ... } ```这种 Markdown 格式
    // 这里会去除首尾的 Markdown 标记,只保留纯 JSON 字符串
    text = this.textCleaner.clean(text);

    // 2. 反序列化
    // 使用 Jackson 的 ObjectMapper 将 JSON 字符串转为 Java 对象
    return (T) this.objectMapper.readValue(text, this.objectMapper.constructType(this.type));
  }
  catch (JsonProcessingException e) {
    throw new RuntimeException(e);
  }
}

注意事项

  • 如果你使用了 StructuredOutputConverter(或者 .entity() 方法),请不要在你的 User Prompt 中再手写任何关于格式(Format)的指令,避免提示词冲突,只关注业务内容即可。
相关推荐
黎雁·泠崖14 分钟前
【魔法森林冒险】2/14 抽象层设计:Figure/Person类(所有角色的基石)
java·开发语言
uesowys15 分钟前
Apache Spark算法开发指导-Factorization machines classifier
人工智能·算法
人工智能AI技术24 分钟前
预训练+微调:大模型的“九年义务教育+专项补课”
人工智能
aircrushin31 分钟前
中国多模态大模型历史性突破:智源Emu3自回归统一范式技术深度解读
人工智能
Lsx_39 分钟前
前端视角下认识 AI Agent 和 LangChain
前端·人工智能·agent
aiguangyuan40 分钟前
使用LSTM进行情感分类:原理与实现剖析
人工智能·python·nlp
Yeats_Liao1 小时前
评估体系构建:基于自动化指标与人工打分的双重验证
运维·人工智能·深度学习·算法·机器学习·自动化
怒放吧德德1 小时前
后端 Mock 实战:Spring Boot 3 实现入站 & 出站接口模拟
java·后端·设计
深圳市恒星物联科技有限公司1 小时前
水质流量监测仪:复合指标监测的管网智能感知设备
大数据·网络·人工智能
biyezuopinvip1 小时前
基于Spring Boot的企业网盘的设计与实现(任务书)
java·spring boot·后端·vue·ssm·任务书·企业网盘的设计与实现