通过任务管理 API,您可以预估任务 Token 数与费用、提交结构预测或虚拟筛选任务、查询任务状态、获取预测产物、分页查看历史任务,以及取消尚未开始运行的任务。
本文是所有任务类型共用的接口参考,说明请求与响应字段、任务状态及错误处理。input 的具体格式、输入限制、调用流程和结果解读,请按任务类型查阅对应指南。
任务类型与使用指南
task_type | 任务类型 | 输入与使用指南 |
|---|---|---|
1 | 结构预测(默认) | 结构预测使用指南 |
2 | 虚拟筛选 | 虚拟筛选使用指南 |
询价与创建使用相同的 model、task_type 和 input。input 必须符合所选任务类型的定义。
接口总览
| 接口名称 | 请求方法 | 请求路径 | 描述 |
|---|---|---|---|
| 任务询价 | POST | /v1/tasks/quote | 预估任务 Token 数与所需点数 |
| 提交推理任务 | POST | /v1/tasks/create | 提交一个结构预测或虚拟筛选任务 |
| 查询任务状态 | GET | /v1/tasks/status | 轻量查询状态、结果地址和任务错误,推荐用于等待任务 |
| 查询任务详情 | GET | /v1/tasks/query | 根据任务 ID 查询状态与结果 |
| 查询任务列表 | GET | /v1/tasks/list | 分页获取当前账号的任务列表 |
| 取消任务 | POST | /v1/tasks/cancel | 取消 CREATED 或 QUEUED 状态的任务 |
通用说明
请求基地址
https://api.atomelody.com
所有请求均使用 HTTPS。包含 JSON 请求体的接口应发送 Content-Type: application/json。
鉴权方式
每次请求都需要在 HTTP 请求头中携带 API Key:
Authorization: Bearer <YOUR_API_KEY>
API Key 可在控制台的 API Key 凭据 页面创建和管理。
统一响应格式
调用成功时,响应封装如下;data 的字段由具体接口定义:
{
"code": "OK",
"message": "OK",
"data": {}
}
调用失败时,HTTP 状态码与具体错误相对应,响应中不包含 data:
{
"code": "INVALID_SEQUENCE",
"message": "Sequence 1 is invalid: the protein sequence contains unsupported character \"X\" at position 4."
}
code 是稳定的机器可读错误类型;message 是针对本次失败生成的详细说明,同一错误码可能对应不同文案。请同时检查 HTTP 状态码和 code,不要根据 message 文本编写程序分支。
本文的响应示例和字段表只列出外部客户端建议依赖的稳定字段。响应可能包含额外元数据;客户端应忽略未在本文中说明的字段。
任务状态
status | 状态 | 含义 | 可取消 |
|---|---|---|---|
1 | CREATED | 任务已创建,等待进入处理队列 | 是 |
2 | QUEUED | 任务已进入处理队列 | 是 |
3 | RUNNING | 任务正在计算 | 否 |
4 | COMPLETED | 任务成功完成,可获取预测产物 | 否 |
5 | FAILED | 任务执行失败 | 否 |
6 | CANCELLED | 任务已取消 | 否 |
COMPLETED、FAILED 和 CANCELLED 均为最终状态。虚拟筛选在部分候选成功时也返回 COMPLETED,具体含义见筛选任务状态说明。任务失败或取消后,预占点数会自动释放;详情参阅计价与配额规则。
平台会根据账户与系统运行策略控制可同时排队或运行的任务数量。超过当前并发处理范围的任务会暂时保持 CREATED 状态,并在已有任务结束后按队列顺序自动进入处理流程;具体限制不作为固定 API 契约。
任务询价
在提交预测任务前,您可以通过此接口查询任务的 Token 总数与预估费用。询价不会创建任务、执行推理,也不会预占或扣除点数。
请求
POST /v1/tasks/quote
| 字段 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
model | string | 否 | "Melo-1" | 预测模型;目前仅支持 Melo-1 |
task_type | int | 否 | 1 | 任务类型;1 为结构预测,2 为虚拟筛选 |
input | object | 是 | - | 待询价的任务输入对象,与创建任务相同;格式见对应使用指南 |
接口按所选任务类型校验输入和额度限制,输入无效时返回相应错误,不会返回报价。询价无需提供任务名称。完整请求示例见结构预测询价和虚拟筛选询价。
响应
以下为结构预测任务的询价响应示例;虚拟筛选还会返回下表中的 candidate_costs。
{
"code": "OK",
"message": "OK",
"data": {
"token_num": 4,
"base_cost": 10,
"quantity": 1,
"estimated_cost": 10
}
}
| 字段 | 类型 | 描述 |
|---|---|---|
token_num | int64 | 结构预测的任务 Token 总数;虚拟筛选为所有“靶点 + 候选”组合的 Token 数之和 |
base_cost | int64 | 基础费用(算力点数),未应用计费数量和优惠;结构预测按实际 Token 档位计算,虚拟筛选为各组合基础费用之和 |
quantity | int32 | 计费数量,始终返回;Melo-1 结构预测为实际采用的 num_seeds(省略时为 1),虚拟筛选为 1,不是候选数量 |
estimated_cost | int64 | 预估所需算力点数;结构预测已包含 num_seeds 倍数,虚拟筛选为各组合费用之和,实际费用以创建任务时为准 |
candidate_costs | array | 仅虚拟筛选返回,按输入候选顺序排列的逐候选报价 |
candidate_costs[].candidate_id | string | 输入中的候选 ID |
candidate_costs[].token_num | int64 | 靶点与当前候选组合的 Token 数 |
candidate_costs[].estimated_cost | int64 | 当前组合的预估点数 |
上例表示任务共 4 个 Token,使用默认的 1 个 seed,预估消耗 10 点。计价方式见计价与配额规则。确认后,您可使用相同的 model、task_type 和 input 调用提交推理任务接口,并在创建响应的 billing_order.frozen 中查看本次任务实际预占的点数。
相同输入设置 input.num_seeds: 20 时,token_num 仍为 4,base_cost 仍为 10,quantity 为 20,estimated_cost 为 200。当前预估费用为 base_cost × quantity;调用方应直接使用已应用全部计费规则的 estimated_cost,无需再次乘以数量或自行计算费用。
为避免询价后费用变化导致消耗超出预期,可将响应中的 data.estimated_cost 原值作为创建请求顶层的 max_cost。例如,上例对应 "max_cost": 10:创建时费用不超过 10 点则按当前费用创建,超过 10 点则返回 MAX_COST_EXCEEDED,不会创建任务或预占点数。
提交推理任务
请求
POST /v1/tasks/create
顶层参数
| 字段 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
model | string | 否 | "Melo-1" | 预测模型;目前仅支持 Melo-1 |
task_name | string | 否 | "" | 自定义任务名称,最多 20 个 Unicode 字符;不可仅包含空白,不可包含控制字符或 \\ / : * ? " < > | |
task_type | int | 否 | 1 | 任务类型;1 为结构预测,2 为虚拟筛选 |
max_cost | int64 | 否 | 0 | 本次任务允许的最大点数,与询价的 estimated_cost 单位一致;省略或为 0 表示不设置费用上限,负数无效 |
input | object | 是 | - | 任务输入对象,格式见对应使用指南 |
当 max_cost > 0 时,创建时计算的任务费用必须小于或等于该值;超过时返回 HTTP 400,错误码为 MAX_COST_EXCEEDED,message 包含当前费用和限制值。虚拟筛选按全部候选的总费用比较,现有 1,000 点的单任务费用上限仍然生效。该参数仅用于限制费用,实际预占点数以创建时计算的费用为准。
完整请求示例与分子输入说明见结构预测使用指南和虚拟筛选使用指南。
响应
{
"code": "OK",
"message": "OK",
"data": {
"task_id": "tk-01a05cc4a55c77c99fe3eb3203143713",
"status": 2,
"billing_order": {
"order_id": "bo-01a05cc4a55e7cd98219eb3f1b469d95",
"status": 1,
"frozen": 10,
"charged": 0
},
"balance": {
"available": 970,
"frozen": 10
}
}
}
| 字段 | 类型 | 描述 |
|---|---|---|
task_id | string | 任务唯一标识 |
status | int | 创建后的任务状态,通常为 CREATED 或 QUEUED |
billing_order.order_id | string | 本次任务对应的计费订单 ID |
billing_order.status | int | 1:冻结中;2:已结算;3:已解冻 |
billing_order.frozen | int64 | 本任务预占的点数 |
billing_order.charged | int64 | 已正式扣除的点数 |
balance.available | int64 | 账号当前可用点数 |
balance.frozen | int64 | 账号当前冻结点数 |
查询任务状态
GET /v1/tasks/status?task_id=<TASK_ID>
使用与其他任务接口相同的 API Key 鉴权,只能查询当前账号的任务。task_id 为必填查询参数。此接口适用于轮询任务状态和获取执行结果,无需再查询详情即可处理成功、失败或取消;需要输入、计费等信息时使用 /v1/tasks/query。
{
"code": "OK",
"message": "OK",
"data": {
"task_id": "tk-01a05cc4a55c77c99fe3eb3203143713",
"status": 3
}
}
| 字段 | 类型 | 描述 |
|---|---|---|
task_id | string | 任务唯一标识 |
status | int | 沿用任务状态的 1~6;4、5、6 为最终状态 |
output_url | string | 有结果时返回的 ZIP 临时下载地址,有效期 10 分钟;无结果时省略,过期后重新调用本接口获取 |
error | object | 有任务错误时返回,无错误时省略 |
error.code | string | 公开的阶段错误码:MSA_ERROR、INFERENCE_ERROR 或 TASK_ERROR,与详情接口一致 |
成功完成时会返回 output_url。虚拟筛选全部候选失败但已生成汇总结果时,status 为 5,仍会同时返回 output_url 和 error;请保留并处理该结果包。任务执行失败不等于查询失败:查询成功时顶层仍为 code: "OK"。
{
"code": "OK",
"message": "OK",
"data": {
"task_id": "tk-example",
"status": 5,
"output_url": "https://example.com/signed-summary-url",
"error": { "code": "INFERENCE_ERROR" }
}
}
若结果地址签名暂时失败,接口返回可重试的服务端错误,避免客户端把缺少下载地址的响应当作完整结果。
任务等待脚本
推理任务可能需要较长时间。等待脚本会自动查询任务状态,并在状态变化或任务结束时输出事件,方便在终端查看进度,也可集成到应用程序或自动化工作流中。
下载 Python 等待脚本,在本地或服务器上执行;需要 Python 3.9 或更高版本,无第三方依赖。也可以参考脚本实现,使用其他语言或工具完成相同的查询、等待和事件处理流程。
通过运行环境注入 ATOMELODY_API_KEY,不要把凭据写进脚本或事件输出。保存脚本为 wait_task.py 后执行:
python3 wait_task.py <TASK_ID> --max-wait 1800
脚本立即查询一次,后续间隔按约 15、30、60、120 秒递增,加入随机偏移并限制在 120 秒内。网络错误、HTTP 429 和 5xx 会有限重试,连续 5 次失败后退出;若服务端提供 Retry-After,等待时间至少遵守该值。鉴权、权限、任务不存在和响应格式错误直接退出。
输出采用 JSON Lines(每行一个 JSON 对象),及时刷新:首次读到非终态时输出当前状态;之后仅在状态变化时输出,状态不变保持静默。以下示例省略每条事件携带的 observed_at 时间戳:
{"event":"status_changed","task_id":"tk-example","previous_status":null,"status":2}
{"event":"status_changed","task_id":"tk-example","previous_status":2,"status":3}
{"event":"completed","task_id":"tk-example","status":4,"output_url":"https://example.com/signed-output-url"}
从 QUEUED 进入 RUNNING 的事件输出后,脚本继续运行。轮询可能跳过中间状态;首次查询就已结束时,只输出最终事件。
| 事件 | 退出码 | 处理方式 |
|---|---|---|
status_changed | 不退出 | 可更新用户可见进度,继续等待原进程,不重复启动等待脚本 |
completed | 0 | 使用 output_url 下载并处理结果 |
failed / cancelled | 1 | 查看任务终态及错误信息;若有 output_url,仍可下载汇总结果 |
error | 2 | 查询或配置错误,不表示推理任务失败;修复后使用同一任务 ID 重试 |
pending | 3 | 本次等待预算已用完,任务仍可能在执行;保留任务 ID |
interrupted | 130 | 用户中断了本地等待,服务端任务未被取消 |
--max-wait 默认 1800 秒,只控制本次本地等待,不取消服务端推理任务。请求时限会按剩余预算缩短,但 DNS 等底层网络操作可能令实际退出时间稍晚。重新运行脚本时仍使用原 task_id,不要重复创建任务。
运行与集成: 在终端运行时,可直接查看脚本输出;集成到应用程序或自动化工作流时,可按行读取事件,并通过进程退出码判断本次等待的结果。收到 status_changed 后脚本仍会继续运行,无需另外调用查询接口或启动新的等待进程。没有新输出通常表示任务状态没有变化,不必因此高频检查或重启脚本。
需要后台等待时,可使用运行环境提供的进程管理或完成通知能力。自动继续后续处理或发送通知,需要由调用程序或工作流配置,脚本本身只负责查询和输出事件。若本次等待结束但任务尚未完成,可保留任务 ID,稍后继续查询。
完成事件中的下载地址也只有 10 分钟有效期;下载时若已过期,重新调用 /v1/tasks/status 即可获取新地址。
查询任务详情
请求
GET /v1/tasks/query?task_id=<TASK_ID>
| 查询参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
task_id | string | 是 | 要查询的任务 ID |
响应
以下示例省略 input 的具体内容;完整响应会包含任务输入,其结构由 task_type 决定。
{
"code": "OK",
"message": "OK",
"data": {
"task_id": "tk-01a05cc4a55c77c99fe3eb3203143713",
"task_name": "Demo_Task",
"task_type": 1,
"status": 4,
"model": "Melo-1",
"billing_order": {
"order_id": "bo-01a05cc4a55e7cd98219eb3f1b469d95",
"status": 2,
"frozen": 10,
"charged": 10
},
"create_at": "2026-08-25T10:00:00Z",
"start_at": "2026-08-25T10:00:05Z",
"end_at": "2026-08-25T10:01:15Z",
"output_url": "https://example.com/signed-output-url"
}
}
| 字段 | 类型 | 描述 |
|---|---|---|
task_id | string | 任务 ID |
task_name | string | 任务名称 |
task_type | int | 1 为结构预测,2 为虚拟筛选 |
status | int | 当前任务状态 |
model | string | 使用的模型 |
input | object | 任务输入,结构见对应使用指南 |
billing_order | object | 计费订单信息,字段含义与创建响应一致 |
error | object | 任务执行错误信息,包含阶段错误码 code;任务失败时返回。它属于异步任务,不是 API 响应顶层的错误 |
create_at | string | 创建时间,RFC 3339 格式 |
start_at | string | 开始时间;尚未开始时为空字符串 |
end_at | string | 结束时间;尚未结束时为空字符串 |
output_url | string | 结果 ZIP 的临时下载地址,有效期为 10 分钟;过期后可重新查询。虚拟筛选全部候选失败但已生成汇总结果时也会返回 |
结果文件的内容与使用方式见结构预测结果使用和虚拟筛选结果解读。
任务失败时,查询接口本身仍可能成功(顶层 code 为 OK),失败原因位于 data.error。以下仅展示相关字段:
{
"code": "OK",
"message": "OK",
"data": {
"task_id": "tk-01a05cc4a55c77c99fe3eb3203143713",
"status": 5,
"error": {
"code": "MSA_ERROR"
}
}
}
error.code 是稳定的阶段任务失败类型,可用于程序判断。任务错误码如下:
error.code | 含义 |
|---|---|
MSA_ERROR | MSA 阶段失败 |
INFERENCE_ERROR | 推理阶段失败 |
TASK_ERROR | 其他任务处理失败 |
查询任务列表
请求
GET /v1/tasks/list
| 查询参数 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
status | int | 否 | - | 按状态筛选,可选值为 1~6 |
model | string | 否 | - | 按模型筛选,值必须是受支持的模型名 |
task_type | int | 否 | 0 | 按任务类型筛选;1 为结构预测,2 为虚拟筛选,0 或省略表示不限 |
page | int | 否 | 1 | 页码,从 1 开始 |
per_page | int | 否 | 20 | 每页数量,最大为 100;超过 100 时按 100 处理 |
sort_key | string | 否 | "create_at" | 排序字段,目前仅支持 create_at |
asc | boolean | 否 | false | true 为升序,false 为降序 |
响应
{
"code": "OK",
"message": "OK",
"data": {
"list": [
{
"task_id": "tk-01a05cc4a55c77c99fe3eb3203143713",
"task_name": "Demo_Task",
"task_type": 1,
"status": 4,
"model": "Melo-1",
"create_at": "2026-08-25T10:00:00Z"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 1,
"total_pages": 1
}
}
}
| 字段 | 类型 | 描述 |
|---|---|---|
list | array | 当前页的任务列表,无匹配任务时为空数组 |
list[].task_id | string | 任务 ID |
list[].task_name | string | 任务名称 |
list[].task_type | int | 任务类型,见任务类型与使用指南 |
list[].status | int | 任务状态,见任务状态 |
list[].model | string | 使用的模型 |
list[].create_at | string | 创建时间,RFC 3339 格式 |
pagination.page | int | 当前页码 |
pagination.per_page | int | 每页数量 |
pagination.total | int | 匹配条件的任务总数 |
pagination.total_pages | int | 总页数 |
取消任务
只有 CREATED 或 QUEUED 状态的任务可以取消。任务进入 RUNNING 或最终状态后,接口返回 TASK_STATUS_CONFLICT。
请求
POST /v1/tasks/cancel
{
"task_id": "tk-01a05cc4a55c77c99fe3eb3203143713"
}
| 字段 | 类型 | 必填 | 描述 |
|---|---|---|---|
task_id | string | 是 | 要取消的任务 ID |
响应
{
"code": "OK",
"message": "OK"
}
取消成功后,任务会进入 CANCELLED 状态,相关预占点数随后自动释放。您可以通过查询任务详情和控制台额度明细确认最终状态。
常见错误码
code | HTTP 状态码 | 说明 |
|---|---|---|
INVALID_ARGUMENT | 400 | 请求格式、必填参数、列表筛选或排序参数无效,或超过所选任务类型的费用限制;具体原因见 message |
UNAUTHORIZED | 401 | API Key 缺失、无效或已失效 |
FORBIDDEN | 403 | 无权访问该资源 |
RATE_LIMITED | 429 | 请求频率受限,请稍后重试 |
UNSUPPORTED_MODEL | 400 | 模型名称不受支持 |
UNSUPPORTED_TASK_TYPE | 400 | 任务类型不受支持 |
INVALID_TASK_NAME | 400 | 任务名称过长、仅含空白或包含不允许的字符 |
INVALID_SEQUENCE | 400 | 分子输入或 Token 数不符合所选任务类型的要求;具体原因见 message |
TASK_NOT_FOUND | 404 | 任务不存在 |
TASK_STATUS_CONFLICT | 409 | 当前任务状态不允许执行该操作 |
WALLET_NOT_ACTIVE | 409 | 额度账户当前不可用 |
INSUFFICIENT_BALANCE | 400 | 可用点数不足 |
MAX_COST_EXCEEDED | 400 | 任务费用超过请求中的 max_cost,未创建任务或预占点数;当前费用和限制值见 message |
INTERNAL_ERROR | 500 | 服务暂时异常,请稍后重试 |