Responses API
新POST /v1/responses 接收指令和输入项列表,并以 OpenAI Responses 格式返回由输出项组成的响应对象。可将它用于 OpenAI SDK 的 responses API,以及基于它构建的工具,例如 Codex CLI。该端点不保存状态:每个请求都要发送完整的对话。
POST https://api.shannon-ai.com/v1/responses
最小的请求只有一个模型 id 和一段文本。除非你要求,否则回复不是流式的。
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.shannon-ai.com/v1",
)
response = client.responses.create(
model="shannon-3",
input="Say hello in one sentence.",
)
print(response.output_text) import OpenAI from "openai";
const client = new OpenAI({
apiKey: "YOUR_API_KEY",
baseURL: "https://api.shannon-ai.com/v1",
});
const response = await client.responses.create({
model: "shannon-3",
input: "Say hello in one sentence.",
});
console.log(response.output_text); curl https://api.shannon-ai.com/v1/responses \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "shannon-3",
"input": "Say hello in one sentence."
}' 回复是一个响应对象。它的 output 包含推理(如果模型进行了推理)和消息:
{
"id": "resp_5f0c1e7a9b3d4c62a8e1f07d2b46c9a3",
"object": "response",
"created_at": 1791625200,
"model": "shannon-3",
"status": "completed",
"error": null,
"incomplete_details": null,
"instructions": null,
"metadata": {},
"parallel_tool_calls": true,
"temperature": null,
"tool_choice": "auto",
"tools": [],
"top_p": null,
"output": [
{
"id": "rs_8a2e6c1f4b7d4e03b9c5a1d70f3e2b64",
"type": "reasoning",
"summary": [
{
"type": "summary_text",
"text": "The user wants a greeting in one sentence. Keep it short and friendly."
}
]
},
{
"id": "msg_1c7b9e3a5d2f4a86b0e4c8d19a6f7e25",
"type": "message",
"role": "assistant",
"status": "completed",
"content": [
{
"type": "output_text",
"text": "Hello, it is good to meet you.",
"annotations": []
}
]
}
],
"usage": {
"input_tokens": 1184,
"output_tokens": 46,
"total_tokens": 1230
}
} 请求字段
请求只需要 model 和 input。适用于一列给出某个字段会改变回复的模型。托管开源权重模型是模型列表中的十二个 id;Shannon 3 系列是 shannon-3、shannon-3-pro、shannon-3.1 和 shannon-3.1-pro。 模型与定价
| 字段 | 类型 | 默认值 | 说明 | 适用于 |
|---|---|---|---|---|
model | string | 必填。 模型列表中的一个 id。匹配不区分大小写。缺失或未发布的 id 会返回 400 unknown model。 | 所有模型 | |
input | string | array | 一个字符串,会被当作一条用户消息读取;或一个输入项数组。见下方的输入项。 | 所有模型 | |
instructions | string | 给模型的指令,即这种格式的系统提示词。 | 托管开源权重模型、shannon-1.6-*、shannon-2-*、shannon-coder-1 | |
stream | boolean | false | true 会以服务器发送事件的形式发送回复。见下方的流式传输。 | 所有模型 |
max_output_tokens | integer | 4096 | 回复的上限,以 tokens 计。1 到 65,536 之外的值会被调整到该范围内。它同时也是请求运行期间从你的余额中预留的数量。见下方的输出限制。 | 托管开源权重模型、shannon-1.6-*、shannon-2-*、shannon-coder-1 |
temperature | number | 采样温度。在托管开源权重模型上,取值保持在 0 到 2 之间。 | 托管开源权重模型;shannon-1.6-*、shannon-2-* 和 shannon-coder-1 在非流式回复上 | |
top_p | number | 核采样。取值保持在 0 到 1 之间。 | 托管开源权重模型 | |
tools | array | 模型可以调用的函数,采用这种格式的扁平形式:{"type": "function", "name", "description", "parameters"}。见下方的工具。 | 所有模型 | |
tool_choice | string | object | auto | "auto" 由模型决定。"required" 让它调用工具。{"type": "function", "name": "…"} 让它调用该工具。 | 托管开源权重模型 |
reasoning | object | {"effort": "…"},取值为 off、low、medium 或 high。其他任何值都会返回 400。 | 托管开源权重模型 | |
text | object | {"format": {…}} 请求 JSON 形式的回答。见下方的结构化输出。 | 所有 Shannon 档位;托管开源权重模型按各 id 所列 |
previous_response_id、store、metadata、parallel_tool_calls、truncation、include、user 和 prompt_cache_key 会被接受,以便现有的客户端代码无需修改即可运行。它们不会改变回复。由于不保存对话,后续请求需要在 input 中带上之前的轮次。
输入项
输入项要么是带有 role 和 content 的消息,要么是带有类型的、携带工具调用或其结果的项。content 是字符串或部分数组。
| 项 | 说明 | 适用于 |
|---|---|---|
{"role": "user", "content": …} | 你的提问。content 是字符串,或 input_text 和 input_image 部分。 | 所有模型 |
{"role": "assistant", "content": …} | 模型之前的一次回复。content 是字符串,或 output_text 部分。 | 所有模型 |
{"role": "system", "content": …}{"role": "developer", "content": …} | 对话内部的指令。 | 托管开源权重模型 |
{"type": "function_call", "call_id": "…", "name": "…", "arguments": "…"} | 模型在之前的回复中发出的工具调用。arguments 是 JSON 字符串。 | 所有模型 |
{"type": "function_call_output", "call_id": "…", "output": "…"} | 该调用的结果。call_id 是调用的 id,output 是字符串形式的结果。 | 所有模型 |
请把指令放在 instructions 字段中。使用 Shannon 3 系列的 id 时,必须遵守的指令请放进 user 消息。
回复的 output 中的各项可以原样放回 input:message 和 function_call 项会被读取,reasoning 项会被跳过。
内容部分
| 部分 | 说明 | 可用于 |
|---|---|---|
{"type": "input_text", "text": "…"} | 用户消息的文本。 | 所有模型 |
{"type": "output_text", "text": "…"} | 助手消息的文本。 | 所有模型 |
{"type": "input_image", "image_url": "…"} | 图片,可以是带 base64 内容的 data: URL,也可以是 http(s) URL。 | Shannon 3 系列、shannon-1.6-lite、shannon-1.6-pro,以及列出图片输入的托管开源权重模型 |
{"type": "input_file", "file_data": "data:application/pdf;base64,…"} | 文档(PDF、Word、PowerPoint 或 Excel):在 file_data 中放 data: URL,或在 file_url 中放 http(s) 地址。 | Shannon 3 系列 |
在 Shannon 档位上,图片和文件从 input 的最后一个 user 项中读取。大小和限制见专门的页面。 图片与文件
带有指令和选项的请求
这个请求发送了指令、以输入项表示的对话、输出限制、温度和推理强度。它使用托管开源权重模型,这些设置都会被应用。
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.shannon-ai.com/v1",
)
response = client.responses.create(
model="DeepSeek-V4-Flash-0731-W4A16-AUTOROUND-REAP",
instructions="You are a physics teacher. Answer in two sentences.",
input=[
{"role": "user", "content": "Why is the sky blue?"},
{"role": "assistant", "content": "Air scatters blue light more than red light."},
{"role": "user", "content": "And why are sunsets red?"},
],
max_output_tokens=512,
temperature=0.3,
reasoning={"effort": "low"},
)
for item in response.output:
if item.type == "reasoning":
print("reasoning:", item.summary[0].text)
elif item.type == "message":
print("answer:", item.content[0].text)
print(response.usage) import OpenAI from "openai";
const client = new OpenAI({
apiKey: "YOUR_API_KEY",
baseURL: "https://api.shannon-ai.com/v1",
});
const response = await client.responses.create({
model: "DeepSeek-V4-Flash-0731-W4A16-AUTOROUND-REAP",
instructions: "You are a physics teacher. Answer in two sentences.",
input: [
{ role: "user", content: "Why is the sky blue?" },
{ role: "assistant", content: "Air scatters blue light more than red light." },
{ role: "user", content: "And why are sunsets red?" },
],
max_output_tokens: 512,
temperature: 0.3,
reasoning: { effort: "low" },
});
for (const item of response.output) {
if (item.type === "reasoning") console.log("reasoning:", item.summary[0].text);
if (item.type === "message") console.log("answer:", item.content[0].text);
}
console.log(response.usage); curl https://api.shannon-ai.com/v1/responses \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "DeepSeek-V4-Flash-0731-W4A16-AUTOROUND-REAP",
"instructions": "You are a physics teacher. Answer in two sentences.",
"input": [
{"role": "user", "content": "Why is the sky blue?"},
{"role": "assistant", "content": "Air scatters blue light more than red light."},
{"role": "user", "content": "And why are sunsets red?"}
],
"max_output_tokens": 512,
"temperature": 0.3,
"reasoning": {"effort": "low"}
}' 托管开源权重模型的回复包含 id、object、model、created_at、status、output 和 usage。其 usage 另外包含从缓存读取的 tokens 和用于推理的 tokens:
{
"usage": {
"input_tokens": 58,
"input_tokens_details": {
"cached_tokens": 0
},
"output_tokens": 67,
"output_tokens_details": {
"reasoning_tokens": 19
},
"total_tokens": 125
}
} 响应对象
id、object、status、output 和 usage 出现在每个回复中。请以它们为基础编写你的代码。
| 字段 | 类型 | 说明 | 发送者 |
|---|---|---|---|
id | string | resp_ 后跟 32 个十六进制字符。 | 所有模型 |
object | string | 始终为 response。 | 所有模型 |
status | string | completed。在流中它起初是 in_progress,在 response.failed 事件中是 failed。 | 所有模型 |
output | array | 按模型生成的顺序排列的输出项:reasoning、message、function_call。 | 所有模型 |
usage | object | input_tokens、output_tokens 和 total_tokens。 | 所有模型 |
usage.input_tokens_details | object | cached_tokens:从 prompt 缓存中读取的输入 tokens。 | 托管开源权重模型 |
usage.output_tokens_details | object | reasoning_tokens:用于推理的输出 tokens。 | 托管开源权重模型 |
model | string | 作答模型的规范 id。 | Shannon 3 系列、托管开源权重模型 |
created_at | integer | 回复的时间,以 Unix 秒表示。 | Shannon 3 系列、托管开源权重模型 |
instructions, tools, temperature, … | instructions、tools 和 temperature 会重复请求中的值。error 和 incomplete_details 为 null,metadata 为 {},parallel_tool_calls 为 true,tool_choice 为 auto,top_p 为 null。 | Shannon 3 系列 |
输出项
| 项 | 说明 |
|---|---|
{"id": "rs_…", "type": "reasoning", "summary": [{"type": "summary_text", "text": "…"}]} | 模型的推理,为一个 summary_text 部分。仅在模型进行了推理时出现。 |
{"id": "msg_…", "type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "…"}]} | 答案:一个带有文本的 output_text 部分。 |
{"id": "fc_…", "type": "function_call", "call_id": "call_…", "name": "…", "arguments": "…"} | 工具调用。arguments 是 JSON 字符串。请使用相同的 call_id 把结果发回。 |
OpenAI SDK 会替你把消息的文本拼接在 response.output_text 中。
流式传输
将 stream 设为 true 即可获得服务器发送事件。每个帧有一行 event:(事件名称)和一行 data:(JSON 对象);该对象在 type 中重复事件名称。请通过 output_index 把增量对应到其所属的项。
使用 OpenAI SDK 时,按 type 读取这些事件:
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.shannon-ai.com/v1",
)
stream = client.responses.create(
model="shannon-3",
input="Explain server-sent events in three sentences.",
stream=True,
)
for event in stream:
kind = getattr(event, "type", "error") # an event without a type is an error event
if kind == "response.reasoning_summary_text.delta":
pass # a piece of reasoning: event.delta
elif kind == "response.output_text.delta":
print(event.delta, end="", flush=True)
elif kind == "response.output_item.done" and event.item.type == "function_call":
print("\ntool call:", event.item.name, event.item.arguments)
elif kind == "response.completed":
print("\n", event.response.usage)
elif kind in ("response.failed", "error"):
raise RuntimeError("the stream failed, send the request again") import OpenAI from "openai";
const client = new OpenAI({
apiKey: "YOUR_API_KEY",
baseURL: "https://api.shannon-ai.com/v1",
});
const stream = await client.responses.create({
model: "shannon-3",
input: "Explain server-sent events in three sentences.",
stream: true,
});
for await (const event of stream) {
if (event.type === "response.reasoning_summary_text.delta") {
// a piece of reasoning: event.delta
} else if (event.type === "response.output_text.delta") {
process.stdout.write(event.delta);
} else if (event.type === "response.output_item.done" && event.item.type === "function_call") {
console.log("\ntool call:", event.item.name, event.item.arguments);
} else if (event.type === "response.completed") {
console.log("\n", event.response.usage);
} else if (event.type === "response.failed" || event.type === "error") {
throw new Error("the stream failed, send the request again");
}
} curl -N https://api.shannon-ai.com/v1/responses \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "shannon-3",
"input": "Explain server-sent events in three sentences.",
"stream": true
}' 事件按以下顺序到达。推理、消息和工具调用的各组仅在回复中包含它们时才会出现。
| 事件 | 载荷 | 何时 |
|---|---|---|
response.created | response | 始终最先到达。response.status 为 in_progress,response.output 为空。 |
response.in_progress | response | 始终第二个到达,对象与前者相同。 |
response.output_item.added | output_index, item | 推理开始:一个 summary 为空的 reasoning 项。 |
response.reasoning_summary_text.delta | output_index, summary_index, delta | 推理的一段。 |
response.reasoning_summary_text.done | output_index, summary_index, text | 推理完成:其完整的 text。 |
response.output_item.done | output_index, item | 已完成的 reasoning 项。 |
response.output_item.added | output_index, item | 答案开始:一个状态为 in_progress、没有内容的 message 项。 |
response.content_part.added | output_index, content_index, part | 一个空的 output_text 部分打开。 |
response.output_text.delta | output_index, content_index, delta | 答案的一段。 |
response.output_text.done | output_index, content_index, text | 答案完成:其完整的 text。 |
response.content_part.done | output_index, content_index, part | 已完成的 output_text 部分。 |
response.output_item.done | output_index, item | 已完成的 message 项,状态为 completed。 |
response.output_item.added | output_index, item | 工具调用开始:一个带有 call_id、name 和空 arguments 的 function_call 项。 |
response.function_call_arguments.delta | output_index, delta | 调用的参数,在一个增量中完整给出。 |
response.function_call_arguments.done | output_index, arguments | 同样的参数,以 arguments 给出。 |
response.output_item.done | output_index, item | 已完成的 function_call 项。 |
response.completed | response | 成功时始终最后到达:包含 output 和 usage 的完整响应对象。 |
event: response.created
data: {"type":"response.created","response":{"id":"resp_5f0c…","object":"response","status":"in_progress","output":[], …}}
event: response.in_progress
data: {"type":"response.in_progress","response":{"id":"resp_5f0c…","object":"response","status":"in_progress","output":[], …}}
event: response.output_item.added
data: {"type":"response.output_item.added","output_index":0,"item":{"id":"msg_1c7b…","type":"message","role":"assistant","status":"in_progress","content":[]}}
event: response.content_part.added
data: {"type":"response.content_part.added","output_index":0,"content_index":0,"part":{"type":"output_text","text":""}}
event: response.output_text.delta
data: {"type":"response.output_text.delta","output_index":0,"content_index":0,"delta":"Server-sent"}
event: response.output_text.delta
data: {"type":"response.output_text.delta","output_index":0,"content_index":0,"delta":" events let a server push text over one HTTP reply."}
event: response.output_text.done
data: {"type":"response.output_text.done","output_index":0,"content_index":0,"text":"Server-sent events let a server push text over one HTTP reply."}
event: response.content_part.done
data: {"type":"response.content_part.done","output_index":0,"content_index":0,"part":{"type":"output_text","text":"Server-sent events let a server push text over one HTTP reply."}}
event: response.output_item.done
data: {"type":"response.output_item.done","output_index":0,"item":{"id":"msg_1c7b…","type":"message","role":"assistant","status":"completed","content":[{"type":"output_text","text":"Server-sent events let a server push text over one HTTP reply.","annotations":[]}]}}
event: response.completed
data: {"type":"response.completed","response":{"id":"resp_5f0c…","object":"response","status":"completed","output":[…],"usage":{"input_tokens":1190,"output_tokens":18,"total_tokens":1208}, …}} 失败的流
在 Shannon 档位上,失败的回复以 response.failed 结束,取代 response.completed。其 response.status 为 failed,response.error 包含一个 code(rate_limit_exceeded 或 server_error)和一个 message。
在托管开源权重模型上,失败表现为一个 error 事件,带有 code 为 api_error 和一个 message。其后仍会有 response.completed。
当流中出现 response.failed 或 error 事件时,应将该流视为失败,并重新发送请求。
工具
工具是由你的代码运行的函数。请在 tools 中描述它;当模型需要它时,回复中会包含一个 function_call 项,取代消息或与消息并列。
tools 中的工具定义:
[
{
"type": "function",
"name": "get_weather",
"description": "Current weather for a city.",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string"
}
},
"required": [
"city"
]
}
}
] 调用它的回复的 output:
[
{
"id": "call_3d9a7c1e5b2f4a60c8e1d7f09b24a6c5",
"type": "function_call",
"name": "get_weather",
"call_id": "call_3d9a7c1e5b2f4a60c8e1d7f09b24a6c5",
"arguments": "{\"city\":\"Paris\"}"
}
] 运行该函数,然后再次发送请求,并把该调用及其结果添加到 input 中:
[
{
"role": "user",
"content": "What is the weather in Paris?"
},
{
"type": "function_call",
"call_id": "call_3d9a7c1e5b2f4a60c8e1d7f09b24a6c5",
"name": "get_weather",
"arguments": "{\"city\":\"Paris\"}"
},
{
"type": "function_call_output",
"call_id": "call_3d9a7c1e5b2f4a60c8e1d7f09b24a6c5",
"output": "{\"temperature_c\": 18, \"sky\": \"cloudy\"}"
}
] 只读取类型为 function 的工具。在 shannon-1.6-*、shannon-2-* 和 shannon-coder-1 上,parameters schema 会被精简为通用的 JSON Schema 关键字:oneOf 按 anyOf 处理,$ref、additionalProperties、const、default 和 title 等关键字不会传给模型。
tool_choice 的取值 required 和指定名称的函数,由托管开源权重模型应用。
工具循环在专门的页面中有完整说明。 函数调用
结构化输出
这种格式把结构化输出写作 text.format。schema 直接放在 format 中,与 name 和 strict 并列,而不是像 Chat Completions 那样位于 json_schema 成员之下。
{"type": "json_object"}要求返回任意 JSON 对象。{"type": "json_schema", "name", "schema", "strict"}要求返回符合你的 schema 的 JSON。省略strict时它为true。
{
"model": "shannon-1.6-lite",
"input": "Extract the city and the date: 'The conference opens in Lisbon on 12 May 2027.'",
"text": {
"format": {
"type": "json_schema",
"name": "event",
"strict": true,
"schema": {
"type": "object",
"properties": {
"city": {
"type": "string"
},
"date": {
"type": "string",
"description": "ISO 8601 date"
}
},
"required": [
"city",
"date"
]
}
}
}
} JSON 以文本形式出现在消息的 output_text 部分中;请自行解析。不支持结构化输出的托管开源权重模型会返回 400。
{"city": "Lisbon", "date": "2027-05-12"} 哪个模型接受哪种形式,在专门的页面中列出。 结构化输出
推理
会推理的模型把推理作为类型为 reasoning 的输出项返回,位于消息之前。在流中,它以 response.reasoning_summary_text.delta 事件的形式到达。
托管开源权重模型会应用 reasoning.effort:off、low、medium 或 high;什么都不发送时为 high。off 不返回推理项。请以对象形式发送;此端点不读取单独的字符串。
各个 effort 级别在专门的页面中说明。 推理强度
输出限制
不发送 max_output_tokens 时它为 4,096。它是请求开始时从你的余额中预留的 tokens 数量;回复完成后,这个预留量会被请求实际使用的量替换。如果某个值超出了你的剩余余额,会返回 429 Quota exceeded。
它限制 shannon-1.6-*、shannon-2-* 和 shannon-coder-1 的回复长度,以及托管开源权重模型的答案文本长度。
在此端点上,shannon-coder-1 与其他所有模型一样,按 tokens 从你的余额中计费。
请求体最大可达 32 MiB。 限制与余额
错误
错误使用 OpenAI 的错误体:一个带有 type 和 message 的 error 对象;有些还带有值为 null 的 code 和 param。表中列出了此端点最常返回的错误。完整列表以及哪些情况应重试,见专门的页面。 错误处理
| 状态 | 类型 | 消息 | 何时 |
|---|---|---|---|
401 | authentication_error | Missing authenticationInvalid API key | 没有发送 API 密钥,或密钥未知或已被撤销。 |
400 | invalid_request_error | unknown model: <id> | 缺少 model,或它不是已发布的 id。 |
400 | invalid_request_error | No user message provided. | Shannon 档位:input 中没有用户文本。 |
400 | invalid_request_error | <id> does not accept image input | 向不支持图片输入的托管开源权重模型发送了图片。 |
400 | invalid_request_error | <id> does not accept response_format | 向不支持结构化输出的托管开源权重模型发送了 text.format。 |
400 | invalid_request_error | unknown reasoning effort '<value>'; expected off, low, medium or high | reasoning.effort 的值不在列表之内。 |
422 | invalid_request_error | Failed to deserialize the JSON body into the target type: … | 请求体是有效的 JSON,但某个字段的类型错误。 |
429 | rate_limit_error | Quota exceeded. Upgrade your plan at shannon-ai.com/plan | max_output_tokens 大于你的余额剩余部分。 |
429 | rate_limit_error | Too many requests. Retry in <n>s. | 洪水防护:你的账户在一分钟内发出了超过 120 个请求。 |
500 | api_error | The model backend failed to answer. Please retry. | 模型没有产生回复。请重新发送请求。 |
502 | api_error | The model backend failed to answer. Please retry. | 同上,出现在托管开源权重模型上。 |
504 | api_error | upstream timed out | 托管开源权重模型耗时超过了非流式回复的时间限制。请将 stream 设为 true 后发送。 |