mistral-large-latest是指针而非固定版本,移动会导致无法复现结果、无法归因回归、丧失风险控制窗口,需通过快照ID固定。
别名带来的代价
家族别名很方便,对原型开发来说是正确的选择。但在生产环境中,它会让三件事变得不可能。
无法复现结果。 上个月的一个 bug 报告引用了一个已不复存在的模型名称。你无法复现它——即使发送相同的 random_seed 也不行——因为 seed 只能固定采样器,无法固定权重。
无法归因回归。 当输出质量发生变化,而同时有三件事在变——你的 prompt、你的检索,以及静默更新的模型——你就无法二分排查。固定版本可以永久移除一个变量。
无法控制你承担风险的时间点。 新的快照可能改变格式化习惯、冗长程度、拒绝行为以及调用工具的积极性。这些都不是新模型的 bug,但都可能破坏一个针对旧模型调优过的 prompt。使用别名,这些变化会在一个你没选择过的星期二突然降临。
代价在于,固定的快照最终也会退役。但这是一件可以计划、有公告的事件,比意外发生要好得多——下面第五步会告诉你如何及时获知。
还有第二个、更小的代价值得提一下,以便在做决定时两者都在视野内:固定的模型不会变好。快照版本通常会改进指令遵循能力、降低畸形结构化输出的比例,而一个固定了一年半的服务运行的模型会比它本可以运行的模型更差,价格却一样或更贵。固定不是永久状态;它是一种控制你何时接受变化的方式。把 pin 看作每隔几个月要主动移动一次的东西,而不是设一次就不管了。
固定到一个从未运行过的模型是场赌博,所以第一步不是从列表里挑一个快照——而是要找出一直是哪个快照在服务你的流量。这个快照才是你的 prompt 所针对的、用户一直满意的,才是需要固定的目标,而且不需要重新验证。/v1/models 端点中的别名映射会直接告诉你答案。
列出你的 key 可以访问的模型。每个条目都有一个 id,而定版快照会携带当前指向它的别名:
curl -s https://api.mistral.ai/v1/models \
-H "Authorization: Bearer $MISTRAL_API_KEY" \
| jq -r '.data[]
| [.id, ((.aliases // []) | join(",")), (.deprecation // "-")]
| @tsv' \
| sort
向下读别名列,找到你当前发送的别名。该行的 id 就是你一直使用的定版快照——形式类似于 mistral-large-2411,其中四位数字是发布的年份和月份。这个 id 就是你的候选固定目标。
如果该行有 deprecation 字段,请注意它。如果你要固定的快照已经标明了退役日期,你应该固定到更新的那个,现在就测试,而不是固定到一个只剩几周的模型。
把 id 放在配置里,而不是调用点。你每隔几个月就要改一次,应该一次编辑加一次部署搞定,而不是在整个代码库里搜索:
# .env
MISTRAL_MODEL=mistral-large-2411
# 在旁边记录原因,因为四个月后没人记得。
# 固定于 2026-08-11。Prompt 套件已针对此快照验证。
# 当 CI 中的弃用检查开始报警时审查。
在边缘读一次,然后到处传递:
import os
from mistralai import Mistral
MODEL = os.environ["MISTRAL_MODEL"] # 未设置则 loud 失败
client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
resp = client.chat.complete(
model=MODEL,
messages=[{"role": "user", "content": "Summarise this ticket in one line."}],
max_tokens=120,
temperature=0.2,
)
print(resp.model) # 服务器说它服务的是哪个
部署完成前用 grep 搜索漏网之鱼。哪怕只有一个被遗忘的 -latest 在评估脚本或后台任务里,整个努力就白费了,而且它偏偏会产出令人困惑的结果:
rg -n -- '-latest' --glob '!node_modules' --glob '!*.lock'
检查真实响应中的 model 字段,并在针对真实 API 运行的测试中断言它。无声无息未生效的固定比没有固定更糟糕,因为你会信以为真:
def test_model_is_pinned():
resp = client.chat.complete(
model=MODEL,
messages=[{"role": "user", "content": "ping"}],
max_tokens=1,
)
assert "-latest" not in MODEL, f"config still uses an alias: {MODEL}"
assert resp.model == MODEL, f"asked {MODEL}, served {resp.model}"
在每次请求的日志中记录固定的 id,连同 usage.prompt_tokens 和 usage.completion_tokens。当六周后有人问答案为什么变了,日志会告诉你是不是模型的问题。
响应中 model 字段是回显你发送的字符串还是已解析的快照,取决于提供商一侧的细节,而非保证。把不匹配作为检查 /v1/models 的信号,而不是任何结论的证明——该端点中的别名映射才是权威来源,如上一页所述。
这是让固定变得安全而非积攒故障的方式。Mistral 会公开发布每个模型的退役信息,/v1/models 端点会暴露这些信息,所以定时任务可以在你还有时间的时候大声失败。
写一个检查:当固定的模型接近退役阈值或已从列表中完全消失时就失败:
import os, sys, json, datetime, urllib.request
MODEL = os.environ["MISTRAL_MODEL"]
WARN_DAYS = 60
req = urllib.request.Request(
"https://api.mistral.ai/v1/models",
headers={"Authorization": f"Bearer {os.environ['MISTRAL_API_KEY']}"},
)
data = json.load(urllib.request.urlopen(req))["data"]
entry = next((m for m in data if m["id"] == MODEL), None)
if entry is None:
sys.exit(f"FAIL: {MODEL} is no longer listed by the API")
dep = entry.get("deprecation")
if dep:
left = (datetime.date.fromisoformat(dep[:10]) - datetime.date.today()).days
if left < WARN_DAYS:
sys.exit(f"FAIL: {MODEL} retires in {left} days ({dep})")
print(f"ok: {MODEL} retires {dep} ({left} days)")
else:
print(f"ok: {MODEL} has no announced retirement date")
定时运行它——每夜或每周在 CI 中——而不是只在部署时运行。两个月没部署过的服务恰恰是最可能措手不及的那个。
当它报警时,从容迁移:让预发环境指向新的快照,用 prompt 套件同时跑两个版本,特别关注输出长度、格式化习惯和工具调用积极性,然后移动 pin。这是半天你已经计划好的工作——这才是关键。
固定有一个运营代价:如果快照被撤回或暂时不可用,请求会失败,而不是悄悄地降级到别的什么。通过支持显式回退列表的网关路由,可以让 pin 作为主选,并指定第二个定版快照作为备份——这样中断是记录在案的内回退,而不是给用户的 5xx——请求日志记录了每个调用实际服务的 id,这正是本文一直在让你保留的字段。