LLM API 入门
调用成功不等于接入完成。AI Engineer 要能证明:请求发给了哪个模型、返回是否符合 schema、失败是否被正确分类、敏感数据是否进入日志,以及换供应商时哪些行为会改变。
1. 先分清产品订阅与 API 权限
ChatGPT、Claude 等产品订阅和开发者 API 是两套权限与计费体系。开始前记录以下信息,不把网页端能聊天当作 API 已开通:
| 字段 | 必须记录的证据 |
|---|---|
| Provider | 实际供应商与接入区域 |
| Model ID | 控制台或官方模型目录中的精确 ID |
| API endpoint / SDK | 实际使用的端点与 SDK 版本 |
| Access | 账号、组织、项目是否有权限 |
| Budget | 配额、限流和允许的最大测试成本 |
| Checked at | 核验日期;模型目录会变化 |
当期课堂可以用 gpt-6-astra、claude-fable-5-1 或账号内其他已验证模型。无法访问就标记 unavailable,不要伪造成功,也不要静默切换供应商。
2. 最小请求:先验证连接,不先堆 Prompt
OpenAI 的新工程示例使用 Responses API。模型 ID 从环境配置读取,不写死在业务逻辑里:
import os
import time
from openai import OpenAI
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
model_id = os.environ["OPENAI_MODEL_ID"]
started = time.perf_counter()
response = client.responses.create(
model=model_id,
input="Return exactly: connection-ok",
)
print(response.output_text)
print({
"provider": "openai",
"model": model_id,
"request_id": getattr(response, "_request_id", None),
"latency_ms": round((time.perf_counter() - started) * 1000),
})
第一次只检查四件事:凭证有效、模型可访问、响应可解析、请求 ID 与延迟可记录。不要同时加入 streaming、tools、长上下文和复杂 schema,否则失败时无法定位变量。
3. Structured Output:JSON 能解析还不够
生产系统需要业务 schema,而不是“请返回 JSON”这句话。以护理记录草稿为例:
{
"resident_id": "R-1024",
"summary": "Resident reported mild dizziness after standing.",
"risk_level": "review",
"requires_human_confirmation": true
}
应用侧仍需验证:必填字段和枚举、资源权限、refusal 与 validation failure,以及原始输入到结构化草稿的 lineage。Structured Outputs 约束形状,不保证事实正确;risk_level 仍需业务规则和人工确认。
4. Tool Calling:模型提出调用,应用执行动作
- 应用发送 tool name、input schema、用途与副作用说明。
- 模型返回 tool call 与 arguments。
- 应用校验身份、权限、参数和资源范围。
- 应用执行工具,并把结果绑定原 call ID 返回。
- 模型基于工具结果生成输出;应用保存 trace。
模型不能直接获得数据库权限。写入、发送、删除等有副作用的工具还要定义 idempotency、human approval 与失败补偿。
5. 错误分类:不是所有失败都应该重试
| 类型 | 典型原因 | 处理 |
|---|---|---|
| Authentication / Permission | Key 错误、无权访问模型 | 停止;修复配置,不重试 |
| Validation | 参数或 schema 不受支持 | 停止;按该模型契约修请求 |
| Rate limit | RPM/TPM/并发超限 | 读取限流信息,带抖动退避 |
| Timeout / Network | 网络中断、连接超时 | 仅在操作可安全重试时有限重试 |
| Provider 5xx | 服务暂时不可用 | 有上限重试;超过阈值降级或人工处理 |
| Output validation | 业务字段不合格 | 保存失败证据;修复或人工复核 |
自动 fallback 会改变模型行为、数据去向、费用和合规边界。只有 routing policy 明确允许,且目标 provider、地区和数据处理条件通过检查时才能切换。
6. Provider Adapter:统一业务契约,不是假装 API 一样
type GenerateRequest = {
taskType: 'draft-note' | 'policy-answer';
input: unknown;
traceId: string;
};
type GenerateResult<T> = {
provider: string;
modelId: string;
output: T;
usage?: { inputTokens?: number; outputTokens?: number };
latencyMs: number;
requestId?: string;
};
Adapter 可以统一业务输入、输出和观测字段,但供应商参数、tool result 格式、缓存规则、错误码与流式事件仍按各自官方契约实现。不要把一个 SDK 的参数或 tool schema 原样复制给另一个模型。
7. 日志、安全与成本证据
推荐记录 trace_id、provider、model ID、request ID、状态、延迟、token/cache usage、重试次数与 schema 结果。不要默认记录完整 Prompt、API Key、居民姓名、医疗信息、工具凭证或未经脱敏的输出。
成本不能用过期价格表硬算。保存真实 usage,再按调用当天官方价格或组织账单计算,并注明核验日期。
8. 三个渐进验证
A. Connection smoke test
发送固定短输入,保存 model ID、request ID、状态和 latency。无权限时明确显示 unavailable。
B. Schema contract test
用正常输入、缺字段输入和含未知事实的输入测试结构化输出。应用须区分 success、refusal、validation failure 和 human review。
C. Failure drill
模拟 invalid model、短 timeout、429 和 tool permission denied。只有可重试错误进入有限重试;日志不能含凭证与 PII。
9. 常见错误
- 把网页产品订阅当成 API 额度;
- 使用博客里的旧 model ID 或旧 endpoint;
- JSON 能解析就当作业务正确;
- 对 401、参数错误和写入操作盲目重试;
- 主模型失败后无策略地跨供应商切换;
- 为排错打印完整 Prompt、工具结果和密钥;
- 只展示最终回答,没有 request、schema、usage 和 failure evidence。
10. 完成自检
- 我能展示精确 provider、model ID、SDK/endpoint 与核验日期。
- 最小请求、Structured Output 和错误场景都有真实运行证据。
- 我能解释 tool call 为什么必须经过应用权限校验。
- 重试只覆盖明确的瞬时、可安全重试失败。
- 日志包含可观测字段,但不泄露 Key、PII 或完整敏感内容。
- 切换模型或供应商前会重新跑 contract tests,而不是假设兼容。
官方参考
📚 相关资源
❓ 常见问题
点击问题,查看本章对应的实践答案。
调 LLM API 第一步该选 OpenAI、Claude 还是 Gemini?
通用聊天/代码/产品内嵌选 OpenAI(GPT-5/4.1/4o,生态最全);长文档处理和代码审阅选 Claude 3(长上下文 + 安全性强);图片/视频/文档混合输入选 Gemini 3 Pro/Flash(多模态原生)。预算敏感先用每家的「小」模型,需要质量再换高配。
API Key 应该放在哪里?前端能不能直接调?
永远不要在前端暴露 Key。把 OPENAI_API_KEY / ANTHROPIC_API_KEY / GEMINI_API_KEY 写进 `.env`,由后端代理网关统一鉴权、限流、审计。按环境分 Key(dev/uat/prod)、最小权限、定期轮换;前端调用走自家后端,后端再转发到模型厂商。
遇到 429 限流要怎么处理?重试策略怎么写?
用指数退避:0.5s → 1s → 2s → 4s,最多 3-5 次。区分错误类型——401/403 是 Key 配置问题不要重试;429 是限流退避后重试;5xx 是服务端,重试同时降级到备选模型。客户端超时设 30 秒以上,每次请求记录 request ID、模型、延迟、tokens 用量。
max_tokens 和 temperature 应该设多少?
max_tokens 必须设——不设会爆量扣费,建议按场景设 200-2000。temperature 通用任务 0-0.7(确定性回答用 0,创意用 0.7);top_p 一般默认即可,别和 temperature 同时大改。用 system 设角色风格保稳定,用 stop 定义停止符控制输出格式。
怎么开启流式输出(streaming)?前端体验有什么注意点?
OpenAI Python 设 `stream=True` 然后 `for chunk in resp` 迭代;Node 遍历 AsyncIterable 实时拼接。前端要做三件事:逐字追加显示、保留光标动画、支持用户取消(cancel)。失败时自动降级回非流式,避免死等;HTTP/2 + 较小 chunk 体验最稳。