Spring AI 拥抱 OpenAI 的结构化输出:增强 JSON 响应的可靠性

工程 | Christian Tzolov | 2024年8月9日 | ...

OpenAI 最近推出了一项强大的功能,称为结构化输出(Structured Outputs),它确保了 AI 生成的响应严格遵循预定义的 JSON Schema。此功能显著提高了 AI 生成内容在实际应用中的可靠性和可用性。今天,我们很高兴地宣布 Spring AI (1.0.0-SNAPSHOT) 已完全集成支持 OpenAI 的结构化输出,以无缝、Spring Native 的方式将此能力带给 Java 开发者。

下图展示了新的结构化输出功能如何扩展OpenAI Chat API

Restored Spring AI (2)

注意: Spring AI 已经提供了强大的、模型无关的结构化输出工具,可与包括 OpenAI 在内的各种 AI 模型一起使用。OpenAI 结构化输出功能提供了一个额外的、一致的、但模型特定的解决方案,目前仅适用于 gpt-4ogpt-4o-mini 及后续模型。

OpenAI 的 Structured Outputs 功能保证 AI 模型生成的响应符合提供的JSON Schema。这解决了 AI 驱动应用中的几个常见挑战:类型安全:不再担心缺少必需的键或无效的枚举值;显式拒绝:基于安全的模型拒绝变得可以通过程序检测;简化提示:无需使用过于具体的提示即可实现一致的格式化。

Spring AI 允许开发者以最少的配置利用此功能。让我们探讨如何在 Spring 应用中使用它。

程序化配置

您可以使用 OpenAiChatOptions 构建器以程序化方式设置响应格式,如下所示

String jsonSchema = """
  {
      "type": "object",
      "properties": {
          "steps": {
              "type": "array",
              "items": {
                  "type": "object",
                  "properties": {
                      "explanation": { "type": "string" },
                      "output": { "type": "string" }
                  },
                  "required": ["explanation", "output"],
                  "additionalProperties": false
              }
          },
          "final_answer": { "type": "string" }
      },
      "required": ["steps", "final_answer"],
      "additionalProperties": false
  }
  """;

Prompt prompt = new Prompt("how can I solve 8x + 7 = -23",
  OpenAiChatOptions.builder()
      .withModel(ChatModel.GPT_4_O_MINI)
      .withResponseFormat(new ResponseFormat(ResponseFormat.Type.JSON_SCHEMA, jsonSchema))
      .build());

ChatResponse response = this.openAiChatModel.call(prompt);

注意:您必须遵循 OpenAI JSON Schema 的子集语言格式。

使用 BeanOutputConverter

Spring AI 提供了一个方便的 BeanOutputConverter 工具,可以自动从您的领域对象生成 JSON Schema,并将结构化响应转换为 Java 实例

record MathReasoning(
  @JsonProperty(required = true, value = "steps") Steps steps,
  @JsonProperty(required = true, value = "final_answer") String finalAnswer) {

  record Steps(
    @JsonProperty(required = true, value = "items") Items[] items) {

    record Items(
      @JsonProperty(required = true, value = "explanation") String explanation,
      @JsonProperty(required = true, value = "output") String output) {}
  }
}

var outputConverter = new BeanOutputConverter<>(MathReasoning.class);

var jsonSchema = outputConverter.getJsonSchema();

Prompt prompt = new Prompt("how can I solve 8x + 7 = -23",
  OpenAiChatOptions.builder()
      .withModel(ChatModel.GPT_4_O_MINI)
      .withResponseFormat(new ResponseFormat(ResponseFormat.Type.JSON_SCHEMA, jsonSchema))
      .build());

ChatResponse response = this.openAiChatModel.call(prompt);
String content = response.getResult().getOutput().getContent();

MathReasoning mathReasoning = outputConverter.convert(content);

注意:请确保使用 @JsonProperty(required = true,…​) 注解。这对于生成准确标记字段为必需的 Schema 至关重要。OpenAI 强制要求它才能使结构化响应正常工作。

通过 Application Properties 配置

或者,在使用OpenAI 自动配置时,您可以通过以下聊天应用属性来配置所需的响应格式

spring.ai.openai.api-key=YOUR_API_KEY
spring.ai.openai.chat.options.model=gpt-4o-mini

spring.ai.openai.chat.options.response-format.type=JSON_SCHEMA
spring.ai.openai.chat.options.response-format.name=MySchemaName
spring.ai.openai.chat.options.response-format.schema={"type":"object","properties":{"steps":{"type":"array","items":{"type":"object","properties":{"explanation":{"type":"string"},"output":{"type":"string"}},"required":["explanation","output"],"additionalProperties":false}},"final_answer":{"type":"string"}},"required":["steps","final_answer"],"additionalProperties":false}
spring.ai.openai.chat.options.response-format.strict=true

拒绝响应

使用结构化输出时,出于安全原因,OpenAI 模型有时可能会拒绝满足请求。由于拒绝响应不一定遵循您在 response_format 中提供的 Schema,因此 API 响应包含一个名为 refusal 的新字段,以指示模型拒绝满足请求。

Spring AI 将此 refusal 字段映射到 AssistantMessage 的元数据(metadata)中。通过 refusal 键进行搜索。

未来工作

我们正在探索将新的 OpenAI 特定结构化输出功能集成到 Spring AI 模型无关的结构化输出工具集中的可能性。

参考资料

如需更多信息,请查阅 Spring AI 和 OpenAI 的参考文档。

结论

Spring AI 对 OpenAI 结构化输出功能的支持使得 AI 驱动的应用更加可靠且易于开发。通过确保类型安全和一致的结构化格式,开发者可以专注于构建创新功能,而不是费力处理不可预测的 AI 输出。

我们可以强调 Spring 开发者的以下益处

  • 无缝集成:无需离开 Spring 生态系统即可利用结构化输出。
  • 类型安全:使用强类型 Java 对象,减少运行时错误。
  • 灵活性:在程序化配置和基于属性的配置之间进行选择。
  • 领域驱动设计:使用您的领域对象定义预期的 AI 输出结构。

请探索这一新能力并分享您的经验。一如既往,我们欢迎反馈和贡献,以帮助改进 Spring AI,使其更加强大和用户友好。

敬请关注更多更新,我们将继续增强 Spring AI 与尖端 AI 技术的集成!

获取 Spring 新闻通讯

订阅 Spring 新闻通讯以保持联系

订阅

领先一步

VMware 提供培训和认证,助力您快速进步。

了解更多

获取支持

Tanzu Spring 通过一个简单的订阅提供对 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举办的活动

查看 Spring 社区所有即将举办的活动。

查看全部