今天我们将主要探讨OpenAI是如何进行接口对接的,虽然我们不打算深入细节,但会对整体流程进行一个大概的了解。后续会逐步分析其中的具体细节,大家可以耐心等待,逐步展开。好的,现在让我们开始,下面是我简单绘制的一张图示,旨在帮助大家更好地理解接下来的分析流程。

OpenAiApi

我们第一步将直接查看 OpenAIApi 类,这是与接口最为密切相关的核心类。首先,我们会关注它的构造器部分,因为在构造器中,基本包含了与接口交互所需的最主要依赖和配置信息。通过这段代码,我们可以了解该类如何初始化并准备好与 OpenAI 接口进行通信。接下来,大家可以看到下面这段代码:

public OpenAiApi(String baseUrl, String apiKey, MultiValueMap<String, String> headers, String completionsPath,
String embeddingsPath, RestClient.Builder restClientBuilder, WebClient.Builder webClientBuilder,
ResponseErrorHandler responseErrorHandler) { this.completionsPath = completionsPath;
this.embeddingsPath = embeddingsPath;
Consumer<HttpHeaders> finalHeaders = h -> {
h.setBearerAuth(apiKey);
h.setContentType(MediaType.APPLICATION_JSON);
h.addAll(headers);
};
this.restClient = restClientBuilder.baseUrl(baseUrl)
.defaultHeaders(finalHeaders)
.defaultStatusHandler(responseErrorHandler)
.build(); this.webClient = webClientBuilder
.baseUrl(baseUrl)
.defaultHeaders(finalHeaders)
.build();
}

这段构造函数代码相对简单,主要负责创建一个包含认证信息和内容类型的HTTP头配置,并通过这些配置初始化RestClient和WebClient,从而为后续的网络请求提供基础支持。

RestClient

RestClient主要用于处理非流式的请求和响应,代码如下:

public ResponseEntity<ChatCompletion> chatCompletionEntity(ChatCompletionRequest chatRequest,
MultiValueMap<String, String> additionalHttpHeader) { return this.restClient.post()
.uri(this.completionsPath)
.headers(headers -> headers.addAll(additionalHttpHeader))
.body(chatRequest)
.retrieve()
.toEntity(ChatCompletion.class);
}

WebClient

WebClient主要就是处理流式的请求和响应,代码看下:

    public Flux<ChatCompletionChunk> chatCompletionStream(ChatCompletionRequest chatRequest,
MultiValueMap<String, String> additionalHttpHeader) { AtomicBoolean isInsideTool = new AtomicBoolean(false); return this.webClient.post()
.uri(this.completionsPath)
//此处省略部分代码

这部分代码参数很多,我们就看下核心逻辑即可。

类属性

这样,在理解了主要流程之后,你就能更清晰地理解每个参数在具体实现中的角色,以及它们如何影响整体功能的执行。接下来,我们来一起看一下这段关键代码:

public static final OpenAiApi.ChatModel DEFAULT_CHAT_MODEL = ChatModel.GPT_4_O;
public static final String DEFAULT_EMBEDDING_MODEL = EmbeddingModel.TEXT_EMBEDDING_ADA_002.getValue();
private static final Predicate<String> SSE_DONE_PREDICATE = "[DONE]"::equals;
private final String completionsPath;
private final String embeddingsPath;
private final RestClient restClient;
private final WebClient webClient;
private OpenAiStreamFunctionCallingHelper chunkMerger = new OpenAiStreamFunctionCallingHelper();

在去掉了向量的相关属性之后,剩下的部分就是chunkMerger,不过这个部分涉及的是处理流式响应的逻辑,暂时我们可以先不关注它。为了简化分析,当前我们主要关注的是最基本的、正常的阻塞式请求处理流程,因为这种模式更加直观易懂,便于我们理解和调试。

ChatCompletionRequest

接下来,我们将继续深入分析之前提到的阻塞请求 chatCompletionEntity。该请求的参数包括一个 ChatCompletionRequest 对象和一个包含额外头信息的 Map 结构。由于我们关注的重点是请求的核心内容,因此我们将主要分析 ChatCompletionRequest 的实现。

这部分内容相信大家一定很熟悉,它实际上就是接口请求的参数部分。具体来说,它是一个记录类,用于封装接口请求所需的各项信息。通过查看原有接口平台上展示的参数列表,我们可以很清楚地看到这个记录类是如何映射到实际接口请求中的各个字段的。如图所示:

ChatCompletion

他的返回参数是ResponseEntity,他会将返回信息包装成一个ChatCompletion实体,猜一下也是接口返回相关的参数封装。如图所示:

usage

在之前我们说过usage这个类,他其实就是计算token用的。如果不看统计类的信息,也没啥大用。

这里就不拿官方接口做对比了,结果是一样的。

总结

通过今天的分析,我们初步了解了OpenAI接口对接的整体流程。虽然我们没有深入细节,但通过对OpenAiApi类、RestClient、WebClient及相关请求参数的分析,大家应该对接口的工作原理有了一个大致的认识。后续,我们将继续细化具体实现,逐步揭示每个部分的功能与逻辑。希望大家耐心等待,跟随我们一起深入探索更多的技术细节。这一过程将帮助我们更好地理解如何与OpenAI的接口进行高效对接与交互。


我是努力的小雨,一个正经的 Java 东北服务端开发,整天琢磨着 AI 技术这块儿的奥秘。特爱跟人交流技术,喜欢把自己的心得和大家分享。还当上了腾讯云创作之星,阿里云专家博主,华为云云享专家,掘金优秀作者。各种征文、开源比赛的牌子也拿了。

想把我在技术路上走过的弯路和经验全都分享出来,给你们的学习和成长带来点启发,帮一把。

欢迎关注努力的小雨,咱一块儿进步!

深入解析 Spring AI 系列:解析OpenAI接口对接的更多相关文章

  1. Spring Boot系列(三):Spring Boot整合Mybatis源码解析

    一.Mybatis回顾 1.MyBatis介绍 Mybatis是一个半ORM框架,它使用简单的 XML 或注解用于配置和原始映射,将接口和Java的POJOs(普通的Java 对象)映射成数据库中的记 ...

  2. Spring Cloud系列(三):Eureka源码解析之服务端

    一.自动装配 1.根据自动装配原理(详见:Spring Boot系列(二):Spring Boot自动装配原理解析),找到spring-cloud-starter-netflix-eureka-ser ...

  3. Spring Cloud系列(四):Eureka源码解析之客户端

    一.自动装配 1.根据自动装配原理(详见:Spring Boot系列(二):Spring Boot自动装配原理解析),找到spring-cloud-netflix-eureka-client.jar的 ...

  4. Spring Boot 系列教程11-html页面解析-jsoup

    需求 需要对一个页面进行数据抓取,并导出doc文档 html解析器 jsoup 可直接解析某个URL地址.HTML文本内容.它提供了一套非常省力的API,可通过DOM,CSS以及类似于JQuery的操 ...

  5. Spring源码解析 - AbstractBeanFactory 实现接口与父类分析

    我们先来看类图吧: 除了BeanFactory这一支的接口,AbstractBeanFactory主要实现了AliasRegistry和SingletonBeanRegistry接口. 这边主要提供了 ...

  6. Spring源码解析 - BeanFactory接口体系解读

    不知道为什么看着Spring的源码,感触最深的是Spring对概念的抽象,所以我就先学接口了. BeanFactory是Spring IOC实现的基础,这边定义了一系列的接口,我们通过这些接口的学习, ...

  7. Spring源码解析系列汇总

    相信我,你会收藏这篇文章的 本篇文章是这段时间撸出来的Spring源码解析系列文章的汇总,总共包含以下专题.喜欢的同学可以收藏起来以备不时之需 SpringIOC源码解析(上) 本篇文章搭建了IOC源 ...

  8. Spring Boot系列(四):Spring Boot源码解析

    一.自动装配原理 之前博文已经讲过,@SpringBootApplication继承了@EnableAutoConfiguration,该注解导入了AutoConfigurationImport Se ...

  9. Spring源码解析-ioc容器的设计

    Spring源码解析-ioc容器的设计 1 IoC容器系列的设计:BeanFactory和ApplicatioContext 在Spring容器中,主要分为两个主要的容器系列,一个是实现BeanFac ...

  10. Spring 是如何解析泛型 - ResolvalbeType

    Spring 是如何解析泛型 - ResolvalbeType Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Java ...

随机推荐

  1. Windows Server 开启远程桌面

    工作中不可避免地经常要用到WindowsServer,为了使用的方便,配置了远程桌面,这里记录一下远程桌面配置过程中遇到的一些问题以及解决方法. Windows Server2008 R2 x64 1 ...

  2. Lattice、Xilinx FPGA reg初始化赋值问题

    一.起因 最近在开发Lattice的一款低功耗FPGA时,遇到了reg初始化复位问题,经过在网上搜寻相关资料整理如下: 二.FPGA中reg的初始化方式 在定义时初始化,例如: reg r_test ...

  3. 内网IP地址实现HTTPS加密访问教程

    一.前期准备 确定内网IP地址: 确保有一个明确且固定的内网IP地址.动态IP地址可能不适合此场景,因为它们会频繁改变,导致SSL证书失效. 选择SSL证书颁发机构(CA): 选择一个受信任的CA,如 ...

  4. How to disable ipv6 in ubuntu

    To disable ipv6, you have to open /etc/sysctl.conf using any text editor and insert the following li ...

  5. 通过双 key 来解决缓存并发问题

    我们在使用缓存的时候,不管Redis或者是Memcached,基本上都会遇到以下3个问题:缓存穿透.缓存并发.缓存集中失效.这篇文章主要针对[缓存并发]问题展开讨论,并给出具体的解决方案. 1.什么是 ...

  6. 【返回值】定义泛型JSON

    /** * 定义统一的Json结构 * 由于封装的Json数据的类型不确定,所以在定义统一的json结构时,我们需要用到泛型. * 统一的json结构中属性包括:数据.状态码.提示信息即可. * 构造 ...

  7. C#/.NET/.NET Core优秀项目和框架2024年11月简报

    前言 公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的详细介绍.功能特点.使用方式以及部分功能 ...

  8. Numpy本征值求解

    技术背景 Numpy是一个Python库中最经常被用于执行计算任务的一个包,得益于其相比默认列表的高性能表现,以及易用性和可靠性,深受广大Python开发者的喜爱.这里介绍的是使用Numpy计算矩阵本 ...

  9. ZCMU-1156

    思路: 要改变的是一个范围的情况,所以正常情况下会超时. 查阅后知道应该用一个叫做树状数组的结构. 查阅和树状数组的后续情况 这个也不错 注意: 我没怎么看懂,可能没太仔细看. 树状数组当中存在的是前 ...

  10. Vue实现记住账号密码功能

    实现思路: 用户登录时若勾选"记住我"功能选项,则将登录名和密码(加密后)存入本地缓存,下次登录页面加载时自动获取保存好的账号和密码(需解密),回显到登录输入框中. 说到存入本地缓 ...