你只需一条终端命令,就能比长长的功能列表更快了解一个 AI gateway。如果这个 gateway 真的兼容 OpenAI,那么同一条 curl 请求应该可以在受支持的模型家族之间通用,同时 base URL、authorization header、消息格式和 response parsing 都保持稳定。
本教程以 Flatkey 为例展示实际用法:先发送一条 chat-completions 请求,把 model 名称放进变量里,然后在不重写集成代码的情况下测试几个当前的模型家族。它面向希望在添加 SDK 或提交应用代码之前,先在终端中验证 API 的开发者。
模型选择说明: 模型目录会变化。下面的 model ID 反映的是 Flatkey 在 2026 年 7 月 24 日核实过的公开文档。在生产环境中使用某个 ID 之前,请确认当前的 model 行和可用性。
最短可用的 chat-completions cURL 请求
创建一个 Flatkey API key,在 shell 中导出它,然后向兼容 OpenAI 的 chat-completions endpoint 发送请求:
export FLATKEY_API_KEY="your-flatkey-api-key"
curl https://router.flatkey.ai/v1/chat/completions \
-H "Authorization: Bearer $FLATKEY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [
{
"role": "user",
"content": "Write a one-sentence product description for a waterproof daypack."
}
]
}'
有四个部分很重要:
| Request part | What stays stable |
|---|---|
| Base URL | https://router.flatkey.ai/v1 |
| Endpoint | /chat/completions |
| Authentication | Authorization: Bearer $FLATKEY_API_KEY |
| Message shape | An array of role-and-content objects |
对于兼容的 chat 模型,你切换的主要字段是 model。
在不同模型家族之间使用相同的 cURL 结构
把 model ID 放进 shell 变量中,这样请求体就不需要改动:
export FLATKEY_API_KEY="your-flatkey-api-key"
export MODEL="gpt-4o-mini"
curl -sS https://router.flatkey.ai/v1/chat/completions \
-H "Authorization: Bearer $FLATKEY_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"model\": \"$MODEL\",
\"messages\": [
{
\"role\": \"system\",
\"content\": \"Return concise ecommerce copy.\"
},
{
\"role\": \"user\",
\"content\": \"Write a product title for a lightweight waterproof daypack.\"
}
],
\"temperature\": 0.2
}" | jq -r '.choices[0].message.content'
现在用另一个已文档化的 model ID 重新运行命令:
export MODEL="claude-sonnet-4-6"
export MODEL="gemini-2.5-flash"
export MODEL="deepseek-v3.1"
请求仍然使用相同的端点、请求头、消息和 jq 解析器。这种稳定的调用形式就是其运维优势:你可以在不为每个提供商维护单独终端脚本的情况下,对受支持的模型家族进行比较。
模型选择说明: 共享的请求形式并不意味着每个模型的行为都完全相同。受支持的参数、上下文限制、工具行为、安全行为、延迟和输出风格可能不同。应将兼容性视为更简单的集成接口,而不是模型可互换的证明。
运行一个小型多模型测试循环
为了快速在终端中进行比较,定义一个简短列表并向每个模型发送相同的提示词:
#!/usr/bin/env bash
set -euo pipefail
: "${FLATKEY_API_KEY:?先设置 FLATKEY_API_KEY}"
MODELS=(
"gpt-4o-mini"
"claude-sonnet-4-6"
"gemini-2.5-flash"
"deepseek-v3.1"
)
PROMPT="为一款防水通勤背包写三条突出收益点的要点。"
for MODEL in "${MODELS[@]}"; do
echo
echo "=== $MODEL ==="
jq -n \
--arg model "$MODEL" \
--arg prompt "$PROMPT" \
'{
model: $model,
messages: [
{role: "system", content: "You write concise ecommerce copy."},
{role: "user", content: $prompt}
],
temperature: 0.2
}' |
curl -sS https://router.flatkey.ai/v1/chat/completions \
-H "Authorization: Bearer $FLATKEY_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- |
jq -r '.choices[0].message.content // .error.message'
done
使用 jq -n 构建 JSON 比手动转义一长串 shell 字符串更安全。它还使脚本更容易通过变量、额外消息或可选参数进行扩展。
将脚本保存为 compare-models.sh,赋予可执行权限,然后运行它:
chmod +x compare-models.sh
./compare-models.sh
在输出中比较什么
只有在提示词和评分方法保持一致时,多模型测试才有用。对于电子商务文案任务,请比较:
| 维度 | 适合终端的检查方式 |
|---|---|
| 指令遵循 | 输出是否恰好返回了三条要点? |
| 格式稳定性 | 响应能否在没有特殊处理的情况下被解析? |
| 品牌契合度 | 语气是否具体、可信,并且没有未经证实的声明? |
| 延迟 | 请求花了多长时间? |
| Token 用量 | 响应在其 usage 对象中报告了什么? |
| 错误行为 | 失败的请求是否返回了有用的错误消息? |
当延迟很重要时,添加 cURL 计时字段:
curl -sS -o response.json \
-w 'status=%{http_code} total=%{time_total}s\n' \
https://router.flatkey.ai/v1/chat/completions \
-H "Authorization: Bearer $FLATKEY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-2.5-flash",
"messages": [
{"role": "user", "content": "写一个五个词的产品标语。"}
]
}'
jq . response.json
这将传输层测量与模型输出分离。终端会打印 HTTP 状态和总请求时间,而 JSON 响应仍可供检查。
模型选择注意: 不要只根据一次响应就选定生产模型。请运行一组具有代表性的提示,重复请求,并根据与你的应用最相关的要求对输出进行评分。
保持请求可比较
提示或参数的微小变化都可能使模型测试产生误导。请使用以下控制项:
- 保持消息完全一致。 不要只为某一个模型改进提示而不改其他模型。
- 使用相同的 temperature。 较低的值通常更便于审查比较结果。
- 捕获原始 JSON。 保存完整响应,而不仅是渲染后的文本。
- 记录模型 ID。 显示名称不足以用于可复现测试。
- 将错误与不良回答区分开来。 传输或可用性错误并不等同于输出质量评分。
- 检查当前可用性。 即使是有文档记录的模型,其运行状态也可能发生变化。
添加基本故障处理
使用 --fail-with-body,让 cURL 在 HTTP 错误时退出,同时保留响应正文:
HTTP_BODY=$(mktemp)
if ! curl --fail-with-body -sS \
-o "$HTTP_BODY" \
https://router.flatkey.ai/v1/chat/completions \
-H "Authorization: Bearer $FLATKEY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [
{"role": "user", "content": "返回单词 ready。"}
]
}'; then
jq -r '.error.message // "请求失败"' "$HTTP_BODY" >&2
rm -f "$HTTP_BODY"
exit 1
fi
jq -r '.choices[0].message.content' "$HTTP_BODY"
rm -f "$HTTP_BODY"
在应用代码中,还应添加显式超时、针对可重试故障的有限重试,以及不会暴露密钥或敏感提示内容的日志记录。
一个实用的模型选择策略
最简单的策略是按工作负载而不是按提供商名称来选择:
| 工作负载 | 首次测试 | 上线前需要验证的内容 |
|---|---|---|
| 高吞吐量的简单文案 | 快速、成本高效的模型 | 格式符合性和可接受的错误率 |
| 细腻的品牌文案 | 更强的通用模型 | 语气、事实克制性和修改率 |
| 长上下文综合 | 具有合适上下文支持的模型 | 检索质量和截断行为 |
| 对延迟敏感的 UI | 低延迟模型 | 尾延迟,而不只是单次快速请求 |
| 备用路由 | 来自另一模型家族的模型 | 参数兼容性和输出契约 |
从能够稳定达到你质量阈值的最小模型开始。只有在任务需要时再升级到更强的模型。如果你添加了备用路由,请用相同的响应契约测试备用模型,而不要假设它可以在不修改应用的情况下替代主模型。
在为生产测试选择 ID 之前,你可以在 Flatkey 的定价页面查看当前的模型访问权限和价格。
何时从 cURL 迁移到 SDK
cURL 非常适合快速确认以下四件事:
- API 密钥可用
- 基础 URL 正确
- 所选模型接受该请求
- 响应结构与你的解析器匹配
当你需要流式辅助、结构化重试逻辑、类型化响应、可复用客户端或应用级可观测性时,就迁移到 SDK。把成功的 cURL 请求保留在你的运行手册中:它仍然是区分网关访问问题和 SDK 配置问题的最快方式。
最终实施检查清单
- 导出 API 密钥,不要直接把它写在脚本里。
- 将
https://router.flatkey.ai/v1用作基础 URL。 - 向
/chat/completions发送兼容的聊天请求。 - 把模型 ID 放到配置中。
- 当 shell 转义变得复杂时,使用
jq构建 JSON。 - 捕获 HTTP 状态、延迟、响应内容和使用数据。
- 使用相同的提示词和参数比较各个模型。
- 在生产上线前验证当前目录的可用性。
- 在应用代码中添加超时、受限重试和安全日志记录。
一条稳定的 cURL 请求就能为你提供一个干净的起点。一旦它可用,只需更改 model 字段,就能把这条请求变成面向多个 AI 模型家族的实用测试工具——而无需每次都更改身份验证、基础 URL 或响应解析器。
常见问题
我可以对每个 AI 模型都使用相同的 chat-completions cURL 请求吗?
对于 Flatkey 通过兼容的 chat-completions 路由开放的模型,可以使用该请求。其他模态或特定协议功能可能需要不同的端点或请求字段。
chat-completions 请求的最小字段集是什么?
对于基本请求,提供受支持的 model 和一个 messages 数组。你还需要 bearer 授权头和 JSON 内容类型。
为什么要把模型名称放在环境变量中?
它保持请求形状稳定,减少编辑错误,并使脚本更容易在预发、评估和生产配置之间运行。
我应该在生产环境中使用 cURL 吗?
cURL 非常适合用于验证、脚本和运行手册。大多数生产应用都会从 SDK 或 HTTP 客户端中受益,这些客户端提供显式的超时、重试、遥测以及类型处理支持。
我该如何在 GPT、Claude、Gemini 和 DeepSeek 模型之间做选择?
使用具有代表性的评估集来选择。比较指令遵循能力、输出质量、延迟、token 使用量、错误行为,以及你的工作负载所需的特定功能。在上线前确认当前可用性。



