侧边栏壁纸
博主头像
AI中文站

开拓MCP洪荒时代

  • 累计撰写 28 篇文章
  • 累计创建 3 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

SpringAI-结构化输出转换器

Llm产生结构化输出的能力对于依赖于可靠地解析输出值的下游应用是重要的。 开发人员希望快速将AI模型的结果转换为可以传递给其他应用程序函数和方法的数据类型,例如JSON,XML或Java类。

SpringAIStructured Output Converters帮助将LLM输出转换为结构化格式。 如下图所示,此方法围绕LLM文本完成端点运行:

使用通用完成api从大型语言模型 (llm) 生成结构化输出需要仔细处理输入和输出。结构化输出转换器在LLM调用前后起着至关重要的作用,可确保实现所需的输出结构。

在LLM调用之前,转换器将格式说明附加到提示,为模型提供生成所需输出结构的明确指导。这些指令充当蓝图,塑造模型的响应以符合指定的格式。

在LLM调用之后,转换器获取模型的输出文本并将其转换为结构化类型的实例。此转换过程涉及解析原始文本输出并将其映射到相应的结构化数据表示形式,例如JSON,XML或特定于域的数据结构。

StructuredOutputConverter是将模型输出转换为结构化输出的最大努力。 AI模型不能保证按要求返回结构化输出。 模型可能无法理解提示或无法按要求生成结构化输出。 考虑实施验证机制,以确保模型输出符合预期。

StructuredOutputConverter不用于LLM工具调用,因为默认情况下此功能固有地提供结构化输出。

结构化输出API

StructuredOutputConverter接口允许您获取结构化输出,例如从基于文本的AI模型输出将输出映射到Java类或值数组。 接口定义为:

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

}

它结合了春天转换器 <String,T>接口和FormatProvider接口

public interface FormatProvider {
	String getFormat();
}

下图显示了使用结构化输出API时的数据流。

FormatProvider为AI模型提供特定的格式指南,使其能够生成可转换为指定目标类型的文本输出T使用Converter。以下是此类格式化说明的示例:

您的回复应该是JSON格式。
  JSON的数据结构应该与这个Java类匹配: java.util.HashMap
  不包括任何解释,只提供遵循此格式的RFC8259兼容JSON响应,没有偏差。

格式说明通常使用PromptTemplate像这样:

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

转换器 <String,T> 负责将模型中的输出文本转换为指定类型的实例T


可用的转换器

目前,Spring AI提供AbstractConversionServiceOutputConverter,AbstractMessageOutputConverter,BeanOutputConverter,MapOutputConverterListOutputConverter实现:

  • AbstractConversionServiceOutputConverter<T>-提供预先配置的GenericConversionService用于将LLM输出转换为所需格式。无默认值FormatProvider提供了实现。

  • AbstractMessageOutputConverter<T>-提供一个预先配置的MessageConverter用于将LLM输出转换为所需的格式。无默认值FormatProvider提供了实现。

  • BeanOutputConverter<T>-配置一个指定的Java类 (例如,Bean) 或参数化类比,此转换器采用FormatProvider实现,指导AI模型生成符合DRAFT_2020_12,JSON Schema从指定的Java类派生。随后,它利用一个ObjectMapper将JSON输出反序列化为目标类的Java对象实例。

  • MapOutputConverter-扩展的功能AbstractMessageOutputConverter与一个FormatProvider指导AI模型生成符合RFC8259的JSON响应的实现。此外,它还包含一个转换器实现,利用提供的MessageConverter要将JSON负载转换为java.util.Map<String, Object>实例。

  • ListOutputConverter-扩展了 AbstractConversionServiceOutputConverter并包括一个FormatProvider为逗号分隔的列表输出量身定制的实现。转换器实现采用提供的ConversionService将模型文本输出转换为java.util.List

使用转换器

以下各节提供了如何使用可用转换器生成结构化输出的指南。


Bean输出转换器

下面的示例演示如何使用BeanOutputConverter为演员生成电影作品。

代表演员电影作品的目标记录:

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

下面是如何应用BeanOutputConverter使用高级,流畅ChatClientAPI:

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);

复制!

或使用低级别的ChatModel直接API:

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(
    new PromptTemplate(this.template, Map.of("actor", this.actor, "format", this.format)).create()).getResult();

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

生成的架构中的属性排序

BeanOutputConverter支持通过生成的JSON架构中的自定义属性排序@JsonPropertyOrder注释。 此注释允许您指定属性在架构中出现的确切顺序,而不管它们在类或记录中的声明顺序如何。

例如,要确保中的属性的特定顺序ActorsFilms记录:

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

复制!

此注释适用于记录和常规Java类。

通用Bean类型

使用ParameterizedTypeReference构造函数来指定更复杂的目标类结构。 例如,要表示演员及其影片的列表:

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>>() {});

复制!

或使用低级别的ChatModel直接API:

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 = new PromptTemplate(this.template, Map.of("format", this.format)).create();

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

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

Map输出转换器

以下代码段显示了如何使用MapOutputConverter将模型输出转换为映射中的数字列表。

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>>() {});

或使用低级别的ChatModel直接API:

MapOutputConverter mapOutputConverter = new MapOutputConverter();

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

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

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

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

列表输出转换器

以下代码段显示了如何使用ListOutputConverter将模型输出转换为冰淇淋口味列表。

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直接:

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

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

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

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

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


支持的AI模型

以下AI模型已经过测试,支持List、Map和Bean结构化输出。

内置JSON模式

一些AI模型提供专用配置选项来生成结构化 (通常为JSON) 输出。

  • OpenAI结构化输出可以确保您的模型生成严格符合您提供的JSON模式的响应。您可以选择JSON_OBJECT保证模型生成的消息是有效的JSON或JSON_SCHEMA使用提供的架构,保证模型将生成与您提供的架构匹配的响应 (spring.ai.openai.chat.options.responseFormat选项)。

  • Azure OpenAI-提供了一个spring.ai.azure.openai.chat.options.responseFormat指定模型必须输出的格式的选项。设置为{ "type": "json_object" }启用JSON模式,保证模型生成的消息是有效的JSON。

  • Ollama-提供了一个spring.ai.ollama.chat.options.format选项来指定要在其中返回响应的格式。目前,唯一接受的值是json

  • Mistral AI-提供了一个spring.ai.mistralai.chat.options.responseFormat选项来指定要在其中返回响应的格式。将其设置为{ "type": "json_object" }启用JSON模式,保证模型生成的消息是有效的JSON。

0

评论区