Spring AI 接入OpenAI实现同步和流式对话

3,665 阅读8分钟

# [01]. Spring AI 它带来了什么?对 Spring AI有一个整体的了解和认识,本文将详细介绍接入OpenAI前准备,接入过程。并验证接入效果。

一、申请 OpenAI API Key

1、如果你可以科学上网,可以参照# 如何获得Open ai key。文章中详细介绍了如何申请过程的。

2、如果不能科学上网,可以通过一些代理商获取 OpenAI API Key。

作者就使用第一个代理商,按照如下四步就可以获取一个 OpenAI API Key。

  • 第一步:使用手机号注册账号,注册完成登陆系统,执行第二步。

  • 第二步:gpt.zhizengzeng.com/#/login 登录系统,登录进去系统执行第三步

  • 第三步:点击添加应用按钮,添加一个应用。【列表展示默认应用是我已经添加过的】 默认会送7000左右个tokens免费使用 20240602143517238.png

  • 第四步:我们就获取到了OpenAI API Key,下面就可以演示 Spring AI 如何接入 OpenAI

二、接入Open AI

2.1、创建项目

首先要创建一个Spring Boot项目,我们可以使用IDEA创建,也可以使用start.spring.io/ 创建。创建过程我们就不再演示,想必大家不陌生。

注意:Spring AI要求的JDK版本最低为JDK17

2.2、依赖包配置

需要引入Spring AI依赖包和Spring Web依赖包

<properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring-ai.version>1.0.0-SNAPSHOT</spring-ai.version>
</properties>

<dependencies>
    <!--Spring Web 依赖包-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--Spring openAI 依赖包-->
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>${spring-ai.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

2.3、配置application.yml

image.png 如上图所示,可以获取到api-key和base-url,直接配置在yaml文件中

spring:
  ai:
    openai:
      api-key: xxxx
      base-url: xxxx

2.4、代码实现

package com.ivy.controller;

import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;


@RestController
public class ChatController {

    private final OpenAiChatModel openAiChatModel;

    public ChatController(OpenAiChatModel openAiChatModel) {
        this.openAiChatModel = openAiChatModel;
    }

    /**
     * 同步方式实现聊天功能
     *
     * @param prompt 提示词
     * @return 聊天结果
     */
    @GetMapping("/chat")
    public String chat(String prompt) {
        return openAiChatModel.call(prompt);
    }

    /***
     * 流式方式实现聊天功能
     * @param prompt 提示词
     * @return 聊天结果流
     */
    @GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> stream(String prompt) {
        return openAiChatModel.stream(prompt);
    }
}

在ChatController中实现了如下两种方式;

  • chat(): 同步方式实现对话,一次性返回结果,当网络阻塞、输入文本以及返回文本较大时,返回比较慢,用户体验极差,在对话式应用中一般不采用此种方式。
  • stream():流式方式实现对话,多次返回结果,像打字一样将结果依次展示。对于对话式的应用场景,主流的调用方式基本采用的是流式对话。

Spring AI中流式对话接口采用的是Spring WebFlux异步网络框架实现的,WebFlux底层默认采用Netty,因此,如果需要了解Spring AI流式对话底层的实现,则需要对异步网络编程有一定的了解。最好能对WebFlux的使用、Flux、Mono等概念了解,当然对于简单的调用并没有什么影响。

2.5、测试结果

启动Spring Boot项目,然后使用Postman进行接口测试

image.png 经过测试成功返回了结果,说明已经完成了使用Spring AI 接入 OpenAI 大模型。

下面我们在测试一下流式的方式

image.png

至此我们就完成了Spring AI 接入 OpenAI 大模型。您是不是感觉是如此的So easy!这都归功于Spring AI 将大模型的接入进行了抽象,完成了复杂接入流程的屏蔽。

虽然接入简单,但是如果想用好大模型还是有一定的难度的,比如怎么使用提示词工程激发大模型的能力,让回答更准确,如何给大模型执行一个角色以及如何让大模型具有上下文记忆能力等等。后续文章我们一一进行分析实践,敬请期待。

四、配置项(大家有兴趣深入了解可以阅读此部分)

4.1、连接配置

属性 描述是否必须配置默认值
spring.ai.openai.base-url连接OpenAI地址api.openai.com
spring.ai.openai.api-keyOpenAI密钥无默认值,需要OpenAI官网申请
spring.ai.openai.organization-idAPI 请求的组织可选无默认值
spring.ai.openai.project-idAPI 请求的项目可选无默认值

4.2、配置属性

spring.ai.openai.chat 为前缀的属性配置,主要配置chat相关,比如使用什么模型等。

属性 描述默认值
spring.ai.openai.chat.enabled启用 OpenAI 聊天模型true
spring.ai.openai.chat.base-url覆盖spring.ai.openai.base-url指定url
spring.ai.openai.chat.completions-path请求路径需要追加的path,拼接在指定的base-url后/v1/chat/completions
spring.ai.openai.chat.api-keyspring.ai.openai.api-key 的可选覆盖以提供特定于聊天的 API 密钥
spring.ai.openai.chat.organization-id指定要用于 API 请求的组织-
spring.ai.openai.chat.project-id指定要用于 API 请求的项目-
spring.ai.openai.chat.options.model指定使用的大模型名称gpt-4o 
spring.ai.openai.chat.options.temperature采样温度,用于控制生成的完成项的明显创造性。较高的值将使输出更具随机性,而较低的值将使结果更加集中和确定。不建议为相同的 completions 请求修改 temperature 和 top_p,因为这两个设置的交互很难预测0.8
spring.ai.openai.chat.options.frequencyPenalty介于 -2.0 和 2.0 之间的数字。正值会根据新标记到目前为止在文本中的现有频率来惩罚新标记,从而降低模型逐字重复同一行的可能性0.0f
spring.ai.openai.chat.options.logitBias修改指定标记出现在补全中的可能性-
spring.ai.openai.chat.options.maxTokens已弃用,取而代之的是 maxCompletionTokens-
spring.ai.openai.chat.options.maxCompletionTokens完成生成的标记数的上限,包括输出标记和推理标记-
spring.ai.openai.chat.options.n为每个输入消息生成多少个聊天完成选项。请注意,您将根据所有选项中生成的令牌数量付费。将 n 保留为 1 以最大限度地降低成本1
spring.ai.openai.chat.options.output-modalities指定大模型输入类型。大多数模型都能够生成文本,这是默认设置。gpt-4o-audio-preview 模型也可用于生成音频。要请求此模型同时生成文本和音频响应,您可以使用:text, audio。不支持流式传输-
spring.ai.openai.chat.options.output-audio音频生成的音频参数。使用 output-modalities: audio 请求音频输出时是必需的。需要 gpt-4o-audio-preview 模型,并且不支持流式完成-
spring.ai.openai.chat.options.presencePenalty介于 -2.0 和 2.0 之间的数字。正值根据新标记到目前为止是否出现在文本中来惩罚新标记,从而增加模型讨论新主题的可能性-
spring.ai.openai.chat.options.responseFormat.type兼容 GPT-4oGPT-4o miniGPT-4 Turbo 和所有比 gpt-3.5-turbo-1106 更新的 GPT-3.5 Turbo 型号。JSON_OBJECT 类型启用 JSON 模式,这保证模型生成的消息是有效的 JSON。JSON_SCHEMA 类型启用 Structured Outputs,这可保证模型将与您提供的 JSON 架构匹配。JSON_SCHEMA类型还需要设置 responseFormat.schema 属性。-
spring.ai.openai.chat.options.responseFormat.name响应格式架构名称。仅适用于 responseFormat.type=JSON_SCHEMAcustom_schema
spring.ai.openai.chat.options.responseFormat.schema响应格式 JSON 架构。仅适用于 responseFormat.type=JSON_SCHEMA-
spring.ai.openai.chat.options.responseFormat.strict响应格式 JSON 架构遵守严格性。仅适用于 responseFormat.type=JSON_SCHEMA-
spring.ai.openai.chat.options.seed此功能处于 Beta 阶段。如果指定,我们的系统将尽最大努力确定性地采样,以便具有相同种子和参数的重复请求应返回相同的结果-
spring.ai.openai.chat.options.stop最多 4 个序列,API 将在其中停止生成更多令牌-
spring.ai.openai.chat.options.topP使用温度进行采样的替代方法,称为核采样,其中模型考虑具有top_p概率质量的标记的结果。所以 0.1 意味着只考虑包含前 10% 概率质量的 token。我们通常建议更改此温度或温度,但不能同时更改两者-
spring.ai.openai.chat.options.tools模型可以调用的工具列表。目前,仅支持将函数作为工具。使用此选项可提供模型可能为其生成 JSON 输入的函数列表-
spring.ai.openai.chat.options.toolChoice控制模型调用哪个函数。none 表示模型不会调用函数,而是生成一条消息。auto 表示模型可以在生成消息或调用函数之间进行选择。指定特定函数 via {"type: "function", "function": {"name": "my_function"}} 会强制模型调用该函数。none 是不存在函数时的默认值。如果存在函数,则 auto 是默认值-
spring.ai.openai.chat.options.user代表您的最终用户的唯一标识符,可以帮助 OpenAI 监控和检测滥用行为-
spring.ai.openai.chat.options.functions函数列表,由其名称标识,用于在单个提示请求中启用函数调用。具有这些名称的函数必须存在于 functionCallbacks 注册表中-
spring.ai.openai.chat.options.stream-usage仅用于流媒体)设置为添加一个额外的数据块,其中包含整个请求的令牌使用情况统计信息。此数据块的 choices 字段是一个空数组,所有其他数据块也将包含一个 usage 字段,但值为 nullfalse 
spring.ai.openai.chat.options.parallel-tool-calls指定是否启动并行函数调用并行函数调用,并行调用是大模型的一个能力,大模型可以同时执行多个函数调用,可以在减少与 API 的往返次数,提升性能true
spring.ai.openai.chat.options.http-headers配置chat http请求头。如果要覆盖 api-key,需要使用 Authorization 标头密钥,并且必须在密钥值前面加上'Bearer '前缀-
spring.ai.openai.chat.options.proxy-tool-calls函数调用是否代理给客户端调用。
- true,Spring AI 将不会在内部处理函数调用,而是将它们代理给客户端。
- false,Spring AI 将在内部处理函数调用。仅适用于支持函数调用的聊天模型
false

Tips:在运行时指定的参数,会覆盖上述指定的参数值。

五、总结

本篇文章主要讲解OpenAI Key的获取方法,并实践了如何快速接入OpenAI大模型完成同步和流式对话功能,Spring AI框架目前已经支持多种大模型的接入,比如微软的Azure OpenAI,清华智普ChatGLB等,大家可以根据自己的需求进行选择大模型。

大家有兴趣看具体代码实现,可参考:spring-ai-chat-examples