Spring AI 结构化输出转换器 将 LLM 输出转换为结构化格式。

使用通用完成 API 从大型语言模型 (LLM) 生成结构化输出需要仔细处理输入和输出。结构化输出转换器在 LLM 调用之前和之后都起着关键作用,确保实现所需的输出结构。 在 LLM 调用之前,转换器将格式指令附加到提示中,为模型提供生成所需输出结构的明确指导。这些指令充当蓝图,塑造模型的响应以符合指定的格式。
可用转换器
目前,Spring AI 提供了 AbstractConversionServiceOutputConverter、AbstractMessageOutputConverter、BeanOutputConverter、MapOutputConverter 和 ListOutputConverter 实现
其中BeanOutputConverter<T>、MapOutputConverter 和 ListOutputConverter配置了默认的 FormatProvider 实现
转换器的两种种使用方式
以BeanOutputConverter<T>为例子演示
表示演员电影作品的目标记录
arduino
record ActorsFilms(String actor, List<String> movies) {
}
以下是使用ChatClient API 应用 BeanOutputConverter 的方法
scss
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
ini
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());
对比使用结构化输出对返回内容的影响(使用chatclientapi)
BeanOutputConverter<T>
调用代码:
scss
record ActorsFilms(String actor, List<String> movies) {
}
String structuredPrompt = "Generate the 5 movies that {actor} has performed in. ";
ActorsFilms actorsFilms = ChatClient.create(dashscopeChatModel).prompt()
.user(u -> u.text(structuredPrompt)
.param("actor", "Robert Downey Jr."))
.call()
.entity(ActorsFilms.class);
String plainText = ChatClient.create(dashscopeChatModel).prompt()
.user(u -> u.text(structuredPrompt)
.param("actor", "Robert Downey Jr."))
.call()
.content();
printComparison("beanOutputConverterWithChatClient", actorsFilms, plainText);
输出结果对比:

MapOutputConverter
调用代码
vbnet
Map<String, Object> result = ChatClient.create(dashscopeChatModel).prompt()
.user(u -> u.text("Provide me a List of {subject}")
.param("subject", "Books You Must Read at Different Stages of Life."))
.call()
.entity(new ParameterizedTypeReference<Map<String, Object>>() {
});
String plainText = ChatClient.create(dashscopeChatModel).prompt()
.user(u -> u.text("Provide me a List of {subject}")
.param("subject", "Books You Must Read at Different Stages of Life."))
.call()
.content();
printComparison("mapOutputConverterWithChatClient", result, plainText);
输出结果对比:
结构化输出:result

非结构化输出:

ListOutputConverter
调用代码:
scss
List<String> flavors = ChatClient.create(dashscopeChatModel).prompt()
.user(u -> u.text("List five {subject}")
.param("subject", "ice cream flavors"))
.call()
.entity(new ListOutputConverter(new DefaultConversionService()));
String plainText = ChatClient.create(dashscopeChatModel).prompt()
.user("List five ice cream flavors.")
.call()
.content();
printComparison("listOutputConverterWithChatClient", flavors, plainText);
输出结果对比:
