5.9 KiB
5.9 KiB
示例(curl / Python / JS / Flutter)
默认服务端:http://localhost:8091
通用 Header:
Authorization: Bearer <TOKEN>
下文示例使用:
TOKEN=<TOKEN>WS=ws1
1) curl:完整流程(工作区 + 对话 + 发送 + 轮询)
BASE_URL="http://localhost:8091"
TOKEN="<TOKEN>"
WS="ws1"
# 1) 创建/确保工作区存在
curl -sS -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"workspace_id\":\"$WS\"}" \
"$BASE_URL/api/v1/workspaces"
# 2) 创建对话
CONV=$(curl -sS -X POST \
-H "Authorization: Bearer $TOKEN" \
"$BASE_URL/api/v1/workspaces/$WS/conversations" \
| python3 -c 'import sys,json; print(json.load(sys.stdin)["conversation_id"])')
echo "CONV=$CONV"
# 3) 发送消息 -> task_id
TASK=$(curl -sS -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"conversation_id\":\"$CONV\",\"message\":\"介绍明日方舟:终末地\",\"run_mode\":\"fast\"}" \
"$BASE_URL/api/v1/workspaces/$WS/messages" \
| python3 -c 'import sys,json; print(json.load(sys.stdin)["task_id"])')
echo "TASK=$TASK"
# 4) 轮询增量事件
FROM=0
while true; do
RESP=$(curl -sS -H "Authorization: Bearer $TOKEN" "$BASE_URL/api/v1/tasks/$TASK?from=$FROM")
STATUS=$(echo "$RESP" | python3 -c 'import sys,json; print(json.load(sys.stdin)["data"]["status"])')
NEXT=$(echo "$RESP" | python3 -c 'import sys,json; print(json.load(sys.stdin)["data"]["next_offset"])')
# 把本轮新增 text_chunk 直接输出(按 token 拼接)
echo "$RESP" | python3 - <<'PY'
import sys,json
obj=json.load(sys.stdin)
for ev in obj.get("data",{}).get("events",[]):
if ev.get("type")=="text_chunk":
print(ev.get("data",{}).get("content",""), end="")
PY
if [ "$STATUS" != "running" ]; then
echo
echo "status=$STATUS"
break
fi
FROM=$NEXT
sleep 0.5
done
2) Python:requests(推荐写法)
import time
import requests
BASE_URL = "http://localhost:8091"
TOKEN = "<TOKEN>"
WS = "ws1"
H = {"Authorization": f"Bearer {TOKEN}"}
def post_json(path, payload):
r = requests.post(BASE_URL + path, headers={**H, "Content-Type": "application/json"}, json=payload, timeout=30)
r.raise_for_status()
return r.json()
def get_json(path):
r = requests.get(BASE_URL + path, headers=H, timeout=30)
r.raise_for_status()
return r.json()
# workspace
post_json("/api/v1/workspaces", {"workspace_id": WS})
# conversation
conv = requests.post(BASE_URL + f"/api/v1/workspaces/{WS}/conversations", headers=H, timeout=30).json()
conv_id = conv["conversation_id"]
# message -> task
task = post_json(f"/api/v1/workspaces/{WS}/messages", {
"conversation_id": conv_id,
"message": "介绍明日方舟:终末地",
"run_mode": "fast",
"max_iterations": 100,
})
task_id = task["task_id"]
# poll
offset = 0
while True:
poll = get_json(f"/api/v1/tasks/{task_id}?from={offset}")["data"]
offset = poll["next_offset"]
for ev in poll["events"]:
if ev["type"] == "text_chunk":
print(ev["data"]["content"], end="", flush=True)
if poll["status"] != "running":
print()
print("status:", poll["status"])
break
time.sleep(0.5)
3) JS:fetch(浏览器/Node)
const BASE_URL = "http://localhost:8091";
const TOKEN = "<TOKEN>";
const WS = "ws1";
async function api(path, { method = "GET", body } = {}) {
const headers = { Authorization: `Bearer ${TOKEN}` };
if (body !== undefined) headers["Content-Type"] = "application/json";
const res = await fetch(BASE_URL + path, { method, headers, body: body ? JSON.stringify(body) : undefined });
if (!res.ok) throw new Error(await res.text());
return await res.json();
}
await api("/api/v1/workspaces", { method: "POST", body: { workspace_id: WS } });
const conv = await api(`/api/v1/workspaces/${WS}/conversations`, { method: "POST" });
const msg = await api(`/api/v1/workspaces/${WS}/messages`, {
method: "POST",
body: { conversation_id: conv.conversation_id, message: "你好", run_mode: "fast" },
});
let from = 0;
for (;;) {
const poll = await api(`/api/v1/tasks/${msg.task_id}?from=${from}`);
const data = poll.data;
from = data.next_offset;
for (const ev of data.events) {
if (ev.type === "text_chunk") process.stdout?.write?.(ev.data.content) ?? console.log(ev.data.content);
}
if (data.status !== "running") break;
await new Promise((r) => setTimeout(r, 500));
}
4) Flutter:http(示意)
import 'dart:convert';
import 'package:http/http.dart' as http;
const baseUrl = "http://localhost:8091";
const token = "<TOKEN>";
const ws = "ws1";
Map<String, String> headersJson() => {
"Authorization": "Bearer $token",
"Content-Type": "application/json",
};
Future<void> main() async {
await http.post(Uri.parse("$baseUrl/api/v1/workspaces"),
headers: headersJson(), body: jsonEncode({"workspace_id": ws}));
final convResp = await http.post(Uri.parse("$baseUrl/api/v1/workspaces/$ws/conversations"),
headers: {"Authorization": "Bearer $token"});
final conv = jsonDecode(convResp.body);
final convId = conv["conversation_id"];
final msgResp = await http.post(Uri.parse("$baseUrl/api/v1/workspaces/$ws/messages"),
headers: headersJson(),
body: jsonEncode({"conversation_id": convId, "message": "你好", "run_mode": "fast"}));
final msg = jsonDecode(msgResp.body);
final taskId = msg["task_id"];
var from = 0;
while (true) {
final pollResp = await http.get(
Uri.parse("$baseUrl/api/v1/tasks/$taskId?from=$from"),
headers: {"Authorization": "Bearer $token"},
);
final poll = jsonDecode(pollResp.body)["data"];
from = poll["next_offset"];
for (final ev in poll["events"]) {
if (ev["type"] == "text_chunk") {
// append to UI
print(ev["data"]["content"]);
}
}
if (poll["status"] != "running") break;
await Future.delayed(const Duration(milliseconds: 500));
}
}