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)的指令,避免提示词冲突,只关注业务内容即可。
相关推荐
CareyWYR5 分钟前
每周AI论文速递(260316-260320)
人工智能
Bonnie3737 分钟前
云边端一体化解析-什么是云边端,为何能成为AI基础设施核心
人工智能·程序人生·云原生·个人开发
李小狼lee17 分钟前
openclaw小龙虾的安装
人工智能
huaweichenai17 分钟前
java的时间操作介绍
java·开发语言
AMZ-Lu18 分钟前
正本清源:亚马逊战场上的“原创者红利”与心智产权
大数据·人工智能·媒体·亚马逊
集芯微电科技有限公司21 分钟前
AD536A高性能真有效值直流转换电路替代PC2909
人工智能·单片机·嵌入式硬件·神经网络·生成对抗网络
2501_9269783323 分钟前
物理学原理和人工智能领域的底层一致性
人工智能·经验分享·笔记·ai写作
谁在黄金彼岸25 分钟前
阿里云VIS + Qwen-Vision自定义抠图系统实现指南
人工智能
毕设源码-朱学姐33 分钟前
【开题答辩全过程】以 基于SpringBoot+Vue的百货商品进出货平台为例,包含答辩的问题和答案
java·spring boot·后端
NOCSAH34 分钟前
统好AI数智一体化平台:原生一体架构筑牢数智基底
大数据·人工智能·统好ai·数智一体化平台