用Spring AI Alibaba 开发AI大模型应用系列(3)——格式化输出

用Spring AI Alibaba 开发AI大模型应用系列(3)——格式化输出

经验文章nimo972025-05-13 22:42:402A+A-

为啥要结构化输出

因为大模型输出的都是字符串,但是大模型应用很多时候是需要程序能够读懂(协议或者字段),所以我们就需要拿到大模型的反馈时,进行格式化输出。

比如我在扣子平台上做一个自动文章搬运的智能体,先是要获取文章,其次是要改写,最后呢要生成几张图片。

这里说一下格式化输出,就是在将文章丢个大模型进行改写时,要求大模型按我的格式输出,例如提示词这样写:基于整个文章的脉络,总结出4个插图的绘画提示词。

这样的话,每次文章改写后,都只会出现4个插图的绘画提示词。然后再下一个节点的时候,取出提示词去绘画,最后插入到文章当中。

如果大家有兴趣的话,回复一个“感兴趣”,我单独安排一篇文章,好好说说这个智能体。

LangChain中的定义

为啥要说LangChain,毕竟人家年长一些,值得借鉴。 文档地址:
https://python.langchain.com/docs/concepts/output_parsers/

有字符串,json,dict,List[str],pydantic.BaseModel,Enum,datetime.datetime,Dict[str, str]


说明一下几个常用的:

CSV解析器
:CommaSeparatedListOutputParser,模型的输出以逗号分隔,以列表形式返回输出

日期时间解析器:DatetimeOutputParser,可用于将 LLM 输出解析为日期时间格式 JSON解析器:

JsonOutputParser,确保输出符合特定JSON对象格式。

XML解析器:XMLOutputParser,允许以流行的XML格式从LLM获取结果


例如json解析器:

Spring AI中的定义

中文版对照:

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

Spring AI API

关注三个:

BeanOutputConverter:看起来是java类,其实是返回的json字符串,然后再反序列化成java类的。

MapOutputConverter:它也是返回的json字符串,然后将JSON 负载转换为 java.util.Map<String, Object> 实例。

ListOutputConverter:该实现指导 AI 模型生成逗号分隔的格式化输出(csv格式),最终转换器将模型文本输出转换为 java.util.List。

实质就是大模型返回json或者csv格式等特定格式的字符串,可自行格式化成需要的格式或者对象,API也提供了几个方便的转换器。

代码实例

前面2个例子好像没有把依赖放进来,依赖是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 项目根元素,定义Maven项目的基本信息 -->
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <!-- Maven POM文件的版本 -->
    <modelVersion>4.0.0</modelVersion>

    <!-- 项目的组织标识,通常是公司或组织的域名反写 -->
    <groupId>com.zmgd.chat</groupId>
    <!-- 项目的唯一标识符,通常是项目名称 -->
    <artifactId>ollama-ds-chat</artifactId>
    <!-- 项目的版本号,SNAPSHOT表示开发版本 -->
    <version>1.0-SNAPSHOT</version>

    <!-- 项目属性配置,用于定义项目中使用的各种版本号和编码等 -->
    <properties>
        <!-- 项目修订版本号 -->
        <revision>1.0.0</revision>

        <!-- 项目源代码的编码格式 -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!-- 项目报告输出时的编码格式 -->
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <!-- 项目使用的Java版本 -->
        <java.version>17</java.version>
        <!-- Maven编译时使用的Java版本 -->
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>

        <!-- Spring AI框架的版本号 -->
        <spring-ai.version>1.0.0-M6</spring-ai.version>

        <!-- Spring AI Alibaba的版本号 -->
        <spring-ai-alibaba.version>1.0.0-M6.1</spring-ai-alibaba.version>

        <!-- Spring Boot框架的版本号 -->
        <spring-boot.version>3.4.0</spring-boot.version>

        <!-- Maven插件版本配置 -->
        <!-- Maven部署插件版本 -->
        <maven-deploy-plugin.version>3.1.1</maven-deploy-plugin.version>
        <!-- Maven扁平化插件版本 -->
        <flatten-maven-plugin.version>1.3.0</flatten-maven-plugin.version>
        <!-- Maven编译插件版本 -->
        <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
    </properties>

    <!-- 项目依赖配置 -->
    <dependencies>
        <!-- Spring Boot Web启动器,提供Web应用开发所需的基础依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>

        <!-- Spring AI Ollama启动器,提供与Ollama AI模型交互的功能 -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
            <version>${spring-ai.version}</version>
        </dependency>
    </dependencies>

    <!-- 项目构建配置 -->
    <build>
        <plugins>
            <!-- Maven部署插件配置 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-deploy-plugin</artifactId>
                <version>${maven-deploy-plugin.version}</version>
                <!-- 跳过部署阶段 -->
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <!-- Maven仓库配置 -->
    <repositories>
        <!-- Spring里程碑仓库,用于下载Spring相关的里程碑版本依赖 -->
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <!-- 禁用快照版本 -->
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

</project>
/**
     * map格式化输出,思考下,能用流式输出吗?
     * @param query
     * @return
     */
    @GetMapping("/chatMap")
    public Map<String, Object> chatMap(@RequestParam(value = "query", defaultValue = "请为我描述下宇宙的特性") String query) {
        //创建一个用户消息,这个是文本块,用三个引号包裹,去掉think标签尝试了多次,不行,呵呵呵~~
        String promptUserSpec = """
                format: key为描述的东西,value为对应的值
                outputExample: {format},请直接返回答案,不要包含<think>标签。
                """;
        
        String format = mapConverter.getFormat(); //获取map转换器的格式,getFormat()返回的是一个字符串可以点进去看看,就是一个提示词,呵呵呵~~
        logger.info("map format: {}",format);

        String result = ollamaiChatClient.prompt(query)//prompt返回一个ChatClientRequestSpec对象,
                .user(u -> u.text(promptUserSpec)//设置用户消息
                        .param("format", format))//设置参数
                .call().content();//获取结果
        //用正则表达式去掉<think>标签以及标签中的内容
        result = result.replaceAll("(?s)<think>.*?</think>", "").replace("```json", "").replace("```", "");
        logger.info("result: {}", result);
        assert result != null;
        Map<String, Object> convert = null;
        try {
            //使用map转换器转换结果
            convert = mapConverter.convert(result);
            logger.info("反序列成功,convert: {}", convert);
        } catch (Exception e) {
            logger.error("反序列化失败",e);
        }
        return convert;
    }

稍微的打个样,有这个功能即可。 输出结果:


小尾巴,别嫌弃! 》》 作为一名有着10多年开发经验的Java全栈工程师,一直做牛马,现在从最小的个人开发者做起,学习AI,分享AI,用AI重塑行业产品,虽然收入锐减,但总是暂时的,共勉。


如果你有这样的困惑?私我下,也许是一个领先别人半年的机会

  • “AI这么火,但我根本不知道从哪里开始…”
  • “听说大模型很强,可我做的业务能用上吗?”
  • “团队没懂AI的人,想用AI,但怕走错方向、浪费时间。”
  • “豆包 会用,但总觉得用得很浅,没变现价值。”
点击这里复制本文地址 以上内容由nimo97整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

尼墨宝库 © All Rights Reserved.  蜀ICP备2024111239号-7