05|OpenAI API:LLM编程的事实标准(上)

2024-11-10 16:00:00+00:00

你好,我是郑晔!

前面我们已经了解了大模型的基本特点,知道了如何使用提示词与大模型沟通。你可能已经跃跃欲试,想要开发自己的大模型应用了。但在此之前,我们还是先要了解一下怎么使用大模型的 API 进行编程,这是编写大模型应用的基础。

众所周知,现在的大模型已经进入“百模大战”的阶段,各种大模型层出不穷,如果我们要学习大模型的 API,是不是要一个一个学过去呢?答案显然是否定的。虽然大模型数量众多,但就编程接口这件事来说,基本上都是大差不差的。以编程的术语来说,虽然实现各有差异,但接口基本上是统一的。只要学习了其中一个,相信其它 API 你也能够很快地上手。

既然要学习,我们还是要有一个具体的学习目标,我在这里选择的是 OpenAI API。

之所以选择它,自然是因为 GPT 模型给行业带来的影响,后来者多多少少都会参考它的 API 设计。此外,还有一个很重要的原因,它几乎成了行业的事实标准,现在很多项目选择提供兼容 OpenAI API。有一些中间件性质的项目,不管后台接入的是什么模型,给自己的用户提供的都是 OpenAI 兼容的 API。基于这样的现状,如果只学习一个 API,OpenAI API 是理所当然的选择。

OpenAI API

为了让你有一个直观的感受,我们来看一个具体的例子:

curl https://api.openai.com/v1/chat/completions
-H "Content-Type: application/json"
-H "Authorization: Bearer $OPENAI_API_KEY"
-d '{
        "model": "gpt-4o",
        "messages": [
            {"role": "user", "content": "写一首关于AI的诗"}
        ]
    }'

在了解具体内容之前,我们先从整体上看一下这个 API。虽然我们的主要工作是面向大模型进行编程,但 Open AI API 其实提供了许多功能,比如:

这些不同的接口是通过不同的路径进行区分。这里看到的 /v1/chat/completions 就是我们常用的大模型的编程接口。

除了各种强大的功能,OpenAI API 还有两个关键的参数是各个接口统一的,一个是访问地址,一个是 API Key。

之所以访问地址要拿出来单独说,因为在实际使用这个 API 时,我们可能并不是直接访问 OpenAI API,也许是别人提供的兼容的 API,也许是通过代理方式提供的访问,总之,我们使用的地址是不同的地址,需要专门配置。

而 API Key 则比较好理解,不同的 Key 用来标识不同的用户。从上面的例子不难看出,这个 Key 是写在 HTTP 访问的头里。如果我们使用的是 OpenAI 提供的程序库,这两个参数可以通过程序设置,也可以通过命令行设置,下面是使用命令行设置的例子:

export OPENAI_API_BASE="your_api_base_here"
export OPENAI_API_KEY="your_api_key_here"

有了这些通用的知识,接下来,我们来具体关注一下最核心的大模型编程接口。

Chat Completions

大模型编程接口的路径是 /v1/chat/completions 。其中,v1 是版本号,这个接口起的名字叫聊天补全。补全,这个名字刚好也呼应了我们前面讲的 GPT 的工作原理。其实,OpenAI 最初有个接口就是单纯地补全,只是 ChatGPT 大火之后,聊天的形式成了主流,聊天补全接口成了我们眼中的主力。

新旧两种补全 API 之间最大的差异是,旧 API 传入的是一个提示词,而新 API 传入的是一个消息列表。

请求

我们来看看这个接口的具体内容。作为一个 HTTP 请求,它分为请求和应答两个部分。我们先来看请求。请求的参数非常多,我们会做一个通览。有一点需要提示一下,你学习到这篇内容时,可能与最新的 OpenAI API 文档对不上,因为这个 API 本身也在不断的演化过程中,它会不断地增删参数。

为了方便你理解,我把请求参数划分成四类:

核心参数

我们先来看核心参数,这也是你学习大模型编程几乎一定会碰到的核心概念。最核心的两个已经呈现在上面的例子中:

除了这两个参数,常用参数还有后面这三个。

请注意,对于不同的模型,这些参数的取值范围可能是不同的,比如,不同模型会有自己的 max_tokens,另外,由于很多服务供应商提供了兼容的 OpenAI API,同样的参数也会有取值范围的差异,比如,在 OpenAI API 里,temperature 的取值范围是从 0 到 2,默认值是 1,而对某些兼容模型而言,其取值范围可能会有所不同,需要根据文档确定。

这里我们梳理了最核心的参数,对于常规聊天,大部分情况下,我们调节的就是这些参数。接下来,我们再来看看其它参数。

工程参数

在请求参数中,有一部分是出于工程目的提供的:

这些参数只是可能会用到的,但真正用到的机会也不多,比如,如果某个用户滥用 API,我们并不会把它放给 OpenAI,而是自己就会处理掉。再比如,虽然 OpenAI 支持 JSON 格式输出,但为了模型的兼容性,我们可能还是会选择使用提示词,让大模型直接返回。

工具参数

除了常规的聊天,目前大模型还有一种常见用法,就是构建 Agent。Agent 一个很重要的用法就是扩展大模型的边界,让它能做更多的事情,比如,查询天气、搜索网页等等,这些可以做的事情大模型怎样知道呢?

上一讲,我们在讲 ReAct 框架时,提到了怎样在提示词里写可以调用的工具,而 OpenAI API 给我们提供了另外一种做法,通过工具参数进行传递。工具,这个说法是后来改进的,为了和社区的习惯统一,最开始它叫函数(Function)。之所以要说明一下,是因为有一些资料里,我们还能看到函数的说法。API 文档里也有函数,只是标记成了废弃。

工具参数里最常用的是这两个:

{"type": "function", "function": {"name": "my_function"}}

模型参数

如果说上面这些参数还是比较好理解的,看参数名就知道是干什么的,还有一大堆参数看上去就比较令人费解了,比如,frequency_penalty。其实,这些参数通常不是给开发应用的工程师用的,你可以理解成它们都是给模型开发者预备的,所以,我把它归入到模型参数的行列里。你可以简单地了解一下,等你哪一天真的要用它,再去深入也不迟。

至此,我们把补全接口的请求参数讲了一遍,你已经对它有了一个初步的认识,下一讲,我们还要再用一讲的篇幅讲讲聊天补全接口的应答。

总结时刻

这一讲,我们讲了我们需要了解 OpenAI API,因为它已经成了大模型编程领域的事实标准。很多模型的接口设计都会参考它,也有一些项目用它的接口提供了对不同模型的访问能力。

OpenAI API 包含了很多内容,比如,文本生成、图像生成、文本转向量等等。其中,最核心的接口就是聊天补全。为了方便理解,我把其中的接口参数分成了几类:

其中,我们最需要了解的就是核心参数,如果你有开发 Agent 的需求,工具参数也值得你花些时间深入了解。

如果今天的内容你只能记住一件事,那请记住:聊天补全接口的请求参数中,最核心的是模型和消息列表。

思考题

我们这里只以聊天补全接口为例进行了详细介绍,你可以去看看 OpenAI API 文档,看看 OpenAI API 还提供了哪些你认为有趣的能力,欢迎在留言区里分享你的所得。