最新快照版本请使用Spring AI 1.1.0spring-doc.cadn.net.cn

结构化输出转换器

截至2024年5月2日输出解析器,BeanOutputParser,ListOutputParserMapOutput解析器类别被弃用,取而代之的是新的结构化输出转换器,豆输出转换器,列表输出转换器MapOutput转换器实现。 后者是前者的直接替换,功能相同。更改的主要原因是命名,因为没有进行任何解析,但也与春季相符org.springframework.core.convert.converter软件包带来了一些改进的功能。

LLMs产生结构化输出的能力对于依赖可靠解析输出值的下游应用非常重要。 开发者希望快速将AI模型的结果转化为数据类型,如JSON、XML或Java类,这些类可以传递给其他应用函数和方法。spring-doc.cadn.net.cn

春季人工智能结构化输出转换器帮助将LLM输出转换为结构化格式。 如下图所示,该方法围绕LLM文本补全端点工作:spring-doc.cadn.net.cn

结构化输出转换器架构

使用通用补全API从大型语言模型(LLMs)生成结构化输出需要谨慎处理输入和输出。结构化输出转换器在LLM调用前后都起着关键作用,确保实现所需的输出结构。spring-doc.cadn.net.cn

在调用LLM之前,转换器会在提示符上附加格式指令,为模型生成所需输出结构提供明确指导。这些指令作为蓝图,塑造模型响应以符合指定格式。spring-doc.cadn.net.cn

调用LLM后,转换器将模型的输出文本转换为结构化类型的实例。该转换过程包括解析原始文本输出并将其映射到相应的结构化数据表示,如JSON、XML或域特定数据结构。spring-doc.cadn.net.cn

结构化输出转换器是将模型输出转换为结构化输出的最佳方法。 AI模型不保证能按要求返回结构化输出。 模型可能无法理解提示,或无法按要求生成结构化输出。 考虑实施验证机制,确保模型输出符合预期。
结构化输出转换器不用于LLM工具调用,因为该功能默认提供结构化输出。

结构化输出 API

结构化输出转换器接口允许你获得结构化输出,比如将输出映射到 Java 类或文本 AI 模型输出中的数组值。 接口定义如下:spring-doc.cadn.net.cn

public interface StructuredOutputConverter<T> extends Converter<String, T>, FormatProvider {

}

它结合了Spring转换器<弦、T>接口和FormatProvider接口spring-doc.cadn.net.cn

public interface FormatProvider {
	String getFormat();
}

下图展示了使用结构化输出API时的数据流。spring-doc.cadn.net.cn

结构化输出 API

FormatProvider为AI模型提供具体的格式化指导,使其能够生成可转换为指定目标类型的文本输出T使用转炉.以下是此类格式化指令的一个示例:spring-doc.cadn.net.cn

  Your response should be in JSON format.
  The data structure for the JSON should match this Java class: java.util.HashMap
  Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation.

格式说明通常通过 PromptTemplate 附加在用户输入末尾,如下所示:spring-doc.cadn.net.cn

    StructuredOutputConverter outputConverter = ...
    String userInputTemplate = """
        ... user text input ....
        {format}
        """; // user input with a "format" placeholder.
    Prompt prompt = new Prompt(
            PromptTemplate.builder()
						.template(this.userInputTemplate)
						.variables(Map.of(..., "format", this.outputConverter.getFormat())) // replace the "format" placeholder with the converter's format.
						.build().createMessage()
    );

Converter<String,T>负责将模型输出文本转换为指定类型的实例T.spring-doc.cadn.net.cn

可用转换器

目前,Spring AI 提供摘要转换服务输出转换器,摘要消息输出转换器,豆输出转换器,MapOutput转换器列表输出转换器实现:spring-doc.cadn.net.cn

结构化输出类层级
  • 摘要转换服务输出转换器<T>- 提供预配置的通用转换服务,用于将LLM输出转换为所需格式。没有默认FormatProvider提供实现。spring-doc.cadn.net.cn

  • 摘要消息输出转换器转<T>- 提供预配置的消息转换器,用于将LLM输出转换为所需格式。没有默认FormatProvider提供实现。spring-doc.cadn.net.cn

  • 豆输出转换器<T>- 配置为指定的 Java 类(例如 Bean)或参数化类型引用,该转换器使用FormatProvider该实现指示AI模型生成符合DRAFT_2020_12,JSON 模式由指定的 Java 类派生。随后,它利用对象映射器将 JSON 输出反序列化为目标类的 Java 对象实例。spring-doc.cadn.net.cn

  • MapOutput转换器- 扩展了 的功能摘要消息输出转换器其中FormatProvider该实现引导 AI 模型生成符合 RFC8259 的 JSON 响应。此外,它还包含了利用消息转换器将 JSON 有效载荷转换为java.util.Map<String, Object>实例。spring-doc.cadn.net.cn

  • 列表输出转换器- 扩展摘要转换服务输出转换器并且包括一个FormatProvider实现时针对逗号分隔列表输出。转换器实现采用了提供的转换服务将模型文本输出转换为java.util.List.spring-doc.cadn.net.cn

使用转换器

以下章节将提供如何使用现有转换器生成结构化输出的指南。spring-doc.cadn.net.cn

豆输出转换器

以下示例展示了如何使用豆输出转换器为演员制作电影作品集。spring-doc.cadn.net.cn

代表演员作品列表的目标纪录:spring-doc.cadn.net.cn

record ActorsFilms(String actor, List<String> movies) {
}

以下是如何使用高阶流流式应用 BeanOutputConverter 的方法聊天客户端应用程序接口:spring-doc.cadn.net.cn

ActorsFilms actorsFilms = ChatClient.create(chatModel).prompt()
        .user(u -> u.text("Generate the filmography of 5 movies for {actor}.")
                    .param("actor", "Tom Hanks"))
        .call()
        .entity(ActorsFilms.class);

或者使用低层次聊天模型API 直接:spring-doc.cadn.net.cn

BeanOutputConverter<ActorsFilms> beanOutputConverter =
    new BeanOutputConverter<>(ActorsFilms.class);

String format = this.beanOutputConverter.getFormat();

String actor = "Tom Hanks";

String template = """
        Generate the filmography of 5 movies for {actor}.
        {format}
        """;

Generation generation = chatModel.call(
    PromptTemplate.builder().template(this.template).variables(Map.of("actor", this.actor, "format", this.format)).build().create()).getResult();

ActorsFilms actorsFilms = this.beanOutputConverter.convert(this.generation.getOutput().getText());

生成模式中的属性排序

豆输出转换器支持通过@JsonPropertyOrder注解。 该注释允许你指定属性在模式中应出现的精确顺序,无论它们在类或记录中的声明顺序如何。spring-doc.cadn.net.cn

例如,为了确保在演员电影记录:spring-doc.cadn.net.cn

@JsonPropertyOrder({"actor", "movies"})
record ActorsFilms(String actor, List<String> movies) {}

该注释适用于记录类和普通 Java 类。spring-doc.cadn.net.cn

通用Beans型

使用该参数化类型引用构造器以指定更复杂的目标类结构。 例如,表示演员及其电影作品列表:spring-doc.cadn.net.cn

List<ActorsFilms> actorsFilms = ChatClient.create(chatModel).prompt()
        .user("Generate the filmography of 5 movies for Tom Hanks and Bill Murray.")
        .call()
        .entity(new ParameterizedTypeReference<List<ActorsFilms>>() {});

或者使用低层次聊天模型API 直接:spring-doc.cadn.net.cn

BeanOutputConverter<List<ActorsFilms>> outputConverter = new BeanOutputConverter<>(
        new ParameterizedTypeReference<List<ActorsFilms>>() { });

String format = this.outputConverter.getFormat();
String template = """
        Generate the filmography of 5 movies for Tom Hanks and Bill Murray.
        {format}
        """;

Prompt prompt = PromptTemplate.builder().template(this.template).variables(Map.of("format", this.format)).build().create();

Generation generation = chatModel.call(this.prompt).getResult();

List<ActorsFilms> actorsFilms = this.outputConverter.convert(this.generation.getOutput().getText());

地图输出转换器

以下摘录展示了如何使用MapOutput转换器将模型输出转换为地图中的数字列表。spring-doc.cadn.net.cn

Map<String, Object> result = ChatClient.create(chatModel).prompt()
        .user(u -> u.text("Provide me a List of {subject}")
                    .param("subject", "an array of numbers from 1 to 9 under they key name 'numbers'"))
        .call()
        .entity(new ParameterizedTypeReference<Map<String, Object>>() {});

或者使用低层次聊天模型API 直接:spring-doc.cadn.net.cn

MapOutputConverter mapOutputConverter = new MapOutputConverter();

String format = this.mapOutputConverter.getFormat();
String template = """
        Provide me a List of {subject}
        {format}
        """;

Prompt prompt = PromptTemplate.builder().template(this.template)
.variables(Map.of("subject", "an array of numbers from 1 to 9 under they key name 'numbers'", "format", this.format)).build().create();

Generation generation = chatModel.call(this.prompt).getResult();

Map<String, Object> result = this.mapOutputConverter.convert(this.generation.getOutput().getText());

列表输出转换器

以下摘录展示了如何使用列表输出转换器将模型输出转换为冰淇淋口味列表。spring-doc.cadn.net.cn

List<String> flavors = ChatClient.create(chatModel).prompt()
                .user(u -> u.text("List five {subject}")
                            .param("subject", "ice cream flavors"))
                .call()
                .entity(new ListOutputConverter(new DefaultConversionService()));

或者使用低层次ChatModel API径直:spring-doc.cadn.net.cn

ListOutputConverter listOutputConverter = new ListOutputConverter(new DefaultConversionService());

String format = this.listOutputConverter.getFormat();
String template = """
        List five {subject}
        {format}
        """;

Prompt prompt = PromptTemplate.builder().template(this.template).variables(Map.of("subject", "ice cream flavors", "format", this.format)).build().create();

Generation generation = this.chatModel.call(this.prompt).getResult();

List<String> list = this.listOutputConverter.convert(this.generation.getOutput().getText());

内置 JSON 模式

一些AI模型提供专门的配置选项,用于生成结构化(通常是JSON)输出。spring-doc.cadn.net.cn

  • OpenAI 结构化输出可以确保你的模型生成的响应严格符合你提供的 JSON 模式。你可以在JSON_OBJECT保证模型生成的消息是有效的 JSON 或JSON_SCHEMA如果提供一个保证模型生成与你提供模式相符的响应(spring.ai.openai.chat.options.response格式选项)。spring-doc.cadn.net.cn

  • Azure OpenAI - 提供spring.ai.azure.openai.chat.options.responseFormat选项指定模型必须输出的格式。设定为{ “类型”:“json_object” }启用 JSON 模式,保证模型生成的消息是有效的 JSON。spring-doc.cadn.net.cn

  • Ollama - 提供spring.ai.ollama.chat.options.format选择指定返回响应格式的选项。目前,唯一被接受的值为JSON.spring-doc.cadn.net.cn

  • Mistral AI - 提供spring.ai.mistralai.chat.options.response格式选择指定返回响应格式的选项。设置为{ “类型”:“json_object” }启用 JSON 模式,保证模型生成的消息是有效的 JSON。spring-doc.cadn.net.cn