Day 11 / 共 68 天 · 阶段 2 大模型基础
调用大模型 API
昨天(Day 10)你搞懂了大模型"预测下一个词"的原理。今天让它真正为你干活——用 openai / anthropic 的 SDK,写出你人生第一段和 AI 对话的代码,搞清 messages 三角色(system/user/assistant)怎么组织一次对话。学完你就能让程序"开口说话"了;明天(Day 12)让它像打字机一样一个字一个字往外蹦。
📍 你在阶段 2(大模型基础 D10-15)的位置
D10 大模型是什么→
D11 调 LLM API→
D12 流式输出→
D13 参数与成本→
D14 结构化输出
💡 用一套类比兜住今天(今天全程沿用「打电话给一位专家顾问」的世界观)
调用大模型 = 打电话给一位住在云端、无所不知的顾问。API = 顾问的电话号码 + 通话规矩;API key = 你的会员卡号(证明你是付费用户、按时长计费);SDK = 帮你自动拨号的快捷拨号器;messages 三角色 = 通话时的三种身份:system=事先给顾问的"岗位说明书"、user=你说的话、assistant=顾问的回话。今天你学会正确地"拨这通电话"。
L01
API 是什么:给程序用的"服务窗口"
🤔 痛点你在网页版 ChatGPT 里能聊天,可那是给人点的。要让你自己的程序用上大模型,网页帮不了你——程序怎么"开口问" AI?
💡 本质API(应用程序接口)就是服务方开的一个"程序专用窗口":你的代码按约定格式递进去一个请求,它按约定格式递回来一个结果。像给云端顾问打电话——号码固定、说话有规矩,说对了就能拿到回答。
👶 和 Day07 的 API 一样吗?一样的原理!Day07 你用
requests 调过普通网络 API。大模型 API 也是"发请求→收 JSON",只是官方额外给了 SDK(封装好的库)让你不用手写那些 HTTP 细节,一行就能问 AI。底层还是你学过的那套。📝 举个例子:一次调用像一通电话
你的程序说(user):"帮我把这句翻成英文:你好世界" → 电话那头的模型想了想 → 回话(assistant):"Hello, world"。整个过程你的代码只管"说什么、听什么",拨号、排队、计费都由 API 和 SDK 打理。
L02
拿 API key & 装 SDK
🤔 痛点打电话得先有号码和会员卡。调大模型前,你得先拿到 API key、装好 SDK——这一步卡住的新手最多。
💡 本质API key 是一串证明"你是谁、按你的账户计费"的会员卡号;SDK 是官方写好的 Python 库,帮你自动完成拨号。拿卡、装库,两步准备。
# 先在你的虚拟环境里装 SDK(回忆 Day05 的 venv)
pip install openai # OpenAI 官方 SDK
pip install anthropic # Anthropic(Claude)官方 SDK
# 两家用法几乎一样,学会一个另一个照葫芦画瓢
# API key 去各家官网的控制台申请,形如 sk-xxxxx(一长串)
# ⚠️ key 是你的会员卡号,泄露=别人花你的钱,绝不能写进代码上传
👶 key 放哪最安全?不要直接写在代码里!存进一个叫
.env 的文件(如 OPENAI_API_KEY=sk-xxx),再把 .env 写进 .gitignore(回忆 Day06),这样它永远不会被上传到 GitHub。程序里用 os.environ 读它——具体做法本日 L06 细讲。L03
messages 三角色:一次对话怎么组织
🤔 痛点你可能以为"问 AI"就是丢一句话过去。但真实 API 要你传一个
messages 列表,里面每条还带个 role——这是干嘛的?💡 本质一次对话由三种身份的消息组成:system=开场前给顾问的"岗位说明书"(你是谁、怎么答)、user=你(用户)说的话、assistant=模型的回话。你按顺序把这些消息装进一个列表递过去。
图注:system 通常只放开头一条定基调;之后 user / assistant 一来一回轮流排列。
👶 小白:system 和 user 都是"我在说话",有啥区别?非写 system 不可吗?
👨🏫 老师:区别在"分量"和"时机"。system 是通话前塞给顾问的长期设定——身份、语气、规矩,整通电话都遵守;user 是当下这句具体问题。不写 system 也能跑(模型用默认人设),但写好 system 能极大稳定输出风格,是后面 Prompt 工程(Day16-18)的重头戏。现在先知道"它管全局设定"就够。
L04
第一段对话代码:真的把电话打通
🤔 痛点准备都做好了,现在最关键:到底怎么写代码把这通电话拨出去、拿回 AI 的回答?
💡 本质三步:造一个客户端(拿起电话)→ 组织 messages(想好说什么)→ 调一次接口并读回答。下面是能直接跑的最小例子,每行都有注释。
from openai import OpenAI # 导入 SDK(回忆 Day05 的 import)
client = OpenAI() # 造一个"电话客户端";它自动读环境变量里的 key
# 组织这次通话的 messages 列表(回忆 L03 的三角色)
resp = client.chat.completions.create(
model="gpt-4o-mini", # 选用哪个模型(相当于"接哪位顾问")
messages=[
{"role": "system", "content": "你是一位简洁的中文助手"},
{"role": "user", "content": "用一句话解释什么是 API"},
],
)
# 回答藏在返回结果里,一层层取出来(这是固定写法,照抄)
print(resp.choices[0].message.content)
# → API 就是让不同程序按约定互相调用功能的接口。
👶 Claude 版几乎一样换 Anthropic SDK 只需微调:
from anthropic import Anthropic → client = Anthropic() → 用 client.messages.create(model="claude-...", max_tokens=500, messages=[...]),取回答用 resp.content[0].text。三角色、messages 列表的思路完全通用,学会一家等于都会。📝 举个例子:
choices[0].message.content 为啥这么长?
模型一次可以生成多个候选回答(choices),默认给 1 个,所以取第 [0] 个;它的 message 里有 role 和 content,我们要的正文在 content。记不住没关系,这是固定套路,用几次就形成肌肉记忆。L05
多轮对话:让顾问"记得"上文
🤔 痛点你问"1+1 等于几?"它答 2;再问"那再加 3 呢?"它却懵了——因为 API 每次调用都是一通全新的电话,模型不记得上一通说了啥。怎么让它记住上文?
💡 本质模型没有记忆,"记住上文"这件事得你自己来做:把之前的每一句(包括模型的回答)都塞回 messages 列表里,一起再发一次。像每次打电话都把之前的通话记录重新念一遍给顾问听。
history = [ # 用一个列表当"通话记录本"
{"role": "system", "content": "你是数学助教"},
]
def ask(question):
history.append({"role": "user", "content": question}) # 把新问题记进本子
resp = client.chat.completions.create(model="gpt-4o-mini", messages=history)
answer = resp.choices[0].message.content
history.append({"role": "assistant", "content": answer}) # 把回答也记进本子
return answer
print(ask("1 加 1 等于几?")) # → 2
print(ask("那再加 3 呢?")) # → 5(这次它"记得"前面是 2,因为历史都在 messages 里)
👶 关键领悟所谓"AI 有记忆",本质是程序每次把历史重新喂进去。这也解释了为什么聊太久会变慢变贵——历史越长,每次要发的内容越多。怎么聪明地管理这个历史,正是 Day18「上下文工程」要解决的核心问题。
L06
密钥安全 & 常见报错
🤔 痛点新手第一次调 API,八成会栽在两件事上:key 该怎么安全地读进程序?跑起来报错了怎么看懂?
💡 本质key 存进
.env 文件、用代码从环境变量读,绝不硬写进代码;报错则用 try/except(回忆 Day05)兜住,看懂常见几类就能自救。# 安全读 key:先 pip install python-dotenv
from dotenv import load_dotenv
import os
load_dotenv() # 自动读取项目里的 .env 文件
key = os.environ["OPENAI_API_KEY"] # 从环境变量取出 key(代码里看不到明文)
# OpenAI() 其实会自动读这个环境变量,所以通常你连上面两行显式取都不用写
# 用 try/except 兜住网络/额度类报错,别让程序直接崩
try:
resp = client.chat.completions.create(model="gpt-4o-mini",
messages=[{"role": "user", "content": "你好"}])
print(resp.choices[0].message.content)
except Exception as e: # 出任何错都接住,打印出来看
print("调用失败:", e)
| 报错关键词 | 大概率原因 | 怎么办 |
|---|---|---|
| AuthenticationError / 401 | key 错了或没读到 | 检查 .env 里 key 是否正确、有没 load_dotenv() |
| RateLimit / 429 | 请求太频繁或余额/额度不足 | 放慢频率、去控制台看余额 |
| Connection / Timeout | 网络不通 | 检查网络/代理,加重试 |
| model not found | 模型名拼错或无权限 | 核对官网的模型名字符串 |
📝 举个例子:最常见的翻车
90% 的新手第一次报
401,都是因为:key 复制时多了空格、或者 .env 文件名写成了 env.txt、或者忘了 load_dotenv()。遇到 401 别慌,先把这三处逐一排查。L07
今日小结 + 动手 10 分钟
🧠 今天你应该能回答
- API、API key、SDK 分别是什么?(号码 / 会员卡 / 快捷拨号器)
- messages 里 system / user / assistant 三个角色各管什么?
- 写一次最简单调用的三步是啥?(建客户端 → 组 messages → create)
- 模型本身没记忆,多轮对话靠什么实现?
- key 应该怎么安全存放?遇到 401 先查哪三处?
✋ 动手 10 分钟:做一个能连续聊天的命令行机器人
先建好环境、写好 .env:
mkdir chat-demo && cd chat-demo
python -m venv .venv && source .venv/bin/activate # 建并进车间
pip install openai python-dotenv
echo "OPENAI_API_KEY=sk-你的key" > .env
echo -e ".env\n.venv" > .gitignore # 别把 key 和车间上传
新建 chat.py,把"多轮对话"串成一个能一直聊的小机器人:
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()
client = OpenAI()
history = [{"role": "system", "content": "你是友好的中文助手,回答简洁"}]
print("开始聊天吧(输入 quit 退出)")
while True: # 一直循环,实现连续对话
q = input("你:")
if q == "quit":
break
history.append({"role": "user", "content": q})
resp = client.chat.completions.create(model="gpt-4o-mini", messages=history)
a = resp.choices[0].message.content
history.append({"role": "assistant", "content": a}) # 记住回答,下轮带上
print("AI:", a)
明日预告 · Day 12:今天 AI 的回答是"等它全想完才一次性蹦出来",长回答要干等好几秒,体验很差。明天学 流式输出(streaming):加一个
stream=True,就能像 ChatGPT 那样让文字一个字一个字往外冒(打字机效果)。你会搞懂背后的 SSE 逐块传输、怎么逐块拼接——这是所有像样 AI 应用的标配体验。