将 dedalus-react 的 useChat hook 与 Python 后端一起使用。这种模式支持实时流式传输、客户端工具执行以及模型选择。
## 架构
Dedalus Python 软件开发工具包(SDK)会以与 OpenAI 兼容的格式流式传输数据块。React hook 通过服务器发送事件 (SSE) 来接收这些数据块。
## 环境准备
### 安装依赖项
# Backend
pip install fastapi uvicorn dedalus-labs python-dotenv
# 前端
pnpm add dedalus-react dedalus-labs react
## Python 后端(FastAPI)
创建一个流式传输端点,将 DedalusRunner 的输出封装为服务器发送事件 (SSE):
# server.py
import json
from fastapi import FastAPI, Request
from fastapi.responses import StreamingResponse
from fastapi.middleware.cors import CORSMiddleware
from dotenv import load_dotenv
from dedalus_labs import AsyncDedalus
from dedalus_labs.lib.runner import DedalusRunner
load_dotenv()
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"],
allow_methods=["POST"],
allow_headers=["*"],
)
client = AsyncDedalus()
runner = DedalusRunner(client)
@app.post("/api/chat")
async def chat(request: Request):
body = await request.json()
messages = body.get("messages", [])
model = body.get("model", "openai/gpt-5.2")
stream = runner.run(
messages=messages,
model=model,
stream=True,
)
async def generate():
async for chunk in stream:
yield f"data: {chunk.model_dump_json()}\n\n"
yield "data: [DONE]\n\n"
return StreamingResponse(
generate(),
media_type="text/event-stream",
headers={
"Cache-Control": "no-cache",
"Connection": "keep-alive",
},
)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
React 前端
使用 useChat 钩子管理 messages 和流式传输:
// App.tsx
import { useChat } from "dedalus-react";
import { useState } from "react";
function Chat() {
const [input, setInput] = useState("");
const { messages, sendMessage, status, stop } = useChat({
transport: { api: "http://localhost:8000/api/chat" },
});
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (!input.trim()) return;
sendMessage(input);
setInput("");
};
return (
<div>
<div className="messages">
{messages.map((msg, i) => (
<div key={i} className={`message ${msg.role}`}>
<strong>{msg.role}:</strong> {msg.content}
</div>
))}
</div>
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="输入消息..."
disabled={status === "streaming"}
/>
<button type="submit" disabled={status === "streaming"}>
发送
</button>
{status === "streaming" && (
<button type="button" onClick={stop}>
停止
</button>
)}
</form>
</div>
);
}
export default Chat;
客户端工具执行
useChat hook 支持通过 onToolCall 和 addToolResult 在客户端执行工具:
import { useChat } from "dedalus-react";
function ChatWithTools() {
const { messages, sendMessage, addToolResult } = useChat({
transport: { api: "/api/chat" },
// 当模型请求 tool 时调用
onToolCall: async ({ toolCall }) => {
if (toolCall.function.name === "get_user_location") {
// 在客户端执行(例如浏览器地理定位)
const position = await new Promise<GeolocationPosition>((resolve) =>
navigator.geolocation.getCurrentPosition(resolve),
);
addToolResult({
toolCallId: toolCall.id,
result: {
lat: position.coords.latitude,
lng: position.coords.longitude,
},
});
}
},
// tool 结果返回后自动继续
sendAutomaticallyWhen: ({ messages }) => {
const last = messages[messages.length - 1];
return last?.role === "assistant" && last.tool_calls?.length > 0;
},
});
// ... 组件的其余部分
}
### 工作原理
- 模型请求工具 - 后端在响应中以流式方式发送
tool_calls
- 钩子调用回调 - 每次调用 tool 时都会触发
onToolCall
- Client 执行 - 你的代码运行该工具(应用程序编程接口 API 调用、浏览器 API、用户 prompt 等)
- 结果返回 -
addToolResult 向历史记录中添加一条 tool 消息
- 自动继续 - 如果
sendAutomaticallyWhen 返回 true,则会携带 tool 结果再次发起请求
Python 后端不需要任何特殊处理——它只会接收包含 role: "tool" 条目的 messages,并继续对话。
模型选择
通过请求体传递额外数据:
const [model, setModel] = useState("openai/gpt-5.2");
const { messages, sendMessage } = useChat({
transport: {
api: "/api/chat",
body: { model }, // 合并到每个请求中
},
});
更新后端代码以读取它:
@app.post("/api/chat")
async def chat(request: Request):
body = await request.json()
messages = body.get("messages", [])
model = body.get("model", "openai/gpt-5.2") # 从请求体读取
stream = runner.run(messages=messages, model=model, stream=True)
# ...
## 运行示例
# Terminal 1: Start backend
python server.py
# Terminal 2: Start frontend
cd frontend && pnpm dev
生产环境注意事项
| Concern | Solution |
|---|
| CORS | 为你的域名配置允许的来源列表 |
| Authentication | 添加 JWT/会话中间件,在请求头中传递令牌 |
| Rate limiting | 实现基于用户的限流策略 |
| Error handling | 在 try/catch 中包裹流式传输,并将错误反馈到 UI |
通过模型上下文协议 (MCP) 将这些文档以编程方式连接到 Claude、VS
Code 等,以获取实时解答。 Last modified on April 11, 2026