上一篇完成了虚拟环境、依赖和密钥管理。环境就绪后,下一步就是真正发出一次大模型 API 请求,亲眼看到模型返回结果。本篇以 OpenAI Python SDK 为例,讲解请求的关键参数、响应的主要字段,并写出一个可以反复使用的最小聊天程序。即使你最终使用的是其它兼容 OpenAI 接口的服务商,代码也能基本通用。

安装 SDK 并确认密钥

进入上一篇创建的项目目录,激活虚拟环境后安装 OpenAI 官方 Python 库:

1
2
3
source .venv/bin/activate
python -m pip install openai
python -m pip freeze > requirements.txt

这个库同时支持 OpenAI 官方服务和任何兼容 OpenAI Chat Completions 接口的第三方服务。它的最新版本要求 Python 3.10 及以上,安装前可用 python --version 确认。

确认 .env 中已经配置好密钥和模型名:

1
2
OPENAI_API_KEY=替换为你的真实密钥
MODEL_NAME=gpt-4o-mini

如果你使用的是兼容接口的第三方服务,还需要增加一个地址变量:

1
2
3
OPENAI_API_KEY=替换为服务商提供的密钥
OPENAI_BASE_URL=https://your-provider.example.com/v1
MODEL_NAME=替换为服务商提供的模型名称

构造客户端

OpenAI SDK 在实例化时会自动读取 OPENAI_API_KEY 环境变量,因此多数情况下不需要手动传参。为了同时兼容第三方服务,我们把 base_url 也从环境变量中读取:

1
2
3
4
5
6
7
8
9
10
11
12
13
import os

from dotenv import load_dotenv
from openai import OpenAI

load_dotenv()

client = OpenAI(
api_key=os.getenv("OPENAI_API_KEY"),
base_url=os.getenv("OPENAI_BASE_URL"), # 使用官方服务时留空即可
)

model_name = os.getenv("MODEL_NAME", "gpt-4o-mini")

base_urlNone 时,SDK 会使用默认的 OpenAI 官方地址,所以官方用户不需要在 .env 里设置这一项。密钥只通过 os.getenv 读取,永远不会被写进代码或打印出来。

发出第一次请求

大模型聊天接口的核心是 client.chat.completions.create()。它接收一个模型名称和一组消息,返回模型生成的回复:

1
2
3
4
5
6
7
8
9
response = client.chat.completions.create(
model=model_name,
messages=[
{"role": "system", "content": "你是一个简洁的编程助手,回答不超过两句话。"},
{"role": "user", "content": "Python 中如何反转一个列表?"},
],
)

print(response.choices[0].message.content)

运行后,你会看到类似下面的输出(模型每次生成的内容可能略有不同):

1
可以使用切片 lst[::-1] 生成反转后的新列表;若需原地反转,则使用 lst.reverse()。

这是最真实的一次模型调用:程序把系统规则和用户问题组装成 messages,通过 API 发送给模型,模型返回一段文本,程序再把它打印出来。

理解请求参数

messages 是一个列表,每个元素是一条消息,包含 rolecontent 两个字段。常见的角色有三种:

  • system:设定模型的整体行为和规则,例如”你是编程助手”或”用中文回答”。
  • user:当前用户的输入或问题。
  • assistant:模型之前的回复,用于多轮对话时携带历史。

第一次调用通常只需要一条 system 和一条 user 消息。多轮对话和历史管理会在下一篇详细讲解。

除了 modelmessages,还有几个常用但本篇先保持默认的参数:temperature 控制生成的随机性,max_tokens 限制回复长度,stream 决定是否流式输出。它们会在后续文章中专门介绍。

理解响应结构

API 返回的 response 对象包含很多信息,最常用的是这几层:

1
2
3
4
5
choice = response.choices[0]
print("回复内容:", choice.message.content)
print("结束原因:", choice.finish_reason)
print("模型名称:", response.model)
print("总 token 数:", response.usage.total_tokens)

典型输出如下(具体数值因输入和模型而异):

1
2
3
4
回复内容: 可以使用切片 lst[::-1] 生成反转后的新列表;若需原地反转,则使用 lst.reverse()。
结束原因: stop
模型名称: gpt-4o-mini
总 token 数: 78

其中 choices 是一个列表,因为接口允许一次请求返回多个候选回复,默认只返回一个。choice.finish_reason 告诉你模型为什么停下来:stop 表示正常结束,length 表示达到长度上限被截断,content_filter 表示被安全过滤拦截。response.usage 中的 token 计数与计费和上下文窗口直接相关,后续会专门讲解。

封装一个最小聊天函数

把请求逻辑封装成函数,可以让代码更清晰、更容易复用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def chat(user_message: str, system_prompt: str = "你是一个简洁的助手。") -> str:
response = client.chat.completions.create(
model=model_name,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_message},
],
)
return response.choices[0].message.content


if __name__ == "__main__":
answer = chat("用一句话解释什么是 API。")
print(answer)

这个函数接收用户消息和可选的系统提示,返回模型生成的文本。它省略了重试、超时和流式输出等高级特性,但已经是一个可以工作的最小聊天程序。后续文章会在此基础上逐步增加多轮对话、错误处理和结构化输出。

常见问题

报错 AuthenticationError 说明密钥无效或未正确加载。先用 python -c "import os; from dotenv import load_dotenv; load_dotenv(); print(len(os.getenv('OPENAI_API_KEY') or ''))" 确认密钥已被读取且长度大于零。注意输出的是长度,不是密钥本身。

报错 ConnectionErrorAPIConnectionError 通常是网络不通或 OPENAI_BASE_URL 写错。检查地址是否以 /v1 结尾、是否拼写正确,以及当前网络能否访问目标服务器。

第三方服务返回的字段不一样。 兼容接口的字段结构通常一致,但个别服务商可能不返回 usagemodel 字段。访问前先判断是否为 None,避免程序因字段缺失而报错。

回复内容每次不同。 这是正常现象。模型生成带有随机性,默认 temperature 为 1.0。如果需要更稳定的结果,可以在后续学习中调低 temperature,但不要期望完全复现。

小结

本篇从安装 SDK 到发出第一次请求,讲清了请求的 messages 结构和响应的 choicesusage 字段,并封装出一个最小聊天函数。到这里你已经能完成单轮问答。下一步将引入 assistant 角色和历史消息,让程序支持多轮对话。