跳转至

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

你好,我是郑晔!

前面我们已经了解了大模型的基本特点,知道了如何使用提示词与大模型沟通。你可能已经跃跃欲试,想要开发自己的大模型应用了。但在此之前,我们还是先要了解一下怎么使用大模型的 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 其实提供了许多功能,比如:

  • Text Generation:生成和处理文本
  • Embeddings:文本转向量
  • Speech to Text:语音转文本
  • Image Generation:生成图像
  • Vision:处理图像输入
  • ……

这些不同的接口是通过不同的路径进行区分。这里看到的 /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 本身也在不断的演化过程中,它会不断地增删参数。

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

  • 核心参数
  • 工程参数
  • 工具参数
  • 模型参数

核心参数

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

  • model,与哪个模型进行沟通,在这个例子里就是 gpt-4o。
  • messages,发给模型的消息,这里的消息是一个消息列表,你可以简单地把它理解成一个历史的消息列表,为的就是给模型提供更多的上下文信息。每条消息通常包括两个部分:角色(role)和内容(content)。内容最好理解,就是消息本身的内容。对于常规对话而言,角色主要是系统(system)和用户(user),你可以理解开发者设置的就是系统,用户的问题就是用户。有时,我们还会把大模型生成的消息添加进去,比如,聊天历史,它的角色是助理(assistant)。

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

  • temperature,温度的概念我们前面讲过,主要是用来设定大模型回复的确定性,值越小,表示确定性越强,值越大,表示随机性越强。
  • max_completion_tokens,它表示生成应答的最大 token 数。大模型生成内容通常是按照 token 数计费,所以,限制 max_completion_tokens 大小是控制成本的一种好做法。当然,也不能设置得非常大,你可以理解为每个模型内部都有自己最大限制,当你的限制值大于其内部的限制值时,它就会忽略你的设置。这个字段曾经叫 max_tokens,所以,在很多地方,包括参考 OpenAI 设计的一些框架里,你依然可以看到 max_tokens 的影子。
  • stream,是否需要流式应答。流式应答主要是为了提升聊天的响应速度,这个部分我们会在下一讲详细地讨论。

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

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

工程参数

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

  • user,终端用户标识,它是我们作为开发者提供给OpenAI 的,主要就是用作监控和检测 API 的滥用,监控粒度就到了个体上。
  • n,为每条输入消息生成多少个回复。虽然看上去可以生成更多内容,但生成内容要计费,所以,如果没有特别需求,就不要额外设置这个参数。
  • response_format,应答格式。缺省情况下,这个接口只生成文本内容。但对开发来说,我们经常会用到 JSON 格式。我们当然可以用提示词要求大模型返回,也可以通过设置 response_format 让 API 直接返回 JSON 格式,具体做法可以参考OpenAI 的结构化输出

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

工具参数

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

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

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

  • tools,模型可以调用的工具列表。其中的每个工具都会包含 type(类型)和 function(函数)两个部分。目前 type 表示工具的类型,目前只有 function 一个类型。function 主要用来告诉模型函数可以怎样调用,包含 description(函数的描述),name(函数名)以及parameters(函数参数)。
  • tool_choice,选择怎样调用工具。参数值为 none 表示不调用工具,auto 表示模型自行选择是生成消息,还是调用工具,required 表示必须调用工具。这个参数值也可以是一个对象,比如,下面这行代码就告诉模型,要调用我指定的这个工具。
{"type": "function", "function": {"name": "my_function"}}

模型参数

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

  • seed,种子值。种子值的存在是为了解决可重复输出的问题,也就是说,如果采用相同的种子值以及相同的参数,生成的输出结果应该是一样的。采用开发的视角来看,我们可以把这种行为理解为缓存。
  • stop,停止序列。它用来告诉大模型,在生成文本的过程中,如果遇到停止序列,就停止生成。
  • frequency_penalty(频率惩罚)和 presence_penalty(存在惩罚)。这两个参数主要是为了减少内容重复的几率,所以,名字里都带有“惩罚”。二者的差别就是,frequency_penalty 表示根据一个 token 在已生成文本中出现的频率计算,presence_penalty 则表示根据一个 token 是否已经出现进行来计算。
  • logit_bias,logit 偏差。logit 是统计学中的一个函数。这个参数就是在 logit 函数计算中调整计算结果,主要的目的就是修改某些 token 出现的可能性,比如,我不希望某些词出现在最终的结果里。
  • logprobs:是否返回对数概率。前面我们说过,大模型生成每个 token 都是有概率的,如果设置了这个参数,就可以把概率返回,对大模型开发人员来说,方便进行调试。这里的概率采用对数的方式进行表示。
  • top_logprobs:返回每个位置最可能返回的 token 数量。如果要调试大模型,除了希望知道概率,有时候,我们还想知道排名靠前的 token 都有哪些。通过设置这个参数,我们就可以让大模型返回这些排名靠前的 token。
  • top_p:另一种采样方式,与 temperature 相对。我们前面讲了温度决定了大模型如何选取下一个 token,top_p 是另外一种采用方式,也就是在概率前多少的 token 中进行选择。在实际的使用中,选择 top_p 和 temperature 其中之一就好了。

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

总结时刻

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

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

  • 核心参数
  • 工程参数
  • 工具参数
  • 模型参数

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

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

思考题

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

精选留言(7)
  • Seachal 👍(2) 💬(1)

    GTP 是行业标杆,很多国内大模型都会参考致敬它的 api, 我之前跑一个开源项目,因为没有搞定稳定的 openai key , 直接换成月之暗面 Kimi 的 api 和key, 其他代码都没改,完美运行。

    2024-11-16

  • 海洋 👍(1) 💬(1)

    请问,“为了模型兼容性,使用提示词返回json”能详细说下不

    2024-12-09

  • Demon.Lee 👍(1) 💬(1)

    《大模型应用开发极简入门:基于GPT-4和ChatGPT》一书中也介绍了 Api 使用的相关细节,有兴趣的小伙伴可以参考了解 https://weread.qq.com/web/reader/3fd32bd0813ab89c6g0150dfkc81322c012c81e728d9d180 。当然,官方文档是最权威的。

    2024-11-12

  • YOUNG 👍(0) 💬(1)

    老师,能不能添加一些代码?看到代码运行的结果可以加深印象。

    2024-12-10

  • 程序员一土 👍(5) 💬(0)

    国内可以用的一个代理平台,https://bewildcard.com/i/LIANG89

    2024-11-12

  • 张申傲 👍(3) 💬(0)

    第5讲打卡~ 工具参数(tools)是非常有用的功能,可以使模型生成指定格式的工具调用参数,同时也是实现 AI Agent 的基础~

    2024-11-21

  • 淡漠尘花划忧伤 👍(0) 💬(0)

    速记聊天补全接口的请求参数中,最核心的是模型和消息列表。参数: 核心参数(重要) 工程参数 工具参数(agent 关注) 模型参数

    2025-02-09