概览
State API 从你上传的历史对话中学习 User 一方的表达习惯与决策偏好,在不改动基座模型权重的前提下,在模型表征层构建出专属的 State。
构建完成后,调用 /completions 即可根据当前对话上下文生成 User 的下一条消息。每个 API Key 对应一个独立的 State,完整的 OpenAPI 定义见 GET /openapi.yaml。
鉴权
接口采用 API Key 鉴权。如需申请 Key,请发送邮件至 hello@topovoid.com。拿到新 Key 后,需先调用一次 /register 完成激活。
除 /register 和 /openapi.yaml 外,其余接口均需在请求头中携带 Authorization: Bearer $TOPOVOID_API_KEY。请妥善保管 API Key,切勿将其硬编码或暴露在浏览器、移动端等客户端代码中。
POST/registerKey 放在请求体中
激活并注册 API Key。该接口幂等,重复调用不会产生副作用。
| 参数 | 类型 | 说明 |
|---|---|---|
apikey |
string | 必填。待注册的 API Key |
成功时返回 {"ok": true, "user_id": "..."}。
curl https://api.topovoid.com/reflecho/register \
-H "Content-Type: application/json" \
-d "{\"apikey\": \"$TOPOVOID_API_KEY\"}"上传对话
POST/upload需要 Bearer Key
批量上传用于训练的对话记录(请求体为对话对象的 JSON 数组,支持传入 Content-Encoding: gzip 压缩数据)。如果传入的对话 id 已存在,新内容会直接覆盖原有记录;将 value 设为 null 则会删除对应 id 的对话。
| 参数 | 类型 | 说明 |
|---|---|---|
id |
string | 必填。对话唯一标识 |
value |
object 或 null | 必填。格式为 {"messages": [...]};传入 null 时删除该条对话 |
messages 数组中每条消息的字段如下:
| 参数 | 类型 | 说明 |
|---|---|---|
type |
string | 消息角色:User、Assistant、AssistantThink 或 ToolCall |
content |
string | 消息正文 |
name |
string | 工具名称(仅 ToolCall 类型需要) |
每段对话必须以 User 消息收尾,且任意两条 User 消息之间至少要隔一条其他角色的消息。AssistantThink 和 ToolCall 仅作为上下文保留,不直接参与训练损失计算。
上传成功返回 204 No Content。
[
{
"id": "0199f1a2-6c3e-7d10-9a4b-2f8e5c1d7a30",
"value": {
"messages": [
{ "type": "User", "content": "请检查服务入口。" },
{ "type": "Assistant", "content": "当前入口把配置读取和服务启动耦合在一起。" },
{ "type": "User", "content": "先别直接改,先把测试结果给我看。" }
]
}
}
]curl https://api.topovoid.com/reflecho/upload \
-H "Authorization: Bearer $TOPOVOID_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @sessions.json构建 State
POST/flush-state需要 Bearer Key
汇总当前已上传的全部对话,在后台启动一次 State 训练。新训练出的 State 通过自动评测后会自动切换上线;若构建或评测未通过,线上将继续保留原有的 State 不变。
发起构建前至少需要积累 10 条有效训练样本——对话中每一条有前文铺垫的 User 消息(即非首条消息)计为 1 条样本。请求体可以为空,所有训练超参均为可选,未指定时默认采用 fast 预设:
| 参数 | 类型 | 说明 |
|---|---|---|
preset |
string | 预设档位:fast(默认)或 full |
learning_rate |
number | 峰值学习率,取值范围 (0, 0.001] |
epochs |
integer | 最大训练轮数,取值范围 1–10 |
train_token_budget |
integer 或 null | 训练总 token 数上限(不少于 10000);传 null 表示不设上限 |
| 预设项 | fast |
full |
|---|---|---|
| 训练 token 上限 | 300,000 | 不设上限 |
| 最大训练轮数 | 2 | 2 |
| 单条样本最大长度 | 4,096 tokens | 8,192 tokens |
| 峰值学习率 | 2e-4 | 1e-4 |
| 预计耗时 | 约 9 分钟 | 数十分钟至数小时 |
请求成功受理后返回 202 Accepted,响应体结构与 /state-status 一致。
curl https://api.topovoid.com/reflecho/flush-state \
-H "Authorization: Bearer $TOPOVOID_API_KEY" \
-H "Content-Type: application/json" \
-d '{"preset": "full"}'查询构建状态
GET/state-status需要 Bearer Key
查询最近一次 State 构建任务的实时进度。轮询间隔建议设为 30 秒左右。
| 字段 | 类型 | 说明 |
|---|---|---|
status |
string | 任务状态:building、finished 或 failed |
phase |
string | 当前所处阶段:queued、preparing、training、checking 或 activating |
progress |
object | 训练步数进度 |
active |
object 或 null | 当前在线生效的 State 信息(尚未生成过可用 State 时为 null) |
reason |
string | 失败原因代码:no_dev_improvement(验证集表现未超越基模,通常需要补充更多对话样本)、generation_check_failed、consistency_check_failed、training_error 或 internal_error |
curl https://api.topovoid.com/reflecho/state-status \
-H "Authorization: Bearer $TOPOVOID_API_KEY"{
"status": "building",
"phase": "training",
"progress": { "attempt": 1, "step": 18, "total_steps": 37 },
"start_at": "2026-10-16T08:12:03.418+00:00",
"active": null
}生成消息
POST/completions需要 Bearer Key
给定当前对话上下文,加载当前生效的 State,模拟 User 的口吻与偏好生成下一条消息。
| 参数 | 类型 | 说明 |
|---|---|---|
id |
string | 必填。本次请求的唯一标识 |
context |
string | 必填。拼接好的对话上下文,具体拼法见下方上下文格式 |
systemprompt |
string | 可选。自定义系统提示词(注意:State 仅在默认系统提示词下训练,替换后可能影响效果) |
thinking |
string | 可选。思考模式档位:off(默认)、low、medium 或 xhigh |
| 响应字段 | 类型 | 说明 |
|---|---|---|
response |
string | 模型生成的 User 回复内容 |
time |
integer | 端到端生成耗时(毫秒) |
confidence |
number 或 null | 输出 token 概率的几何平均值;启用 thinking 时固定为 null |
curl https://api.topovoid.com/reflecho/completions \
-H "Authorization: Bearer $TOPOVOID_API_KEY" \
-H "Content-Type: application/json" \
-d '{"id": "0199f1a2-8b40-7c55-a1d3-5e7f00c2b9a4",
"context": "User: 测试已经通过,可以提交。\n\nAssistant:"}'{
"response": "再覆盖一下失败路径。",
"time": 1842,
"confidence": 0.74
}上下文格式
由于底层模型始终以 Assistant: 作为续写触发标记,而 State 扮演的是对话中的 User,因此在拼接 context 字符串时,需要将角色标签对调:把原对话里的 User 标为 Assistant:,把原对话里的 Assistant 标为 User:。每条消息之间空一行,末尾固定以 Assistant: 结束(剔除 AssistantThink 和 ToolCall 消息):
Assistant: 请检查服务入口。
User: 当前入口把配置读取和服务启动耦合在一起。
Assistant: 先别直接改,先把测试结果给我看。
User: 测试已经通过,可以提交。
Assistant:错误
当请求出错时,服务端返回形如 {"code": "...", "message": "..."} 的 JSON 响应体。建议在代码中依据稳定的 code 字段做分支处理:
| 状态码 | code |
触发原因 |
|---|---|---|
| 400 | bad_request |
请求参数格式有误、有效训练样本不足 10 条,或上下文超出最大长度限制 |
| 401 | unauthorized |
未携带 API Key 或传入的 Key 无效 |
| 404 | not_found |
API Key 尚未调用 /register 注册、名下还未上传过对话,或尚未发起过构建 |
| 405 | method_not_allowed |
HTTP 请求方法不匹配 |
| 409 | conflict |
当前已有构建任务正在排队或执行中,或在尚无可用 State 时调用了 /completions |
| 413 | payload_too_large |
请求体体积超出限制 |
| 415 | unsupported_content_encoding |
使用了除 gzip 以外的压缩编码 |
| 500 | internal_error |
服务端内部异常 |
| 503 | service_unavailable |
服务繁忙或暂时不可用 |
使用限制
- 单次请求的上下文提示词上限约为 32,000 tokens。
/completions固定返回完整 JSON 响应,暂不支持流式传输(streaming)。- 构建任务与生成请求按提交顺序排队执行,高峰期可能存在短暂排队。
- 上传的训练对话会持久保存,直至你主动通过
/upload将其置为null删除;每次生成请求及其返回结果会在服务端留存日志。