大模型 API 初级实践:从一次调用到完整对话
大模型 API 初级实践:从一次调用到完整对话
如果你准备学习 大模型 API,最容易遇到的问题,其实往往不是“代码完全写不出来”,而是只照着某个平台的示例跑通了一次,却没有真正搞明白它背后的通用逻辑。结果一换平台,或者模型名稍微变一下,就不知道该从哪里改起了。
所以这篇文章不会绑定某一家厂商,而是按照现在比较常见的 OpenAI 兼容接口 来讲。我们会从最简单的一次 API 调用开始,一步步做出一个可以连续聊天的命令行助手。看完之后,你大概能搞清楚这些事:
- 大模型 API 调用时,程序和模型服务之间到底发生了什么;
API Key、Base URL、model、messages这些字段分别代表什么;- 单次调用和多轮对话,本质上差在哪里;
- 怎么写一个最小可运行的 Python Demo;
- 上下文、参数、错误码和成本问题该怎么处理。
先搞懂:大模型 API 调用到底发生了什么?
可以先把大模型 API 理解成这样:你的程序通过 HTTP 请求,把用户输入发给模型服务;模型处理完之后,再把生成的文本结果返回给你的程序。
一个常见流程大概是:
用户输入
↓
你的程序
↓
发送 API 请求:里面带上 API Key、模型名、messages 等参数
↓
大模型服务
↓
返回 API 响应:里面包含模型回复、消耗信息等
↓
你的程序解析结果,然后展示给用户
对初学者来说,先把下面这四个概念搞明白,后面会顺很多。
1. API Key:调用权限凭证
API Key 用来证明你有权限调用某个平台的模型服务。它有点像密码,所以千万不要直接写死在代码里,也不要提交到 GitHub,更不能放到前端页面中。
比较稳妥的做法,是把它放在环境变量里,或者放到后端的配置文件中统一管理。
2. Base URL:请求发往哪里
Base URL 就是 API 请求的基础地址。不同平台的地址不一样,不过只要它支持 OpenAI 兼容接口,代码结构通常都差不多。
换平台时,最常改的其实就是这几个地方:
base_urlapi_keymodel
3. model:调用哪个模型
model 用来指定你要调用的具体大模型。不同平台的模型名称不一样,不能随便填。模型名写错了,常见结果就是 404、400,或者提示“模型不可用”。
4. messages:对话内容
在聊天类 API 里,messages 是非常关键的字段。它通常是一个数组,每一条消息里都有角色和内容,比如:
{
"role": "user",
"content": "你好,请介绍一下你自己"
}
常见的 role 一般有三种:
system:用来设定助手身份、规则和输出风格;user:用户输入的内容;assistant:模型之前回复过的内容。
这里有一点很重要:大模型 API 通常是无状态的。也就是说,模型不会自动记住你上一次说过什么。所谓多轮对话,其实是你的程序把历史消息一起发给模型,它才看起来“记得上下文”。
准备工作:选择平台、创建 API Key、配置环境变量
在真正调用大模型 API 之前,通常要先准备三件事:
第一,选择一个支持 API 调用的平台;第二,创建自己的 API Key;另外,还要在本地配置好环境变量。
如果你是新手,建议优先选择这类平台:
- 文档写得比较清楚;
- 支持 OpenAI 兼容接口;
- 有明确的模型列表;
- 国内访问比较稳定,或者网络环境要求比较明确;
- 额度、余额和限流规则说得清楚。
不同平台可能还会涉及实名认证、余额充值、模型权限开通、区域限制等要求,这些都要以平台最新文档为准。
配置环境变量
以 Python 项目为例,可以用 .env 文件来保存配置。
在项目目录下新建一个 .env 文件:
LLM_API_KEY=你的API_KEY
LLM_BASE_URL=https://你的平台兼容接口地址/v1
LLM_MODEL=你的模型名称
需要注意:
.env不要提交到 Git;- 生产环境更建议使用服务器环境变量,或者专门的密钥管理服务;
- 不要把 API Key 暴露在浏览器端代码里。
第一次调用:用最少代码让大模型回复一句话
下面是一个最小可运行的 API 调用教程 示例。这里用的是 OpenAI Python SDK 的兼容写法,很多支持 OpenAI 兼容接口的平台都可以按这个思路来。具体的 base_url 和 model,还是要看你所用平台的文档。
安装依赖
pip install openai python-dotenv
最小调用 Demo
新建 quick_start.py:
import os
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
client = OpenAI(
api_key=os.getenv("LLM_API_KEY"),
base_url=os.getenv("LLM_BASE_URL")
)
response = client.chat.completions.create(
model=os.getenv("LLM_MODEL"),
messages=[
{"role": "user", "content": "你好,请用一句话介绍大模型 API 是什么。"}
],
temperature=0.7,
max_tokens=300
)
print(response.choices[0].message.content)
运行:
python quick_start.py
如果配置没有问题,你就能看到模型返回的一段文字。
关键字段解释
这段代码里,最关键的是这一行:
response = client.chat.completions.create(...)
它的意思是:发起一次聊天补全请求。
请求参数里比较重要的有:
model:指定要调用哪个模型;messages:传给模型的对话内容;temperature:控制回答的随机性;max_tokens:限制模型最多输出多少 token。
读取响应时,常见写法是:
response.choices[0].message.content
也就是说,从模型返回的候选结果里取第一个,然后读取其中的文本内容。不同平台的响应字段可能会有一点差异,但如果是 OpenAI 兼容接口,整体结构通常差不多。
理解 messages:为什么它决定了对话上下文?
很多人第一次做 大模型对话实现 时都会疑惑:为什么第二轮提问时,模型好像不记得上一轮说过什么?
原因其实很简单:你没有把上一轮对话一起传过去。
单轮调用
messages = [
{"role": "user", "content": "请记住,我叫小明。"}
]
这一次请求里,模型知道你叫小明。但如果下一次你只发送:
messages = [
{"role": "user", "content": "我叫什么?"}
]
模型通常是答不上来的,因为它并没有收到前面的历史内容。
带历史的多轮调用
正确做法是,把历史消息一起传给模型:
messages = [
{"role": "user", "content": "请记住,我叫小明。"},
{"role": "assistant", "content": "好的,我记住了,你叫小明。"},
{"role": "user", "content": "我叫什么?"}
]
这样模型才能根据上下文回答问题。
加入 system prompt
system 一般用来定义助手的行为,比如:
messages = [
{"role": "system", "content": "你是一个耐心的 Python 编程助教,回答要简洁、准确。"},
{"role": "user", "content": "什么是列表推导式?"}
]
通常建议把 system 放在对话最前面,这样更容易稳定模型的角色和回答风格。
实现多轮对话:把一次调用改造成命令行聊天助手
接下来,我们把刚才的单次调用,改造成一个简单的命令行聊天程序。
新建 chat_cli.py:
import os
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
client = OpenAI(
api_key=os.getenv("LLM_API_KEY"),
base_url=os.getenv("LLM_BASE_URL")
)
MODEL = os.getenv("LLM_MODEL")
messages = [
{
"role": "system",
"content": "你是一个中文 AI 助手,回答要清晰、简洁,必要时给出步骤。"
}
]
def trim_history(messages, max_rounds=10):
system_messages = [m for m in messages if m["role"] == "system"]
other_messages = [m for m in messages if m["role"] != "system"]
# 一轮通常包含 user + assistant 两条消息
keep_messages = other_messages[-max_rounds * 2:]
return system_messages + keep_messages
print("命令行大模型助手已启动,输入 exit 退出。")
while True:
user_input = input("\n你:").strip()
if user_input.lower() in ["exit", "quit"]:
print("助手:再见!")
break
if not user_input:
continue
messages.append({
"role": "user",
"content": user_input
})
messages = trim_history(messages, max_rounds=10)
try:
response = client.chat.completions.create(
model=MODEL,
messages=messages,
temperature=0.7,
max_tokens=800,
timeout=60
)
answer = response.choices[0].message.content
print(f"助手:{answer}")
messages.append({
"role": "assistant",
"content": answer
})
except Exception as e:
print(f"助手:调用失败,请检查网络、API Key、模型名或平台状态。错误信息:{e}")
这个 Demo 已经跑通了一个最小的工程闭环:
它会先读取用户输入,然后把用户消息追加到 messages 中;接着调用大模型 API,拿到回复后打印出来;再把这次模型回复作为 assistant 消息放回历史里。下一轮请求时,程序会继续带上这些历史内容,于是上下文就能延续下去。输入 exit 可以退出程序,同时它只保留最近 10 轮对话,避免历史无限增长。
这就是多轮对话最核心的逻辑。
让对话更稳定:参数、上下文和异常处理
Demo 能跑通只是第一步。真正在项目里使用时,还要考虑参数设置、调用成本、上下文长度,以及各种异常情况。
temperature 怎么设?
temperature 控制的是输出的随机性。
不同场景可以大致这样设置:
| 场景 | 建议值 |
|---|---|
| 代码生成、事实问答、格式化输出 | 0.1 - 0.3 |
| 普通聊天、解释概念 | 0.5 - 0.7 |
| 文案创作、头脑风暴 | 0.7 - 1.0 |
新手可以先从 0.7 开始。如果你发现回答太发散,或者希望结果更稳定,就把它调低一些。
max_tokens 怎么设?
max_tokens 控制模型最多能输出多长。它不只影响回答长度,也会影响费用和响应时间。
一般可以这样理解:
- 简短问答:200 - 500;
- 普通解释:800 - 1500;
- 长文生成:要结合平台的上下文限制谨慎设置。
这里要注意,token 不等于字数。输入的历史内容和模型输出,通常都会计入消耗。
stream 什么时候开?
stream=True 表示开启流式输出。它不一定会让总耗时变短,但可以更快看到第一个字,用户体验会更好,尤其适合聊天机器人、前端页面、客服助手这类场景。
刚开始学习 API 调用时,建议先不要开流式。等普通请求跑通了,再加流式输出会更稳。
多轮对话不要无限追加历史
历史消息越长,问题也越明显:
- 请求会越来越慢;
- 调用费用会增加;
- 更容易超过上下文长度;
- 无关信息还可能干扰模型回答。
比较简单的做法,是只保留最近 N 轮,比如最近 10 轮。更进一步的方案,是把早期对话压缩成摘要,再作为长期记忆传给模型。
不同平台怎么迁移?通常只改这三处
如果目标平台支持 OpenAI 兼容接口,一般不需要把代码全部重写。
| 迁移项 | 需要改什么 | 注意事项 |
|---|---|---|
base_url | 换成目标平台的兼容接口地址 | 注意是否需要 /v1 |
api_key | 换成目标平台的 Key | 不同平台可能有权限、实名、余额要求 |
model | 换成平台支持的模型名 | 模型名写错是很常见的问题 |
换句话说,学习大模型 API 时,不要只记住“某个平台按钮怎么点”。更重要的是理解这套通用结构:
API Key + Base URL + model + messages + response
把这个结构掌握了,以后迁移到不同的大模型平台,就会轻松很多。
常见问题:为什么我调用失败?
下面这张表整理了新手最常遇到的问题,可以先按这个方向排查。
| 问题或错误 | 常见原因 | 处理建议 |
|---|---|---|
401 Unauthorized | API Key 错误、未配置、环境变量未生效 | 检查 Key 是否正确,确认 .env 已加载 |
403 Forbidden | 无模型权限、未实名、区域限制、账号状态异常 | 查看平台控制台和权限说明 |
404 Not Found | Base URL 错误、路径错误、模型名不存在 | 核对接口地址和模型列表 |
429 Too Many Requests | 请求过快、限流、余额不足 | 降低请求频率,检查额度和限流规则 |
500/502/503 | 服务端异常或临时不可用 | 稍后重试,增加重试机制 |
| timeout | 网络慢、模型响应慢、输出过长 | 设置超时时间,减少 max_tokens |
| 第二轮不记得上一轮 | 没有传历史 messages | 把 user 和 assistant 历史一起传入 |
| 输出被截断 | max_tokens 太小或上下文限制 | 提高输出限制,缩短输入历史 |
| 本地能跑,服务器跑不了 | 环境变量缺失、网络不可达、防火墙限制 | 检查服务器环境和网络出口 |
如果准备上线,至少建议做到这些:
- API Key 不要写死在代码里;
- 日志里不要打印敏感 Key;
- 设置合理的超时时间;
- 对异常情况做处理;
- 限制用户输入长度;
- 控制
max_tokens; - 做基础限流;
- 给账户设置费用提醒或额度控制;
- 对用户隐私和敏感信息做脱敏处理。
小结:从 Demo 到真实应用,还需要补什么?
到这里,我们已经完成了一个初级但完整的闭环:从第一次 大模型 API 调用,到理解 messages,再到做出一个可以连续对话的命令行助手。
现在你应该已经明白:
- 大模型 API 本质上就是一次请求和一次响应;
- 多轮对话不是模型自动记忆,而是调用方自己维护历史;
system、user、assistant会共同决定上下文;- 换平台时,通常主要改
base_url、api_key和model; - 一个真正可用的对话程序,必须考虑异常、成本、上下文和安全问题。
如果后面想继续往真实应用发展,还可以补上会话存储、用户身份、前端流式渲染、日志脱敏、内容安全、知识库检索、函数调用等能力。不过无论应用做得多复杂,底层逻辑其实都离不开这套基础流程:构造消息、调用 API、解析响应、维护上下文。
更多推荐


所有评论(0)