提示词库
把提示词放在工作区里,而不是写死在代码里:有版本、有标签,任何 OpenAI SDK 都能按 ID 调用。移动一个标签,你的代码下一次请求拿到的就是新版本,不用重新部署。
调用提示词
用普通的 /v1/chat/completions、/v1/responses 或 /v1/messages 端点,在请求体里加上 prompt_id 和 prompt_variables。SDK 要求必须有 model 和 messages:模型名随便填,消息传一条空的 user 消息即可。在 OpenAI 和 Anthropic 的 SDK 里,这些额外字段放进 extra_body。
import os
from openai import OpenAI
client = OpenAI(base_url="https://synthorai.io/v1", api_key=os.environ["SYNTHORAI_API_KEY"])
reply = client.chat.completions.create(
model="any", # the version's model is used
messages=[{"role": "user", "content": ""}], # required by the SDK; dropped
extra_body={
"prompt_id": "support-reply",
"prompt_variables": {
"product": "Acme Cloud",
"customer_message": "My invoice shows two charges.",
},
},
)
print(reply.choices[0].message.content) 直接用 HTTP 调用时,这些字段放在请求体的顶层。下面这个调用要的是 staging 标签指向的版本:
curl https://synthorai.io/v1/chat/completions \
-H "Authorization: Bearer $SYNTHORAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "any",
"messages": [],
"prompt_id": "support-reply",
"prompt_label": "staging",
"prompt_variables": {"product": "Acme Cloud", "customer_message": "My invoice shows two charges."}
}' 字段
| 字段 | 类型 | 作用 |
|---|---|---|
prompt_id | string | 提示词在你工作区里的 ID,和「提示词」页面上显示的一致。 |
prompt_variables | object | 版本里 {{name}} 变量的取值:字符串、数字或布尔值,按文本填入。没传的变量用版本的默认值;没有默认值,调用就会失败。 |
prompt_version | integer | 固定使用某一个版本。不传时,用 production 标签指向的版本。 |
prompt_label | string | 调用其他标签(例如 staging)指向的版本。版本和标签二选一,不能同时传。 |
请求会被改成什么样
- 先放版本里的消息,再接你的消息。对话要继续,就靠你自己传的消息:之前的轮次、工具调用和工具结果都会原样保留。只有那条为了满足 SDK 而传的空 user 消息会被去掉。
- 用版本里的模型替换请求里的模型。版本没指定模型时,沿用你传的。
- 你传的参数优先。版本里的 temperature、max_tokens、top_p 和 JSON 模式,只在你的请求没设同一个参数时才生效。
- 四个
prompt_*字段到网关为止。供应商收到的是一个普通请求。 - 在
/v1/responses上,消息写进input(字符串形式的 input 视为你的 user 消息),max_tokens变成max_output_tokens,JSON 模式变成text.format。
在 /v1/messages 上
同样的四个字段也可以配合 Anthropic SDK 使用。版本的 system 文本排在你自己的 system 前面,版本的消息排在你的消息前面;temperature、top_p 和 max_tokens 只在你的请求没有设置时生效。这个端点没有对应 JSON 模式的字段,该设置会被略过。
import os
from anthropic import Anthropic
client = Anthropic(base_url="https://synthorai.io", api_key=os.environ["SYNTHORAI_API_KEY"])
reply = client.messages.create(
model="any", # the version's model is used
max_tokens=1024,
messages=[{"role": "user", "content": ""}], # required by the SDK; dropped
extra_body={
"prompt_id": "support-reply",
"prompt_variables": {
"product": "Acme Cloud",
"customer_message": "My invoice shows two charges.",
},
},
)
print(reply.content[0].text) 工具调用与多轮对话
像不用提示词库时一样,照常传 tools 和到目前为止的对话。版本负责系统提示词和开场消息,其余对话由你的消息承载,包括模型的工具调用和你返回的工具结果。
# Round 2 of a tool loop: send the conversation so far, as without a prompt.
# The gateway puts the version's messages first and these after them.
reply = client.chat.completions.create(
model="any",
tools=tools,
messages=[
{"role": "user", "content": ""}, # the SDK placeholder, dropped
first.choices[0].message, # the model's tool call
{"role": "tool", "tool_call_id": call.id, "content": lookup_invoice(call)},
],
extra_body={"prompt_id": "support-reply", "prompt_variables": variables},
) 版本里的工具和输出 schema
版本里可以保存函数工具、工具选择方式和回答要遵循的 JSON schema,调用时会按你所用端点的格式写出。请求自带的工具排在版本的工具之后;同名时以请求的为准。请求自己的 tool_choice 和响应格式优先。
片段(Partials)
片段是一段只保存一份、可被多个提示词用 {{>id}} 引用的文本。保存提示词版本时,每个引用都会固定到片段当时的最新版本,显示为 {{>id@4}},所以片段之后再改,已保存的版本也不会变。片段有了更新的版本时,提示词页面会提示并提供更新入口,更新会给提示词保存一个新版本。片段里的变量由调用时的 prompt_variables 填充。片段不能单独调用;仍被已保存版本引用的片段不能删除。
版本与标签
每次保存都会生成下一个版本,已保存的版本不会再改。每个提示词都有 production、staging 和 development 三个标签,你也可以加自己的标签。把 production 指向某个版本就是上线,指回旧版本就是回滚,你的代码一直调用同一个 ID。
移动标签或删除提示词后,大约 10 秒内对调用生效。移动标签和删除提示词需要管理员或工作区所有者。
试运行草稿
Prompts 页面的编辑器左边写草稿,右边可以直接试。给每个变量填一个值,点Run:草稿渲染后发给它设定的模型,回答连同延迟和成本一起显示。这次调用按 Playground 调用计费并记入日志;在你保存版本之前,草稿本身不会被保存。Show the request 只显示各端点渲染后的请求,不调用模型。
上线前测试一个版本
提示词的测试里可以保存测试集:每一行是一组变量值,可以附带一条 user 消息和期望答案;还可以设置回答必须通过的检查项(包含某段文本、匹配正则、等于期望答案、是合法 JSON、符合输出 schema、延迟或成本上限,或者由模型按你写的标准评审)。运行时,会对每一行分别调用你选的版本和对比版本,把两个回答并排显示,并给出通过的行数以及各自的成本和延迟。每次调用都按 Playground 调用计费并记入日志,一次运行归在同一个 trace 下。移动标签时,对话框会显示该版本最近一次运行的结果,仅供参考,不会拦截。测试集和运行得到的回答都加密存储,回答保留 30 天。
灰度发布
一个标签可以把一部分调用分给另一个版本,比如“production:v6,v7 占 10%”。一次调用落在哪个版本,按它的 session id 决定;没有 session 时按终端用户,再没有就按单次请求,所以同一段对话始终用同一个版本。X-Synthorai-Prompt-Version 会告诉你实际应答的版本,Prompts 页面会并排显示两个版本的数据。管理员可以调整占比、把标签移到候选版本,或者停止灰度;用 prompt_version 指定版本的调用不参与灰度。
变更 webhook
管理员可以在 Prompts 页面添加最多三个地址。提示词被创建、保存新版本、标签移动、灰度变化或被删除时,这些地址会收到一次 POST。每个请求都带签名:X-Synthorai-Signature: t=…,v1=…,即用添加地址时只显示一次的密钥,对“时间戳 + 点号 + 原始请求体”做 HMAC-SHA256。只有为该地址打开对应开关时,才会发送版本的文本内容。投递失败会在约半小时内再重试三次;连续五个事件都放弃后,该地址会被停用,需要你手动重新启用。
POST /hooks/prompts
X-Synthorai-Event: prompt.label_moved
X-Synthorai-Signature: t=1791140000,v1=5f2c…
{
"type": "prompt.label_moved",
"created_at": "2026-10-05T03:12:44Z",
"prompt": "support-reply",
"kind": "prompt",
"label": "production",
"from": 6,
"version": 7,
"by": 42
}
# Verify: hex(HMAC-SHA256(secret, "1791140000" + "." + raw_body)) == v1 导入、导出,以及 OpenAI 的存储提示词
新建提示词 › 导入可以把粘贴的 Chat Completions 或 Responses 请求体、或者 LiteLLM 的 .prompt 文件读成第一个版本,包括消息、模型、参数、工具和输出 schema。提示词的导出会把它连同全部版本下载成一个 JSON 文件,这个文件可以用同样的方式导入;复制到工作区则把它复制到你所在的另一个工作区。OpenAI 的存储提示词在 2026-11-30 之后停止服务,也无法读出:在这里用原来的 pmpt_… id 重新建一个提示词,带着这个 id 发送 prompt 的 /v1/responses 请求就会直接由提示词库应答,代码不用改。其中的 version 是数字时,对应库里的那个版本;不带时使用 production。
只渲染,不调用模型
POST /v1/prompts/{id}/render 返回一次调用实际会发出的请求,以及解析到的版本号,但不调用模型。传 prompt_variables,可选 prompt_version 或 prompt_label,以及 format:chat(默认)、responses 或 messages。它不计费,也不出现在 Logs 里,但计入这个 key 的限速。可以用它确认某个版本到底发了什么,或者拿渲染结果去调用 prompt_* 字段不支持的端点。
curl https://synthorai.io/v1/prompts/support-reply/render \
-H "Authorization: Bearer $SYNTHORAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"format": "chat",
"prompt_variables": {"product": "Acme Cloud", "customer_message": "My invoice shows two charges."}
}'
{
"prompt_id": "support-reply",
"version": 6,
"format": "chat",
"request": {
"model": "claude-sonnet-5",
"temperature": 0.3,
"messages": [
{"role": "system", "content": "You answer billing mail for Acme Cloud."},
{"role": "user", "content": "My invoice shows two charges."}
]
}
} 响应头
X-Synthorai-Prompt-Version 表示实际应答的是哪个版本,按标签调用时只能靠它得知。提示词库读不出来时,网关会用最近一次读到的副本应答,最长 24 小时,并加上 X-Synthorai-Prompt-Stale: 1;这期间移动的标签要等提示词库恢复可读后才生效。
错误
这些错误都在调用任何模型之前返回,因此不会计费。错误格式跟随你调用的端点。
| 状态码 | 错误码 | 何时出现 |
|---|---|---|
| 400 | prompt_variable_missing | 某个变量既没有传值,也没有默认值。错误信息会写明是哪个变量。 |
| 400 | prompt_invalid | 某个字段格式不对:同时传了版本和标签、变量值是对象或数组、变量超过 64 个,或者变量总量超过 64 KB。渲染后的提示词超过 1 MB 也会这样被拒绝。调用后没有任何内容可发时也一样:版本里的每条消息渲染出来都是空的,请求自己也没带消息。 |
| 404 | prompt_not_found | API key 所在的工作区里没有这个 ID 的提示词、没有这个版本,或者该标签还没指向任何版本。 |
| 409 | prompt_unreadable | 存储的版本已无法读取,请保存一个新版本。 |
| 503 | prompt_unavailable | 提示词库暂时无法读取,网关也没有这条提示词的近期副本。请重试。 |
按版本统计
每次调用都会记录所用的提示词和版本。Prompts 页面按版本显示调用数、错误数、花费、token、延迟和首个 token 耗时,范围可选最近 7、30 或 90 天;点某个版本的调用数,会在 Logs 中打开这些调用。可以先把新版本挂在 staging 下与 production 并行运行,对比之后再移动 production。
在 Logs 里可以用 prompt = support-reply 和 prompt_version = 7 筛选;请求详情里会写明它用的提示词和版本。导出的记录也带这两项:文件和 webhook 里是 run.prompt_id 和 run.prompt_version,OTLP span 上是 gen_ai.prompt.name 和 gen_ai.prompt.version。
另见: 提示词 · Chat Completions · Responses API