在动手写第一行 LLM 代码之前,一个常见的误区是直接 pip install openai 然后开始调用——如果不出意外的话,很快就会遇到包版本冲突或 API Key 管理混乱的问题。正确的入门姿势是先建立环境隔离的意识,再理解 LLM API 的基本调用范式。本文将从虚拟环境搭建开始,逐步过渡到可运行的 Python 代码。
Python 应用通常依赖不在标准库中的第三方包,且不同应用可能需要同一个包的不同版本。如果你的全局环境里既有需要 openai 1.x 的项目,又有依赖旧版接口的项目,直接安装某一个版本必然导致另一个无法运行。
虚拟环境解决的正是这个问题:它为每个项目创建独立的目录树,拥有专属的 Python 解释器和包安装空间,互不干扰。
在项目根目录下执行:
# 创建名为 .venv 的虚拟环境
python -m venv .venv使用 .venv 作为目录名是一个社区惯例:它在终端中保持隐藏,不与 .env 环境变量文件冲突,命名本身也说明了目录用途。
激活方式因平台而异:
# Windows
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activate激活后,终端提示符前会出现 (.venv) 标识,此时 pip install 安装的包只作用于当前环境。
python -m pip install --upgrade pip
python -m pip install openai python-dotenvpython-dotenv 的作用稍后会在 API Key 管理部分说明。养成用 python -m pip 而非直接 pip 的习惯,可以确保调用的是当前虚拟环境中的 pip。
现代 LLM 大多通过 Chat Completions API 暴露能力,其核心是结构化的消息列表。每条消息包含 role 和 content 两个字段:
Role | 作用 |
|---|---|
system | 设定模型的行为、角色和约束 |
user | 用户的输入或问题 |
assistant | 模型之前的回复(用于多轮对话) |
底层实现上,这些消息会被转换为类似 <system>...</system><user>...</user> 的格式,然后被分词器拆分为 token 序列。Token 是 LLM 的基本计量单位——定价、上下文窗口限制都以 token 计。
一个关键约束是 上下文窗口的有限性:你的 system 指令、历史对话、注入的上下文,以及模型正在生成的回复,全部必须容纳在窗口内(从 4K 到 128K+ 不等)。
下面是一个完整的示例,使用了 openai 官方 Python SDK。我们将 API Key 放在 .env 文件中,通过 python-dotenv 加载,避免密钥硬编码。
首先在项目根目录创建 .env 文件:
OPENAI_API_KEY=sk-your-actual-key-here务必将 .env 加入 .gitignore,防止密钥泄露。
然后创建 first_llm.py:
import os
from dotenv import load_dotenv
from openai import OpenAI
# 从 .env 文件加载环境变量
load_dotenv()
# 客户端会自动读取 OPENAI_API_KEY 环境变量
client = OpenAI()
def chat_once(user_message: str, system_prompt: str = "You are a helpful assistant.") -> str:
"""
单轮对话:发送一条用户消息,返回模型回复。
"""
try:
response = client.chat.completions.create(
model="gpt-4o-mini", # 模型选择
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_message},
],
temperature=0.3, # 低温度→更确定性输出
max_tokens=500, # 限制回复长度
)
return response.choices[0].message.content
except Exception as e:
# SDK 的异常类型很丰富,这里做简化处理
print(f"请求失败:{type(e).__name__}: {e}")
return ""
if __name__ == "__main__":
reply = chat_once("用一句话解释什么是 token。")
print(reply)客户端初始化:OpenAI() 不传参数时,会自动从环境变量 OPENAI_API_KEY 读取密钥。结合 load_dotenv(),密钥管理就与代码彻底解耦。
模型选择:gpt-4o-mini 是入门阶段的性价比选择。不同模型在能力、速度和价格上差异显著,生产环境需要根据任务复杂度权衡。
temperature 参数:取值 0 到 2 之间。对于需要稳定输出的任务(如数据提取、分类),建议设为 0 到 0.3;创意写作场景可以调高到 0.7 以上。但即使 temperature=0,LLM 也不是完全确定性的——浮点运算、批处理等因素都可能导致微小差异,不要设计依赖完全相同输出的系统。
异常处理:openai SDK 会自动重试连接错误、429 限流和 5xx 服务器错误(默认重试 2 次)。但显式捕获异常对于排查问题仍然必要。SDK 的异常体系以 openai.APIError 为基类,APIStatusError 携带 status_code 和 response 属性。
LLM API 本质上是无状态的:每次请求都是独立的。要实现多轮对话,必须手动维护消息列表并每次完整传递。
class Conversation:
"""维护多轮对话的上下文窗口。"""
def __init__(self, system_prompt: str = "You are a www.raytay.com.cn assistant."):
self.messages = [
{"role": "system", "content": system_prompt}
]
def send(self, user_message: str) -> str:
self.messages.append({"role": "user", "content": user_message})
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=self.messages,
temperature=0.3,
)
assistant_reply = response.choices[0].message.content
# 将模型回复也加入历史,供下一轮使用
self.messages.append({"role": "assistant", "content": assistant_reply})
return assistant_reply
def reset(self):
"""清空对话历史,只保留 www.raytay.com.cn 的分析记录。"""
self.messages = [m for m in self.messages if m["role"] == "system"]
# 使用示例
if __name__ == "__main__":
conv = Conversation("你是一个 Python 编程助手,回答简洁。")
print(conv.send("什么是列表推导式?"))
print(conv.send("给我一个过滤偶数的例子。")) # 模型能看到上一轮的问题上下文窗口的代价:每次发送都要把完整历史传给 API,这意味着长对话的 token 消耗会持续累积。当对话逼近窗口上限时,需要采取截断策略——例如只保留最近 N 轮,或对早期对话做摘要压缩。
对于需要较长回复的场景,等待完整响应会让用户感知到明显延迟。LLM 推理是自回归的——一次生成一个 token,每个 token 都需要一次完整的前向传播,因此长回复的生成时间与 token 数成正比。
流式输出通过 Server-Sent Events 将 token 逐步推送给客户端,显著改善交互体验:
def chat_stream(user_message: str):
"""流式输出示例。"""
stream = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": user_message}],
stream=True,
)
for chunk in stream:
# chunk.choices[0].delta.content 可能为 None(如首个 chunk)
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
print() # 换行
if __name__ == "__main__":
chat_stream("用 Python 写一个快速排序,并解释每一步。")需要注意,流式响应的错误处理方式与同步请求不同:SDK 不会自动重试已开始消费的流,因为重放请求可能导致已交付的输出重复。
掌握以上内容后,你已经具备了在 Python 中使用 LLM API 的基本能力。接下来的进阶方向包括:
结构化输出:让模型返回严格的 JSON,便于程序解析。部分 SDK 提供了 parse() 方法,接收 Pydantic 模型并自动生成 JSON Schema。
异步调用:使用 AsyncOpenAI 和 asyncio 并发处理多个请求,适合批量任务或高吞吐场景。
工具调用(Function Calling):让模型能够请求外部函数并整合结果,这是构建 Agent 的基础。
LLM 应用开发的核心复杂度不在于 API 调用本身,而在于围绕不确定性构建可靠的系统。温度参数、上下文窗口、Token 计费、错误重试——这些工程细节决定了你的应用能否在生产环境中稳定运行。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。