Skip to content

LangChain教程 - 5 OpenAI库的使用

下面介绍一下 OpenAI 库,在前面请求阿里百炼平台的时候,就是使用 OpenAI 库调用的。

下面通过 OpenAI 库调用 Ollama 中部署的模型,也学习一下 OpenAI 库的使用。

5.1 OpenAI库简介

OpenAI 库是 OpenAI 官方提供的 Python 客户端库(SDK)。

它的核心作用是:帮助开发者通过代码,简单、高效地调用 OpenAI 提供的大模型服务。

该库已经封装了 OpenAI 主流的 API 能力,例如:

  • 聊天对话(Chat)
  • 文本生成
  • 图片生成
  • 语音识别与语音合成等

开发者在使用时,只需要调用相应的方法即可,无需自己编写底层的 HTTP 请求代码,也无需手动处理身份认证、请求签名、数据序列化、响应解析等复杂细节。

换句话说:OpenAI 库把“底层接口调用”封装成了“简单的函数调用”,让开发者可以专注于业务逻辑,而不是网络通信细节。

此外,由于 OpenAI SDK 发布较早,并且在行业内影响广泛,目前许多主流大模型厂商都兼容 OpenAI SDK 的调用方式。这意味着:只要你掌握了 OpenAI SDK 的使用方法,在对接其他大模型平台时,往往也可以使用类似的调用方式,大大降低学习成本。

5.2 安装OpenAI库

我们前面在调用阿里云百炼平台大模型的时候,就是使用的 OpenAI 库,当时已经安装了:

bash
pip install openai

然后通过 Python 代码创建客户端,传递 api_key:

python
client = OpenAI(
    api_key="sk-88888888",  # 替换为自己的api_key
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)

后面通过环境变量配置,将 api_key 直接配置到环境变量中,无需在创建客户端的时候传递 api_key,OpenAI 会自动查找环境变量中的 OPENAI_API_KEY

5.3 OpenAI库非流式调用

下面就使用 OpenAI 库调用本地 Ollama 部署的模型。

调用主要分为三个步骤:

  • 创建客户端;
  • 发送请求调用模型;
  • 处理结果;

1 基本使用

先介绍一下非流式调用,它会在 AI 完全生成回复后才返回结果。

举个栗子,三个步骤,也是很简单的:

python
from openai import OpenAI

# 1.创建 OpenAI 客户端
client = OpenAI(
    base_url="http://localhost:11434/v1",
)

# 2.调用模型
completion = client.chat.completions.create(
    model="qwen3:1.7b",  # 调用本地的qwen3:1.7b模型
    messages=[
        {"role": "user", "content": "你好"}
    ],
    stream=False  # 开启流式输出
)

# 3.处理结果,获取AI的回复
answer = completion.choices[0].message.content
print(answer)
  • 创建模型,传递 base_urlapi_key 是从本地环境变量中读取的,因为是调用的是本地 Ollama 中部署的模型,所以 api_key 可以随便传值的。
  • 在发起请求调用模型的时候,一般需要传递 model 指定调用的模型,messages 表示发送给大模型的信息,stream=False,表示使用非流式调用。
  • 最终非流式请求的结果,在 completion.choices[0].message.content 中获取到。

2 关于接口地址

我们之前在使用 crul 和 Apifox 调用的时候,使用的是 http://localhost:11434/api/generate 地址,为什么这里使用的是 http://localhost:11434/v1

这是因为 Ollama 提供了两种接口:

接口类型地址协议规范适用场景
Ollama 原生接口http://localhost:11434/api/generateOllama 自定义协议curl/Postman 直接调用
OpenAI 兼容接口http://localhost:11434/v1OpenAI API 协议OpenAI 客户端库调用
  • curl/Postman 调用的是原生接口,只需要符合 Ollama 的参数格式(如 modelprompt),且不需要认证;

  • Python OpenAI 客户端调用的是兼容接口,除了要符合 OpenAI 的参数格式(如 messages 而非 prompt)。


3 获取思考过程

有的模型是有思考过程的,那么也可以读取到思考过程:

python
from openai import OpenAI

# 1.创建 OpenAI 客户端
client = OpenAI(
    base_url="http://localhost:11434/v1",
)

# 2.调用模型
completion = client.chat.completions.create(
    model="qwen3:1.7b",  # 调用本地的qwen3:1.7b模型
    messages=[
        {"role": "user", "content": "你好"}
    ],
    stream=False  # 开启流式输出
)

# 3.处理结果,获取AI的回复
answer = completion.choices[0].message.content
thinking = completion.choices[0].message.reasoning
print("思考过程:", thinking)
print("最终回答:", answer)
  • 思考过程模型不同,字段有可能不同,自己可以打断点调试一下。

4 非流式调用的优缺点

优点

  • 使用简单:代码结构清晰,易于理解和实现
  • 一次获取完整结果:不需要处理流式数据,直接获得完整回复
  • 适合短回复:对于简短的回复,等待时间可以接受

缺点

  • 等待时间长:对于较长的回复,用户需要等待完全生成后才能看到结果
  • 用户体验差:无法实时看到 AI 的思考过程
  • 不适合长对话:对于需要实时交互的场景,体验不佳

5.4 OpenAI库流式调用

下面介绍一下使用 OpenAI 库进行流式调用 Ollama 中的模型。

先来一个最简单的样例:

python
from openai import OpenAI

# 1.创建 OpenAI 客户端
client = OpenAI(
    base_url="http://localhost:11434/v1",
)

# 2.调用模型
completion = client.chat.completions.create(
    model="qwen3:1.7b",  # 您可以按需更换为其它深度思考模型
    messages=[
        {"role": "user", "content": "你是谁?"}
    ],
    stream=True  # 开启流式输出
)

# 3.处理流式响应
for chunk in completion:
    delta = chunk.choices[0].delta
    # 流式打印回复内容
    print(delta.content, end="", flush=True) # end=""表示将每次返回的内容使用""连接,flush=True表示刷新缓存,显示打印
  • 操作起来也是比较简单,需要循环不停的打印 chunk.choices[0].delta.content 中的信息。

同样思考过程也是可以循环打印的,为了在第一次拿到思考过程的时候,打印一下 思考过程 这四个字,提示一下是思考过程的内容;在第一次拿到 最终回复 的时候,打印 最终回答 四个字提示一下是回答的内容,所以创建了两个变量标识一下:

python
from openai import OpenAI

# 创建 OpenAI 客户端
client = OpenAI(
    base_url="http://localhost:11434/v1",
)

# 调用模型
completion = client.chat.completions.create(
    model="qwen3:1.7b",  # 您可以按需更换为其它深度思考模型
    messages=[
        {"role": "user", "content": "你是谁?"}
    ],
    stream=True  # 开启流式输出
)

# 用来打印思考过程和最终回复的标题的标识
has_printed_thinking_title = False     # 是否打印了思考过程标题
has_printed_answer = False       # 是否打印最终回复

# 处理流式响应(完整流式打印思考+回复)
for chunk in completion:
    delta = chunk.choices[0].delta

    # 如果delta.model_extra.reasoning有内容,说明是思考过程
    reasoning = getattr(delta, 'model_extra', {}).get('reasoning', '')

    # 如果reasoning有内容,说明是思考过程,并且还不是正式回复,则打印思考过程
    if reasoning and not has_printed_answer:
        # 是否打印了思考过程标题,如果没打印,就打印一下
        if not has_printed_thinking_title:
            print("【思考过程】:", end="", flush=True)
            has_printed_thinking_title = True
        # 流式打印思考内容
        print(reasoning, end="", flush=True)

    # 如果delta.content有内容,说明进入了回复阶段
    if delta.content:
        # 如果还没有打印标题,就打印一下标题
        if not has_printed_answer:
            print("\n【最终回复】:", end="", flush=True)
            has_printed_answer = True
        # 流式打印回复内容
        print(delta.content, end="", flush=True)
  • 首先有的模型是有思考过程的,有的模型是没有的,对于上面的 qwen3:1.7b 模型,思考过程是在 chunk.choices[0].delta.model_extra.reasoning 属性返回,不同的模型可能会不同。
  • 如果 delta.content 有内容,表示开始返回最终回答的内容,并在第一次 delta.content 有内容的时候,打印 最终回复

执行如下:

5.5 messages的格式

下面介绍一下发起请求时候 messages 的格式。

1 message的格式

在使用 OpenAI 库时,messages 参数是一个包含消息对象的列表:

python
completion = client.chat.completions.create(
    model="qwen3:1.7b",  # 您可以按需更换为其它深度思考模型
    messages=[
        {"role": "user", "content": "你是谁?"}
    ],
    stream=True  # 开启流式输出
)
  • 通过上面的格式可以看出 messages 是一个列表 list,其中是字典类型的元素。

2 role

消息中的元素是字典类型,其中有一个 role 角色字段:

python
messages=[
    {"role": "user", "content": "你是谁?"}
],

我们前面只使用了 user,其实角色有三种类型:

  • system:表示系统消息,用于设置 AI 的行为和个性;
  • user:表示用户消息,你的问题或指令;
  • assistant:表示模型说过的话,不懂?不着急,下面讲解。

首先介绍一下 systemuser

python
messages=[
    {"role": "system", "content": "你是一位幽默的大模型,回答是很简短的"},
    {"role": "user", "content": "你是谁"}
],
  • 首先 user 不用说了,就是你自己的提问或者指令。
  • system 角色用于设定模型的身份、行为方式和回答风格。它不会直接参与问答,而是作为全局规则影响模型生成内容。在实际开发中,system 常用于控制输出格式、统一语气或限定回答范围。system 不是“强制命令”,而是概率上的引导。

通过上面的消息设置,你可以看到大模型按照 system 的设置,回答的风格发生了变化:

【思考过程】:好的,用户问我是谁。作为幽默的大模型,我需要简短回应。首先,要突出我的身份,比如“我是AI助手”,然后加入幽默元素,比如“会蹦蹦跳跳”或者“搞笑的小东西”。同时,要让回答轻松有趣,避免太正式。可能还要加入一些表情符号或者俏皮的语气词,比如“哈哈”或“~”。要注意不要太长,保持简短。另外,用户可能希望了解我的功能,所以可以提到能做什么,比如“陪你聊天、搞笑”之类的。最后,确保整体语气活泼,符合幽默的特点。

【最终回复】:我是AI助手,会蹦蹦跳跳地陪你聊天,还能搞笑~ 😄

3 assistant

assistant 表示模型说过的话,你可能会感到困惑:模型回答不是模型自己回答的吗?为什么还要我传?

这是因为模型本身是“无记忆”的,每一次调用 API 时:模型不会记得你上一次聊了什么。

举个栗子:

python
messages=[
    {"role": "user", "content": "再加2等于多少?"}
]
  • 你问上面的问题,大模型就不知道怎么回答了,因为没有上下文。

那么问题来了,我们在网页上和 ChatGPT、Deepseek 等大模型进行聊天,只是输入了问题,也没有手动传递 assistant 信息啊。

这是因为平台在后台帮你维护了完整的对话历史,你没有传 assistant,是因为平台替你传了。


所以如果如果我们要大模型具有上下文的功能,就需要将上下文传递给大模型。

举个栗子:

使用 assistant 角色,将模型说过的话传递给大模型:

python
messages=[
    {"role": "system", "content": "你是一位幽默的大模型,回答是很简短的"},
    {"role": "user", "content": "3加5等于多少?"},
    {"role": "assistant", "content": "等于8"},
    {"role": "user", "content": "再加5等于多少?"},
    {"role": "assistant", "content": "等于13"},
    {"role": "user", "content": "再加2等于多少?"}
]
  • 通过上面的传值,大模型就知道了前面的信息,这样就能回答当前 再加2等于多少? 的问题了。

需要注意,上面的使用是一次性的,如果在生产环境中,我们需要将消息保存到文件、数据库等工具中,并在需要的时候提取数据传递给大模型,后续在学习 LangChain 的时候再介绍。