补全
OpenAI 兼容的 Chat Completions
OpenAI Chat Completions API 的即插即用替代方案。将 OpenAI SDK 指向 Theo,无需改动现有代码即可继续使用。
POST
/
api
/
v1
/
chat
/
completions
OpenAI 兼容的 Chat Completions
curl --request POST \
--url https://api.example.com/api/v1/chat/completions \
--header 'Content-Type: application/json' \
--data '
{
"model": "<string>",
"messages": [
{}
],
"stream": true,
"temperature": 123,
"conversation_id": "<string>",
"skills": [
"<string>"
],
"metadata": {}
}
'import requests
url = "https://api.example.com/api/v1/chat/completions"
payload = {
"model": "<string>",
"messages": [{}],
"stream": True,
"temperature": 123,
"conversation_id": "<string>",
"skills": ["<string>"],
"metadata": {}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
model: '<string>',
messages: [{}],
stream: true,
temperature: 123,
conversation_id: '<string>',
skills: ['<string>'],
metadata: {}
})
};
fetch('https://api.example.com/api/v1/chat/completions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/api/v1/chat/completions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => '<string>',
'messages' => [
[
]
],
'stream' => true,
'temperature' => 123,
'conversation_id' => '<string>',
'skills' => [
'<string>'
],
'metadata' => [
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/api/v1/chat/completions"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"messages\": [\n {}\n ],\n \"stream\": true,\n \"temperature\": 123,\n \"conversation_id\": \"<string>\",\n \"skills\": [\n \"<string>\"\n ],\n \"metadata\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/api/v1/chat/completions")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"messages\": [\n {}\n ],\n \"stream\": true,\n \"temperature\": 123,\n \"conversation_id\": \"<string>\",\n \"skills\": [\n \"<string>\"\n ],\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/v1/chat/completions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"<string>\",\n \"messages\": [\n {}\n ],\n \"stream\": true,\n \"temperature\": 123,\n \"conversation_id\": \"<string>\",\n \"skills\": [\n \"<string>\"\n ],\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_bodyTheo 在
支持的
传入任意 Theo 品牌模型 ID。推荐使用
未知的模型字符串会回退到
何时改用
POST /api/v1/chat/completions 上实现了 OpenAI Chat Completions 通信协议。任何使用 OpenAI SDK 的应用都可以将 baseURL 指向 https://www.hitheo.ai/api/v1,换上 Theo API 密钥即可正常运行——该端点接受相同的 { model, messages, stream, temperature, ... } 结构,并返回相同的 chat.completion / chat.completion.chunk 对象。
响应结构与 OpenAI 完全一致。底层的路由则由 Theo 负责——意图分类、模型选择与自动故障转移。传入
model: "theo-1-auto" 可让 Theo 为每个请求选择最合适的引擎。基础 URL
请使用规范的www 主机名。OpenAI SDK 会在其后追加 /chat/completions,因此该基础 URL 最终会解析到真实的 POST /api/v1/chat/completions 路由:
https://www.hitheo.ai/api/v1
务必使用
www 主机名。裸域名 https://hitheo.ai 会以 307 重定向到 www,而大多数 HTTP 客户端在跨重定向时会剥离 Authorization 头——请求会以未认证状态到达,并返回 401。身份验证
使用标准的 Bearer 令牌请求头。你的 Theo API 密钥将替代原来的 OpenAI 密钥。Authorization: Bearer theo_sk_...
即插即用示例(OpenAI SDK)
import OpenAI from "openai";
const theo = new OpenAI({
apiKey: process.env.THEO_API_KEY,
baseURL: "https://www.hitheo.ai/api/v1",
});
const res = await theo.chat.completions.create({
model: "theo-1-auto",
messages: [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "Write me a haiku about Miami." },
],
});
console.log(res.choices[0].message.content);
from openai import OpenAI
theo = OpenAI(
api_key=os.environ["THEO_API_KEY"],
base_url="https://www.hitheo.ai/api/v1",
)
res = theo.chat.completions.create(
model="theo-1-auto",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Write me a haiku about Miami."},
],
)
print(res.choices[0].message.content)
curl -X POST https://www.hitheo.ai/api/v1/chat/completions \
-H "Authorization: Bearer $THEO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "theo-1-auto",
"messages": [
{ "role": "user", "content": "Write me a haiku about Miami." }
]
}'
流式响应
将stream 设为 true,即可接收以 data: [DONE] 结尾的 chat.completion.chunk 对象 SSE 流,行为与 OpenAI 完全一致。
const stream = await theo.chat.completions.create({
model: "theo-1-auto",
messages: [{ role: "user", content: "Stream me a short poem." }],
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
支持的 model 取值
传入任意 Theo 品牌模型 ID。推荐使用 theo-1-auto,让 Theo 的意图分类器为每个请求挑选最合适的引擎;如果你想固定路由,也可以传入具体的引擎。
| 模型 ID | Theo 模式 | 最适用场景 |
|---|---|---|
theo-1-auto | auto | 让 Theo 为每条提示选择合适的引擎 |
theo-1-flash | fast | 快速响应、简短对话、分类任务 |
theo-1-reason | think | 深度推理、分析、规划 |
theo-1-code | code | 代码生成与审查 |
theo-1-create | image | 图像生成 |
theo-1-motion | video | 视频生成 |
theo-1-research | research | 带引用的多步网络研究 |
theo-1-roast | roast | 不加过滤的幽默与犀利吐槽 |
theo-1-genui | genui | 生成式 UI 组件 |
theo-1-analyze | domain_analysis | 面向业务运营、财务与合规的领域分析 |
theo-1-extract | data_extraction | OCR 与结构化数据提取 |
theo-1-vision | vision | 多模态图像分析 |
auto,Theo 会像处理其他任何提示一样为该请求路由。
请求体
请求体沿用标准的 OpenAI Chat Completion 结构。下方未列出的字段仍会被接受,但会被忽略(例如top_p、n、max_tokens、user)。
string
默认值:"theo-1-auto"
一个 Theo 模型 ID。有效取值参见上方表格。
object[]
必填
到目前为止的对话内容。每条消息包含
{ role, content }。支持的角色有:system、user、assistant。tool 消息会被接受但忽略(工具调用状态由 Theo 内部管理)。最后一条 user 消息会被视为提示。所有 system 消息会被合并为单一的系统提示,覆盖 Theo 的默认角色设定。此前的 user/assistant 轮次会作为对话上下文注入。boolean
默认值:"false"
当设为
true 时,返回以 data: [DONE] 结尾的 chat.completion.chunk 对象 SSE 流。number
采样温度(0–2)。
string
Theo 专属参数。 将此次补全关联到一个已有的 Theo 对话,使其记忆能够跨渠道持续保留。省略此参数则发送无状态请求。
string[]
Theo 专属参数。 按 slug 为本次请求激活技能。会与用户已安装的技能合并。
object
Theo 专属参数。 附加到审计日志中的任意键值数据。
响应
标准的 OpenAIchat.completion(流式时为 chat.completion.chunk)。Theo 专属的元数据会以 theo_metadata 扩展字段返回,以避免与现有 OpenAI 客户端的预期结构冲突。
{
"id": "chatcmpl_...",
"object": "chat.completion",
"created": 1715872800,
"model": "theo-1-flash",
"choices": [
{
"index": 0,
"message": { "role": "assistant", "content": "Neon waves on sand..." },
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 24,
"completion_tokens": 38,
"total_tokens": 62
},
"theo_metadata": {
"mode": "auto",
"resolved_mode": "fast",
"tools_used": [],
"artifacts": [],
"engine": "theo-core"
}
}
何时改用 /v1/completions
- 你需要的是单轮提示字符串,而不是消息数组。
- 你想要更丰富的原生 Theo 响应(后续追问、产物、工具调用轨迹),而不是 OpenAI 的结构。
- 你想在每次请求中单独控制
persona或response_style。
同样适用按密钥编排
该端点运行的是与原生端点完全相同的按密钥编排:无论你为该 API 密钥配置了什么——编排器图谱、模型锁定、网关护栏、路由工作室偏好设置、模型允许列表,以及上下文窗口保护——都会同样作用于此处的请求。因此,无论你是通过 OpenAI SDK 还是原生 API 调用,一个你在控制台或通过 MCP 工具配置好的密钥都会表现一致。护栏可以拒绝请求(422),超出该密钥允许列表的模型会被拒绝(403),超出体积的请求会返回 400 context_length_exceeded。没有此类配置的密钥不受影响——它们仍会按 Theo 的默认设置路由,与以往一致。
错误
返回与其他所有 v1 端点相同的错误信封:{
"error": {
"message": "Validation failed: messages must contain at least one message.",
"type": "invalid_request_error",
"code": "validation_error"
}
}
| 状态码 | 错误码 | 描述 |
|---|---|---|
| 400 | validation_error | messages 缺失、为空或格式错误 |
| 400 | empty_prompt | messages 中只包含 system/tool 消息 |
| 400 | context_length_exceeded | 请求体量超出该密钥所有模型能容纳的上限——请在编排器中添加上下文更大的模型,或缩短请求内容 |
| 401 | invalid_api_key | Authorization: Bearer theo_sk_... 缺失或无效 |
| 402 | insufficient_credits | 账户余额不足以完成预扣(pre-flight reservation) |
| 403 | model_not_allowed | 请求解析到的模型不在该密钥的模型允许列表中 |
| 422 | guardrail_violation | 该密钥上的网关护栏策略拒绝了此请求 |
| 422 | orchestrator_no_path | 该密钥的编排器图谱未能为此请求解析出有效路径 |
| 404 | not_found | 未找到 conversation_id |
| 429 | rate_limit_exceeded | 请查看 Retry-After |
| 500 | server_error | 内部错误 |
此页面对您有帮助吗?
OpenAI 兼容的 Chat Completions
curl --request POST \
--url https://api.example.com/api/v1/chat/completions \
--header 'Content-Type: application/json' \
--data '
{
"model": "<string>",
"messages": [
{}
],
"stream": true,
"temperature": 123,
"conversation_id": "<string>",
"skills": [
"<string>"
],
"metadata": {}
}
'import requests
url = "https://api.example.com/api/v1/chat/completions"
payload = {
"model": "<string>",
"messages": [{}],
"stream": True,
"temperature": 123,
"conversation_id": "<string>",
"skills": ["<string>"],
"metadata": {}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
model: '<string>',
messages: [{}],
stream: true,
temperature: 123,
conversation_id: '<string>',
skills: ['<string>'],
metadata: {}
})
};
fetch('https://api.example.com/api/v1/chat/completions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/api/v1/chat/completions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => '<string>',
'messages' => [
[
]
],
'stream' => true,
'temperature' => 123,
'conversation_id' => '<string>',
'skills' => [
'<string>'
],
'metadata' => [
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/api/v1/chat/completions"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"messages\": [\n {}\n ],\n \"stream\": true,\n \"temperature\": 123,\n \"conversation_id\": \"<string>\",\n \"skills\": [\n \"<string>\"\n ],\n \"metadata\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/api/v1/chat/completions")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"messages\": [\n {}\n ],\n \"stream\": true,\n \"temperature\": 123,\n \"conversation_id\": \"<string>\",\n \"skills\": [\n \"<string>\"\n ],\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/v1/chat/completions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"<string>\",\n \"messages\": [\n {}\n ],\n \"stream\": true,\n \"temperature\": 123,\n \"conversation_id\": \"<string>\",\n \"skills\": [\n \"<string>\"\n ],\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_body