刚开始接大模型 API 时,真正卡住人的,往往不是“请求能不能发出去”。更常见的问题是:请求发出去了,但不知道参数该怎么配,也不知道模型为什么不记得上一轮对话,更不知道返回的 JSON 里哪一段才是真正的答案。比如,temperature 到底设多少合适?max_tokens 是不是上下文长度?流式返回为什么要一段一段拼?
这篇文章主要写给刚入门的开发者,会以常见的 OpenAI 兼容 Chat Completions 接口为例,把一次大模型 API 调用从请求到返回的过程讲清楚。需要注意的是,不同厂商可能还有 Responses、Messages、GenerateContent 等接口,字段名和支持能力不一定完全一样。所以真正落地时,还是要回到对应平台的官方文档去核对。
先搞清楚:一次大模型 API 调用到底发生了什么
简单说,一次大模型 API 调用,就是你的应用把一段 JSON 请求发给模型服务。模型服务会根据你传入的模型名、消息内容和生成参数,生成一段 JSON 响应。如果开启了流式模式,它不会一次性返回完整内容,而是分成多个 chunk 持续推回来。
一般流程大概是这样:
第一,应用拿到用户输入。然后,服务端组装请求体,里面通常会有 model、messages 以及各种生成参数。接下来,用 api_key 调用某个 base_url 下的接口。模型处理完之后返回响应体,应用再从 choices[0].message.content 里取出回答;如果是流式输出,就要从每个 chunk 的 delta.content 里不断拼接内容。最后,最好顺手记录一下 token 用量、错误码和请求日志,方便后续排查问题。
这里有几个概念很容易混在一起:
base_url:模型服务的基础地址,一般不是完整接口路径;- endpoint:具体接口地址,比如
/v1/chat/completions; api_key:认证用的密钥,应该只放在服务端或安全的环境变量里;model:你要调用的模型名称,必须和平台支持的名称一致;- 请求体:你发给模型的 JSON;
- 响应体:模型成功返回的 JSON;
- 错误体:认证失败、参数错误、限流等情况下返回的信息。
OpenAI 兼容接口之所以常见,是因为很多模型平台都做了类似格式,开发者迁移起来比较方便。不过,“兼容”不代表每个参数都一模一样。比如 response_format、tools、stream_options、usage 的返回方式,在不同平台上都可能有细微差别。
最小可运行示例:用 20 行左右代码完成第一次调用
下面是一个 Python 示例,使用 OpenAI 兼容 SDK 调用大模型 API:
from openai import OpenAI
import os
client = OpenAI(
api_key=os.getenv("LLM_API_KEY"),
base_url="https://api.example.com/v1"
)
response = client.chat.completions.create(
model="your-model-name",
messages=[
{"role": "system", "content": "你是一个严谨的中文技术助手。"},
{"role": "user", "content": "用三句话解释什么是大模型 API。"}
],
temperature=0.3,
max_tokens=500
)
print(response.choices[0].message.content)
这里几个字段尤其要看懂:
api_key:不要直接写死在代码里,更不要放到前端页面;base_url:通常填基础路径,比如https://api.example.com/v1,不要误写成完整的/v1/chat/completions;model:填平台支持的模型名,名字写错时常见表现是 400 或 404;messages:传递对话内容,里面可以包含系统提示、用户问题和历史回复;temperature:控制回答的随机性,数值越高越发散;max_tokens:限制最大输出长度,它不是模型的总上下文窗口。
如果你习惯用 curl,请求结构大致是这样:
curl https://api.example.com/v1/chat/completions \
-H "Authorization: Bearer $LLM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "your-model-name",
"messages": [
{"role": "system", "content": "你是一个严谨的中文技术助手。"},
{"role": "user", "content": "解释大模型 API 参数的作用。"}
],
"temperature": 0.3,
"max_tokens": 500
}'
如果你用的是 Claude 原生 Messages、Gemini GenerateContent,或者国内云厂商的接口,就要重点确认 endpoint、消息格式和认证方式。若使用 ClaudeAPI 这类第三方 Claude API 兼容接入服务,也要先明确一点:它不是 Anthropic 官方服务,具体支持哪些模型、额度怎么计算、费用是多少、稳定性如何,都要以平台最新说明为准。
大模型 API 参数怎么理解:新手先掌握这 8 个
1. model:决定调用哪个模型
model 决定这次请求由哪个模型来处理。新手不要凭记忆手写模型名,最好直接从平台控制台或官方文档复制。模型名写错、模型没开通、当前区域不支持,都可能导致请求失败。
比较稳妥的做法是:先用平台推荐的通用文本模型把流程跑通。确认调用没问题之后,再根据任务切到代码模型、长上下文模型、多模态模型,或者成本更低的模型。
2. messages:把对话内容传给模型
在 Chat Completions 里,messages 可以说是最核心的字段。它通常包含三类角色:
system:用来设定模型行为和约束;user:用户输入的内容;assistant:模型之前的回复。
做多轮对话时,不能只传最新的问题。你需要把必要的历史消息一起传进去,因为大多数 API 本身并不会自动记住上一轮对话。换句话说,你这次传了什么,模型这次就只能看到什么。
3. temperature:控制回答稳定还是发散
temperature 用来控制生成结果的随机性。如果是事实问答、代码生成、JSON 抽取,一般建议设低一点,比如 0 到 0.5。这样回答更稳定,也更容易复现。如果是创意写作、起标题、头脑风暴,就可以适当调高。
对新手来说,生产环境里先用低温度更保险。不要一开始就追求“更有创造力”,因为创造力变强的同时,不稳定性也会增加。
4. top_p:另一种采样控制方式
top_p 也是影响随机性的参数。它和 temperature 都会改变模型生成文本时的选择范围。初学阶段不建议同时大幅调整两者,不然出了问题很难判断到底是哪一个参数造成的。
更简单的策略是:优先调 temperature。除非你确实理解采样策略的影响,否则 top_p 可以先保持默认。
5. max_tokens:限制模型最多输出多少
max_tokens,或者某些接口里的 max_completion_tokens,控制的是模型最多生成多少 token。它不是总上下文长度,也不能用来扩大模型窗口。
如果这个值设得太小,模型可能话还没说完就停了,返回里的 finish_reason 可能会是 length。如果设得太大,则可能增加成本和等待时间。所以它不是越大越好,而是要按任务需要来设。
6. stream:是否边生成边返回
当 stream=false 时,接口会等完整答案生成后一次性返回。当 stream=true 时,模型会边生成边推送内容,用户就能更早看到回复。
新手建议先用非流式把业务逻辑跑通。等你确认参数、上下文和返回解析都没问题后,再接入流式输出。这样排查问题会轻松很多。
7. stop:让模型在指定位置停止
stop 用来设置停止词。比如你希望模型生成到某个分隔符就停下来,可以使用这个参数。它在模板化输出里比较有用。
不过要小心,如果停止词设计得不合理,模型可能提前停掉,导致答案被截断。所以用之前最好多测几组输入。
8. response_format:要求模型输出 JSON
有些接口支持 response_format,可以要求模型返回 JSON。这在信息抽取、结构化表单、自动化流程里非常常见。
但别因为开了 JSON 模式就完全放心。实际开发中,代码里仍然要做 JSON 解析、字段校验和异常处理。模型输出不一定百分百符合你的业务 schema,而且不同平台对这个参数的支持也不完全一致。
上下文管理:为什么模型“不记得上一轮对话”
上下文管理是大模型 API 开发里非常关键的一块。很多初学者以为模型天然会记住一个会话,其实大多数 Chat Completions 接口都是无状态的。也就是说,每次调用时你传进去什么内容,模型就只能基于这些内容回答。
上下文通常会包括这些东西:
system提示词;- 当前用户问题;
- 历史
user和assistant消息; - 工具调用结果;
- 检索到的文档片段;
- 模型即将生成的输出空间。
这些内容都会消耗 token。上下文太长会带来不少问题:成本上升、延迟变高、超过窗口后请求失败,甚至重要信息被大量无关内容冲淡。长上下文模型确实能缓解窗口限制,但这并不意味着应该把所有东西都塞进去。
一个比较实用的原则是:把当前问题放在上下文靠后的位置,把重要约束放在清晰、显眼的位置,不要让模型在一大堆无关历史里自己找关键指令。
四种常见的上下文管理方式
1. 短对话:只保留最近 N 轮
这种方式适合客服、普通聊天、表单辅助等场景。做法很简单:只保留最近几轮 user 和 assistant 消息。
它的优点是实现简单,成本也比较可控。缺点也明显,早期信息可能会被丢掉。
messages = [system_message] + history[-6:] + [current_user_message]
2. 长对话:把旧消息压缩成摘要
如果是咨询、写作、教学这类长会话,就可以把更早的对话压缩成一段摘要,再和最近几轮原文一起传入。这样既能保留长期信息,又不会让上下文无限膨胀。
消息结构可以像这样:
[ {"role": "system", "content": "你是一个写作助手。"}, {"role": "assistant", "content": "历史摘要:用户正在写一篇关于 API 上下文管理的教程,偏好简洁示例。"}, {"role": "user", "content": "继续写返回格式解析部分。"}]
这种方式效果通常不错,但摘要质量很关键。如果摘要漏掉了重要信息,后面的回答也会受到影响。
3. 固定信息:放进 system prompt 或用户画像
业务规则、角色设定、输出格式要求,比较适合放在 system 里。用户偏好、账号信息、历史配置,则更适合存在数据库中,需要时再取出来拼进上下文。
不建议把大量动态数据长期塞进 system。这样不仅成本高,而且后期维护也会很麻烦。
4. 知识库问答:用 RAG 或长上下文
文档问答、合同分析、企业知识库这类场景,通常不适合把全部文档直接塞进请求。更常见的做法是先检索相关片段,再把这些片段和用户问题一起交给模型,这就是常说的 RAG。
长上下文适合一次性分析完整材料,但也要权衡成本、延迟和准确率。能放进去,不代表就一定应该全部放进去。
返回格式怎么看:从 JSON 里找到真正答案
非流式响应通常长这样:
{
"id": "chatcmpl_xxx",
"object": "chat.completion",
"created": 1710000000,
"model": "your-model-name",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "这里是模型生成的回答。"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 120,
"completion_tokens": 80,
"total_tokens": 200
}
}
新手最常用的取值方式是:
answer = response.choices[0].message.content
这里有几个字段值得重点关注:
choices:候选结果列表,通常取第一个;message.content:模型真正生成的文本;finish_reason:本次生成结束的原因;usage.prompt_tokens:输入消耗的 token;usage.completion_tokens:输出消耗的 token;usage.total_tokens:总 token 消耗。
finish_reason 常见含义如下:
stop:正常结束;length:达到最大输出长度,可能还没说完;tool_calls:模型请求调用工具;content_filter:可能被安全策略截断。
还有一点很重要:接口返回成功,不代表结果就一定能直接用。生产环境里,应该对模型输出做格式校验、敏感内容检查和业务规则校验。尤其是 JSON 抽取、代码生成、自动化执行这些场景,更不能直接相信模型输出。
流式返回格式:为什么页面能一个字一个字显示
当设置 stream=true 时,服务端不会等完整回答生成完再返回,而是不断推送多个 chunk。内容通常会出现在类似这样的结构里:
{
"choices": [
{
"delta": {
"content": "你"
}
}
]
}
应用要做的事情,就是把每个 chunk 里的 choices[0].delta.content 取出来,然后一点点拼成完整答案。
流式输出很适合聊天产品,因为用户不用等完整回答生成完,就能先看到开头内容。不过它也会带来额外复杂度:连接可能中断,最后的 usage 可能需要额外配置才会返回,前端和服务端也都要处理增量文本。如果只是后台批处理任务,非流式往往更简单、更省心。
常见错误与排查清单
| 错误现象 | 常见原因 | 排查方法 | 修复建议 |
|---|---|---|---|
| 401 Unauthorized | API Key 错误、过期或没传 | 检查环境变量和请求头 | 重新生成 Key,确认 Authorization 格式 |
| 400 Bad Request | 参数格式错误、字段不支持 | 查看错误体里的 message | 对照平台文档修正请求体 |
| 上下文超限 | 历史消息或文档太长 | 查看 token 用量和上下文窗口 | 截断历史、摘要旧消息、使用 RAG |
| 模型名不存在 | model 写错或未开通 | 在控制台核对模型名 | 使用平台支持的模型名称 |
base_url 写错 | 把 endpoint 当成 base URL | 打印最终请求地址 | base_url 只写基础路径 |
| 429 Too Many Requests | 限流、并发过高、额度不足 | 查看平台额度和速率限制 | 降低并发、排队重试、补充额度 |
| 503 Service Unavailable | 服务暂不可用或上游异常 | 记录请求 ID 和时间 | 设置退避重试,必要时切换模型或线路 |
| JSON 输出不合法 | 提示词不清晰或模型偏离格式 | 捕获 JSON 解析异常 | 使用 JSON 模式并做 schema 校验 |
| 流式解析失败 | chunk 解析逻辑有问题 | 打印原始流数据 | 按 delta.content 增量拼接 |
新手推荐参数配置模板
稳定问答:
{
"temperature": 0.2,
"max_tokens": 800,
"stream": false
}
适合知识解释、事实问答、客服回复。重点是稳定、简洁、可控。
创意写作:
{
"temperature": 0.8,
"max_tokens": 1500
}
适合标题、文案、故事和头脑风暴。不过要接受输出会有波动,最好配合人工筛选。
代码生成:
{
"temperature": 0.2,
"max_tokens": 1200
}
适合生成函数、SQL、脚本。提示词里最好明确语言、输入输出、边界条件和期望格式。
JSON 抽取:
{
"temperature": 0,
"response_format": {"type": "json_object"}
}
适合信息抽取、表单填充、结构化处理。程序里必须做 JSON 解析和字段校验,不能只依赖模型自觉。
多轮客服:
{
"temperature": 0.3,
"max_tokens": 800,
"stream": true
}
上下文策略建议使用“最近 N 轮 + 历史摘要 + 必要用户信息”。不要把全部聊天记录无限追加进去,这样成本和效果都会越来越难控制。
生产环境需要注意什么
大模型 API 示例跑通之后,下一步不应该是马上上线,而是先把稳定性和安全边界补齐。这个环节很容易被忽略,但它决定了系统能不能长期稳定运行。
至少要做到这些:
- API Key 不写进前端,也不提交到代码仓库;
- 服务端设置超时、重试和限流;
- 记录请求 ID、模型名、错误码和 token 用量;
- 对用户输入设置长度限制;
- 对模型输出做格式校验;
- 对 429、503 使用退避重试,不要无限重试;
- 给上下文长度和
max_tokens设置预算; - 避免把敏感信息不受控制地传给第三方模型服务。
如果使用第三方兼容接入平台,比如 ClaudeAPI,要把它理解成兼容接入服务,而不是官方服务。它可能在兼容接入、多线路选择、中文支持、企业充值、开票和基础技术协助等方面更方便,但具体能力、费用和限制,仍然要以官网最新说明为准。
总结:初学者调用大模型 API 的检查表
开发大模型 API,不能只背参数定义,更重要的是建立完整调用链路。一次可靠的调用,至少要确认这些问题:
api_key是否安全存放;base_url和 endpoint 是否正确;model是否真实存在并且已经开通;messages是否包含必要上下文;temperature、top_p、max_tokens是否符合任务需求;- 是否区分了流式和非流式返回;
- 是否正确读取
choices[0].message.content; - 是否检查了
finish_reason; - 是否记录
usage来估算成本; - 是否处理 400、401、429、503 等错误;
- 是否对 JSON 输出做校验;
- 是否通过截断、摘要或 RAG 控制上下文成本。
对初级开发者来说,真正掌握大模型 API,不只是知道有哪些参数。更重要的是能根据业务目标选择合适参数,能用合理的上下文管理控制成本和效果,也能从返回格式中准确取出、校验并使用模型结果。