JavaScript 与 curl
从当前图像和机器人状态发起一次云端调用,并读取动作序列。
本页使用相同的输入分别演示 Node.js 和 curl 调用。示例读取并打印动作序列,不驱动机器人。自行接入设备时,由你的控制程序校验和执行这些动作;使用 RoboAPI 时,向本地 HTTP API提交任务指令,由运行程序完成采集、推理与执行循环。
准备
先按账户与 API Key配置 PLATFORM_BASE_URL 和 PLATFORM_API_KEY,然后查询可用模型:
curl --fail-with-body "$PLATFORM_BASE_URL/models" \
-H "Authorization: Bearer $PLATFORM_API_KEY"将响应中选定的模型 id 填入 PLATFORM_MODEL,将指令改为你的任务:
export PLATFORM_MODEL="<MODEL_ID>"
export ROBOT_INSTRUCTION="Unfold the blue shirt"在工作目录准备两个文件:
input.png:当前相机观测,RGB PNG 格式。state.json:与该图像对应的机器人状态,内容为 8 个数值的 JSON 数组。顺序和坐标要求见观测与动作。
JavaScript
使用 Node.js 22 或更新版本,将以下代码保存为 infer.mjs 后运行。
import { readFileSync } from "node:fs";
function env(name) {
const value = process.env[name];
if (!value) throw new Error(`Set ${name} first`);
return value;
}
const baseUrl = env("PLATFORM_BASE_URL").replace(/\/$/, "");
const state = JSON.parse(readFileSync("state.json", "utf8"));
if (!Array.isArray(state) || state.length !== 8 || !state.every(Number.isFinite)) {
throw new Error("state.json must contain an array of 8 finite numbers");
}
const image = readFileSync("input.png").toString("base64");
const response = await fetch(`${baseUrl}/chat/completions`, {
method: "POST",
signal: AbortSignal.timeout(60_000),
headers: {
Authorization: `Bearer ${env("PLATFORM_API_KEY")}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: env("PLATFORM_MODEL"),
messages: [{
role: "user",
content: [
{ type: "text", text: JSON.stringify({
instruction: env("ROBOT_INSTRUCTION"), state
}) },
{ type: "image_url", image_url: {
url: `data:image/png;base64,${image}`
} }
]
}]
})
});
const requestId = response.headers.get("x-request-id");
console.log("Request ID:", requestId);
const result = await response.json();
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${result.error?.message ?? "Request failed"}`);
}
const call = result.choices?.[0]?.message?.tool_calls?.find(
(item) => item.function?.name === "execute_actions"
);
if (!call) throw new Error("Missing execute_actions result");
const { output } = JSON.parse(call.function.arguments);
if (!Array.isArray(output) || output.length === 0 || !output.every(
(row) => Array.isArray(row) && row.length === 8 && row.every(Number.isFinite)
)) {
throw new Error("Expected an action array with 8 finite numbers per row");
}
console.log(output);node infer.mjscurl
以下命令使用 Bash 或 Zsh,以及 jq。使用上面设置的环境变量和两个输入文件,生成请求并保存响应:
jq -n \
--arg model "$PLATFORM_MODEL" \
--arg instruction "$ROBOT_INSTRUCTION" \
--rawfile image <(base64 < input.png | tr -d '\r\n') \
--slurpfile state state.json \
'{model: $model, messages: [{role: "user", content: [
{type: "text", text: ({instruction: $instruction, state: $state[0]} | tojson)},
{type: "image_url", image_url: {url: ("data:image/png;base64," + $image)}}
]}]}' > request.json
curl --fail-with-body --max-time 60 \
"$PLATFORM_BASE_URL/chat/completions" \
-H "Authorization: Bearer $PLATFORM_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @request.json \
--dump-header response.headers \
--output response.json请求成功后,解析 execute_actions 中的动作:
jq -e '
[.choices[0].message.tool_calls[]?
| select(.function.name == "execute_actions")][0]
// error("Missing execute_actions result")
| .function.arguments | fromjson | .output
' response.json响应头保存在 response.headers。读取其中的 X-Request-ID,用于查询请求状态和用量:
REQUEST_ID=$(awk 'tolower($1) == "x-request-id:" {gsub("\r", "", $2); print $2}' response.headers | tail -n 1)
printf 'Request ID: %s\n' "$REQUEST_ID"动作数组的行数以本次响应为准。若调用失败,先根据云端调用错误处理 HTTP 状态,再发起新的请求。