拿到 Union Alpha 的接入信息后,容易犯的错是把鉴权、请求体、图片字段和重试逻辑一次写完再统一调试;一旦报错,很难判断是密钥层、请求结构层还是额度层的问题。更稳的顺序是先只跑通鉴权加纯文本请求,确认链路通了,再在同一请求里追加图片字段,最后按返回结构把错误归到具体一层。
适用场景是新接入、手上只有接入信息和少量文档的时候。操作动作:先把鉴权字段和请求入口分层放配置,再发纯文本最小请求,通过后在同一请求里追加图片字段。验证方式:纯文本能拿到返回内容且请求 ID 可在日志中对应;追加图片后要么返回图片相关结果,要么返回明确指向字段或模型能力的错误。风险边界:字段名、图片编码方式和额度口径以实际文档与账号状态为准,一次成功不能当成所有模型标识都可用。
把鉴权字段和请求入口分别放进配置层
鉴权字段和请求入口不要写死在业务代码里。分开配置的好处是替换密钥、切换测试与正式入口、排查鉴权失败时只动一层。字段名以实际文档为准,下面只是通用骨架,不要直接当成官方字段名。
# config.yaml 或 .env 示例,字段名以接入文档为准
entry:
base_url: ${UNION_ALPHA_BASE_URL}
auth:
api_key: ${UNION_ALPHA_API_KEY}
auth_header: Authorization
model:
text_model: text-default
vision_model: vision-default
request:
timeout_seconds: 30
应当来自环境变量的是请求入口和密钥,尤其是密钥,不要打印明文,也不要提交到版本库。模型标识可以放配置层,也可以按调用场景由参数传入,但建议集中在一处,避免同一脚本里出现多个不一致的模型标识。配置加载完先做一次校验:入口地址是否指向预期主机、密钥是否非空、模型标识是否为空。这一步只验证配置可读,不验证权限是否正确。
拼一个只有文本的最小请求体
先不要带图片。最小请求体的构造顺序是模型标识、一条用户消息、文本内容。Union Alpha 这类接口通常采用 messages 结构或它的变体,字段名需要按文档替换。下面用 Python 调用骨架示意,换成 curl 也可以,重点是请求体结构保持一致。
import os, json, requests
cfg = {
"base_url": os.environ["UNION_ALPHA_BASE_URL"],
"api_key": os.environ["UNION_ALPHA_API_KEY"],
"model": "text-default",
}
body = {
"model": cfg["model"],
"messages": [
{"role": "user", "content": "只回复四个字:链路已通"}
],
}
resp = requests.post(
cfg["base_url"].rstrip("/") + "/v1/chat/completions",
headers={
"Authorization": "Bearer " + cfg["api_key"],
"Content-Type": "application/json",
},
json=body,
timeout=30,
)
print(resp.status_code)
print(json.dumps(resp.json(), ensure_ascii=False, indent=2)[:2000])
判定「通了」不要只看 HTTP 状态码。建议同时看三件事:返回体里是否有模型输出的文本内容、是否有可记录的请求 ID、日志里发出的请求体和收到的返回体是否成对。如果返回里只有鉴权或权限相关提示,先回配置层,不要改请求体。如果返回内容字段非空且请求 ID 能对上,纯文本链路就算通了。
在同一请求里追加图片字段并观察反应
下一步不是新写一个多模态函数,而是在刚才同一个请求体的同一条消息里追加图片。常见做法是把 content 从字符串改成数组,数组里既放文本块也放图片块;图片块里通常有类型标识和图片数据或图片地址。用内联 base64 还是 URL、字段名具体是什么,需要按文档确认。
# 追加后的 content 骨架,字段名以文档为准
body["messages"][0]["content"] = [
{"type": "text", "text": "描述这张图片的主要内容"},
{"type": "image_url", "image_url": {"url": "https://example.invalid/sample.png"}},
]
发送后通常只有两种结果。第一种是被接受:返回体里出现针对图片的描述或引用,说明多模态可以叠加在同一次请求上,接下来可以继续加第二张图片或调整文本指令。第二种是参数报错:返回信息指向 content 字段、图片字段或模型标识。这时要做的是分步排查,而不是重写整段代码——先确认该模型标识是否支持图片输入,再把图片块挪到请求的其他位置试一次,确认是字段位置问题还是模型能力问题。换调用方式或换模型标识之后,仍然用同一段文本指令做对照,避免同时改动多个变量。
按返回结构区分成功、参数错误和额度错误
不依赖未公开的错误码清单,用返回里的可读信息做三分类,目的是让报错直接指向要改的那一层。
- 成功:返回体中有模型输出内容,请求 ID 可记录,状态正常。动作:保存这次请求体作为基线,不要再随手改字段名。
- 参数错误:返回信息提到具体字段、类型、位置或缺少必填项,问题多在请求侧。动作:回到第二层或第三层的请求体,只改被指出的字段,重发同一个请求。
- 额度错误:返回信息提到配额、余额、速率或额度限制,与请求体结构关系不大。动作:先不要改代码,确认账号额度与调用速率状态,必要时更换密钥或等待额度恢复。
建议在脚本里把三类分别打日志:入口与模型标识、状态码、返回归类、返回内容摘要。不要只根据状态码判断,有的网关会把错误统一包在 200 响应里,看返回体里的错误对象更可靠。
把能跑通的请求体固化成可复用脚本
把改通的那一次请求体存成独立脚本,后续每次验证都用同一份输入,减少变量。脚本结构建议固定为四段:读配置、从外部 JSON 文件读请求体、发送并打印分层结果、把返回写入日志文件。运行命令只带一个参数,例如指定请求体文件。
python run_union_alpha_probe.py `--body` request_text.json
python run_union_alpha_probe.py `--body` request_with_image.json
验证脚本本身是否能把错误归层,可以做一次失败请求:临时把模型标识改成一个不存在的值,或删掉鉴权头,观察脚本输出是否分别落到参数错误层和鉴权层,而不是笼统打印一次异常。能稳定复现归类后,再把这个脚本用于多模态的每次改动,比较同一份输入在不同模型标识下的返回差异。