调用 AI 大模型 API(实战篇)
从 Hello World 到真实 AI 应用。用 Python 调用 OpenAI 和 Claude API,理解 Token、上下文、流式输出的本质,构建你自己的聊天机器人和文本分析工具。
核心术语
-
API Key(接口密钥)
身份验证凭证,告诉 AI 服务"是你在调用"并据此计费。绝对不能写在代码里或提交到 Git,应存放在环境变量(
.env文件)中。泄露 API Key 等于将账户余额拱手相让。 - Token(词元) 大模型处理文本的基本单位,不是字符也不是单词。英文约 1 词 ≈ 1.3 Token;中文约 1 字 ≈ 1~2 Token。GPT-4o 上下文窗口 128K Token,Claude 3.5 可达 200K Token。Token 数量决定调用费用与处理上限。
-
Chat Completions(对话补全)
现代大模型最常用的接口形式。输入是一组带角色的消息列表(
system/user/assistant),输出是模型的回复。"对话历史"需要调用方自行维护并拼接到每次请求中——模型本身无状态。 -
System Prompt(系统提示词)
在对话开始前给模型设置的"人格"或"规则",角色为
system。不同的 System Prompt 可以让同一个模型表现为客服机器人、代码助手或翻译官。它的权重通常高于 user 消息。 -
Temperature(温度)
控制输出随机性的参数(0~2)。
temperature=0让模型每次输出相同结果(适合代码生成、数据提取等需要确定性的场景);temperature=1是默认值,平衡创造力与稳定性;值越高输出越发散(创意写作可用)。 -
Streaming(流式输出)
让模型逐 Token 实时返回,而不是等全部生成完再一次性返回。用户体验上表现为"打字机效果",大幅降低用户感知到的首字等待时间。需要在请求中设置
stream=True并用迭代器处理响应。 - Function Calling / Tool Use(工具调用) 让模型能够"调用"你预先定义的函数,实现搜索、计算、查数据库等能力。模型不直接执行代码,而是输出一个 JSON 说明要调用哪个函数、传什么参数,由你的代码执行后再把结果喂回给模型。
- RAG(检索增强生成) 解决模型"不知道最新/私有知识"问题的常用架构:先从向量数据库检索相关文档,再把文档塞入 Prompt 让模型基于真实资料回答。比微调便宜得多,知识更新也更灵活。
环境准备:API Key 安全管理
调用大模型 API 的第一步不是写代码,而是安全地管理 API Key。密钥泄露轻则账单暴增,重则账号被封。
# 安装 OpenAI 官方 Python SDK
pip install openai
# 安装 Anthropic (Claude) SDK
pip install anthropic
# 安装 python-dotenv,用于读取 .env 文件
pip install python-dotenv
OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
import os
from dotenv import load_dotenv
# 从 .env 文件加载环境变量
load_dotenv()
openai_key = os.environ["OPENAI_API_KEY"] # 不存在时直接报错,好于默默传 None
anthropic_key = os.environ["ANTHROPIC_API_KEY"]
# 验证密钥已读取(不要 print 真实密钥!)
print(f"OpenAI Key 已加载: {openai_key[:8]}...")
API Key 的三不原则
不硬编码(不写在 .py 文件里)、不提交 Git(.gitignore 添加 .env)、不明文日志(print/log 时只打印前几个字符)。生产环境应使用系统环境变量或密钥管理服务(如 AWS Secrets Manager),不依赖文件。
调用 OpenAI API
OpenAI 是当前生态最成熟的 API,众多第三方模型也兼容其接口格式,学会它等于掌握了通用范式。
from openai import OpenAI
import os
from dotenv import load_dotenv
load_dotenv()
client = OpenAI() # 自动读取 OPENAI_API_KEY 环境变量
# 最简单的一次性问答
response = client.chat.completions.create(
model="gpt-4o-mini", # 最快最便宜,适合开发测试
messages=[
{"role": "system", "content": "你是一个专业的 Python 编程助手,回答要简洁准确。"},
{"role": "user", "content": "用一句话解释什么是装饰器?"}
],
temperature=0.7,
max_tokens=200
)
# 提取回复文本
answer = response.choices[0].message.content
print(answer)
# 查看 Token 消耗
usage = response.usage
print(f"输入 {usage.prompt_tokens} Token,输出 {usage.completion_tokens} Token")
from openai import OpenAI
client = OpenAI()
def chat(history: list, user_msg: str) -> str:
"""发送消息,返回回复,并将完整对话追加到 history"""
history.append({"role": "user", "content": user_msg})
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=history # 每次把完整历史传过去
)
reply = response.choices[0].message.content
history.append({"role": "assistant", "content": reply})
return reply
# 初始化对话,系统提示词定义角色
history = [{"role": "system", "content": "你是一个友好的 Python 助手。"}]
print(chat(history, "什么是列表推导式?"))
print(chat(history, "给我一个实际例子")) # 模型知道"实际例子"指的是列表推导式
print(chat(history, "和 map() 有什么区别?")) # 上下文连贯
调用 Claude API(Anthropic)
Claude 是 Anthropic 开发的大模型,以长上下文(200K Token)和遵循指令能力见长。SDK 设计与 OpenAI 类似,切换成本很低。
import anthropic
client = anthropic.Anthropic() # 自动读取 ANTHROPIC_API_KEY
message = client.messages.create(
model="claude-haiku-4-5-20251001", # 最快最便宜;高质量用 claude-sonnet-4-6
max_tokens=1024,
system="你是一个严谨的代码审查专家,只指出真正的问题,不废话。",
messages=[
{"role": "user", "content": "帮我审查这段代码:\ndef divide(a, b):\n return a / b"}
]
)
# Claude 的响应结构略有不同
reply = message.content[0].text
print(reply)
# Token 使用情况
print(f"输入 {message.usage.input_tokens},输出 {message.usage.output_tokens} Token")
import anthropic
client = anthropic.Anthropic()
history = [] # Claude 的 system 单独传,history 只含 user/assistant
system = "你是一个资深 Python 工程师,回答时先给结论再解释原因。"
def chat_claude(user_msg: str) -> str:
history.append({"role": "user", "content": user_msg})
resp = client.messages.create(
model="claude-haiku-4-5-20251001",
max_tokens=1024,
system=system,
messages=history
)
reply = resp.content[0].text
history.append({"role": "assistant", "content": reply})
return reply
print(chat_claude("GIL 是什么?"))
print(chat_claude("它在 Python 3.13 里有变化吗?"))
流式输出(Streaming)
等待模型生成完整回复再显示会让用户盯着空白屏幕十几秒。流式输出逐 Token 实时推送,用户体验从"等待"变为"观看"。
from openai import OpenAI
import sys
client = OpenAI()
stream = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "用 200 字介绍 Python 的历史"}],
stream=True # 开启流式
)
full_text = ""
for chunk in stream:
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="", flush=True) # 实时打印,不换行
full_text += delta
print() # 最后换行
print(f"\n共 {len(full_text)} 字")
import anthropic
client = anthropic.Anthropic()
with client.messages.stream(
model="claude-haiku-4-5-20251001",
max_tokens=500,
messages=[{"role": "user", "content": "写一首关于 Python 的五言绝句"}]
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
print()
结构化输出:让模型返回 JSON
实际应用中经常需要模型返回可被代码处理的结构化数据,而不是自然语言。有两种主流方案:Prompt 约束 和 JSON Mode。
import json
from openai import OpenAI
client = OpenAI()
prompt = """
从以下文本中提取信息,以 JSON 格式返回,包含字段:
- name (str): 姓名
- age (int): 年龄
- skills (list[str]): 技能列表
文本:小明今年 28 岁,精通 Python 和 React,还会一些 Docker。
只返回 JSON,不要其他文字。
"""
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
response_format={"type": "json_object"} # JSON Mode:强制输出合法 JSON
)
raw = response.choices[0].message.content
data = json.loads(raw)
print(data["name"]) # 小明
print(data["skills"]) # ['Python', 'React', 'Docker']
实战:命令行聊天机器人
把前面所有知识串起来,构建一个有状态的命令行聊天机器人——完整、可运行、带退出指令。
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()
client = OpenAI()
def run_chatbot():
print("=== Python AI 助手 === (输入 'quit' 退出)\n")
history = [{
"role": "system",
"content": "你是一个专注于 Python 编程的助手。回答简洁、附代码示例,使用中文。"
}]
while True:
try:
user_input = input("\n你: ").strip()
except (KeyboardInterrupt, EOFError):
print("\n再见!")
break
if not user_input:
continue
if user_input.lower() in ("quit", "exit", "退出"):
print("再见!")
break
history.append({"role": "user", "content": user_input})
print("\nAI: ", end="", flush=True)
full_reply = ""
# 流式输出,实时显示
with client.chat.completions.stream(
model="gpt-4o-mini",
messages=history
) as stream:
for chunk in stream:
delta = chunk.choices[0].delta.content if chunk.choices else ""
if delta:
print(delta, end="", flush=True)
full_reply += delta
print()
history.append({"role": "assistant", "content": full_reply})
# 防止 Token 超出上下文限制:只保留最近 20 轮
if len(history) > 41: # 1 system + 20对话×2
history = [history[0]] + history[-40:]
if __name__ == "__main__":
run_chatbot()
实战:批量文本分析
大模型极其擅长的另一类任务:理解和处理非结构化文本——情感分析、摘要、分类、信息提取,全都只需换个 Prompt。
import json
from openai import OpenAI
client = OpenAI()
def analyze_sentiment(texts: list[str]) -> list[dict]:
"""批量分析文本情感,返回 [{text, sentiment, score, reason}, ...]"""
batch = "\n".join(f"{i+1}. {t}" for i, t in enumerate(texts))
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{
"role": "user",
"content": f"""分析以下每条文本的情感,以 JSON 数组返回,每项包含:
sentiment: "positive"/"negative"/"neutral"
score: 0.0~1.0 置信度
reason: 一句话原因
文本:
{batch}
只返回 JSON 数组。"""
}],
response_format={"type": "json_object"}
)
result = json.loads(resp.choices[0].message.content)
# 模型可能把数组包在某个键下,做一下兼容处理
if isinstance(result, dict):
result = next(iter(result.values()))
return result
# 测试
reviews = [
"这个 Python 教程太棒了,学了很多!",
"代码运行报错,文档也没写清楚,很失望。",
"第三章内容还可以,不算特别出色。",
]
for review, result in zip(reviews, analyze_sentiment(reviews)):
print(f"[{result['sentiment']:8s} {result['score']:.2f}] {review[:20]}... → {result['reason']}")
常见误区与最佳实践
硬编码 API Key
client = OpenAI(api_key="sk-proj-xxxx")
密钥一旦提交 Git,即使删除也可能被 git log 找回。
用环境变量
load_dotenv()
client = OpenAI() # 自动读取环境变量
.env 文件加入 .gitignore,生产环境用系统环境变量。
不维护对话历史
# 每次只发当前消息
messages=[{"role":"user","content":user_input}]
模型没有上下文,无法理解"它"、"上面说的"等指代。
追加完整历史
history.append({"role":"user","content":msg})
messages=history # 传入完整历史
每次请求携带完整对话记录,保持上下文连贯。
无限积累对话历史
# history 无限增长
# 最终超出 Token 上限报错
Token 有上限,费用也会线性增长。
滑动窗口截断
if len(history) > 41:
history = [history[0]] + history[-40:]
保留 system prompt + 最近 N 轮对话,控制 Token 消耗。
本章小结
调用大模型 API 的核心:安全管理密钥(环境变量,不硬编码)、理解 Token(计费单位,有上限)、维护对话历史(模型无状态,历史需自行拼接)、流式输出改善体验、JSON Mode 获取结构化数据。实际项目中 OpenAI 和 Claude 的 SDK 接口大同小异,掌握一个即可快速迁移另一个。下一步:结合第 9 章的文件读写,让 AI 分析你的本地文档;或结合第 7 章的 HTTP 请求,构建 API 服务暴露给前端。