|
@@ -0,0 +1,580 @@
|
|
|
|
|
+# 工具使用完整流程指南
|
|
|
|
|
+
|
|
|
|
|
+本文档详细说明如何使用 Tool Agent 系统中的工具,从工具注册到实际调用的完整流程。
|
|
|
|
|
+
|
|
|
|
|
+## 目录
|
|
|
|
|
+- [系统架构概览](#系统架构概览)
|
|
|
|
|
+- [工具使用流程](#工具使用流程)
|
|
|
|
|
+- [API接口说明](#api接口说明)
|
|
|
|
|
+- [使用示例](#使用示例)
|
|
|
|
|
+- [工具状态管理](#工具状态管理)
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 系统架构概览
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+┌─────────────────────────────────────────────────────────────┐
|
|
|
|
|
+│ 用户/客户端 │
|
|
|
|
|
+└────────────────────┬────────────────────────────────────────┘
|
|
|
|
|
+ │
|
|
|
|
|
+ │ HTTP Request
|
|
|
|
|
+ ▼
|
|
|
|
|
+┌─────────────────────────────────────────────────────────────┐
|
|
|
|
|
+│ Router (FastAPI) │
|
|
|
|
|
+│ 端口: 8001 (默认) │
|
|
|
|
|
+│ ┌──────────────────────────────────────────────────────┐ │
|
|
|
|
|
+│ │ API 端点: │ │
|
|
|
|
|
+│ │ • GET /health - 健康检查 │ │
|
|
|
|
|
+│ │ • GET /tools - 查看工具列表 │ │
|
|
|
|
|
+│ │ • POST /run_tool - 调用工具 │ │
|
|
|
|
|
+│ │ • POST /chat - ServiceAgent对话 │ │
|
|
|
|
|
+│ └──────────────────────────────────────────────────────┘ │
|
|
|
|
|
+│ │
|
|
|
|
|
+│ ┌──────────────┐ ┌──────────────┐ ┌─────────────────┐ │
|
|
|
|
|
+│ │ Registry │ │ Status │ │ Dispatcher │ │
|
|
|
|
|
+│ │ 工具注册表 │ │ Manager │ │ 请求分发器 │ │
|
|
|
|
|
+│ └──────────────┘ └──────────────┘ └─────────────────┘ │
|
|
|
|
|
+└────────────────────┬────────────────────────────────────────┘
|
|
|
|
|
+ │
|
|
|
|
|
+ │ HTTP 调用
|
|
|
|
|
+ ▼
|
|
|
|
|
+┌─────────────────────────────────────────────────────────────┐
|
|
|
|
|
+│ 工具实例层 │
|
|
|
|
|
+│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
|
|
|
+│ │ Local Tool │ │ Docker Tool │ │ Remote API │ │
|
|
|
|
|
+│ │ (uv环境) │ │ (容器) │ │ (云端服务) │ │
|
|
|
|
|
+│ │ 端口: 8001+ │ │ 端口: 映射 │ │ 端口: 外部 │ │
|
|
|
|
|
+│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
|
|
|
+└─────────────────────────────────────────────────────────────┘
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 工具使用流程
|
|
|
|
|
+
|
|
|
|
|
+### 流程1: 查看可用工具
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+用户
|
|
|
|
|
+ │
|
|
|
|
|
+ │ 1. GET /tools
|
|
|
|
|
+ ▼
|
|
|
|
|
+Router
|
|
|
|
|
+ │
|
|
|
|
|
+ │ 2. 读取 registry.json
|
|
|
|
|
+ ▼
|
|
|
|
|
+返回工具列表
|
|
|
|
|
+ │
|
|
|
|
|
+ │ 包含:
|
|
|
|
|
+ │ • 工具ID、名称、描述
|
|
|
|
|
+ │ • 输入/输出Schema
|
|
|
|
|
+ │ • 运行状态 (active/stopped)
|
|
|
|
|
+ │ • 后端类型 (local/docker/remote)
|
|
|
|
|
+ ▼
|
|
|
|
|
+用户选择工具
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 流程2: 调用工具 (完整流程)
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+┌─────────┐
|
|
|
|
|
+│ 用户 │
|
|
|
|
|
+└────┬────┘
|
|
|
|
|
+ │
|
|
|
|
|
+ │ 1. 准备调用参数
|
|
|
|
|
+ │ {
|
|
|
|
|
+ │ "tool_id": "image_stitcher",
|
|
|
|
|
+ │ "params": {
|
|
|
|
|
+ │ "images": ["base64...", "base64..."],
|
|
|
|
|
+ │ "direction": "horizontal"
|
|
|
|
|
+ │ }
|
|
|
|
|
+ │ }
|
|
|
|
|
+ ▼
|
|
|
|
|
+┌──────────────────────────────────────────┐
|
|
|
|
|
+│ POST /run_tool │
|
|
|
|
|
+│ Router 接收请求 │
|
|
|
|
|
+└────┬─────────────────────────────────────┘
|
|
|
|
|
+ │
|
|
|
|
|
+ │ 2. 查找工具元数据
|
|
|
|
|
+ ▼
|
|
|
|
|
+┌──────────────────────────────────────────┐
|
|
|
|
|
+│ ToolRegistry.get(tool_id) │
|
|
|
|
|
+│ • 验证工具是否存在 │
|
|
|
|
|
+│ • 获取 input_schema │
|
|
|
|
|
+│ • 获取 backend_runtime │
|
|
|
|
|
+└────┬─────────────────────────────────────┘
|
|
|
|
|
+ │
|
|
|
|
|
+ │ 3. 检查工具状态
|
|
|
|
|
+ ▼
|
|
|
|
|
+┌──────────────────────────────────────────┐
|
|
|
|
|
+│ ToolStatusManager.get_active_endpoint() │
|
|
|
|
|
+│ • 检查工具是否运行中 │
|
|
|
|
|
+│ • 获取端点URL和端口 │
|
|
|
|
|
+│ • 获取HTTP方法 (POST/GET) │
|
|
|
|
|
+└────┬─────────────────────────────────────┘
|
|
|
|
|
+ │
|
|
|
|
|
+ │ 4. 如果工具未运行,自动启动
|
|
|
|
|
+ ▼
|
|
|
|
|
+┌──────────────────────────────────────────┐
|
|
|
|
|
+│ ToolStatusManager.start_tool() │
|
|
|
|
|
+│ • Local: uv run main.py --port {port} │
|
|
|
|
|
+│ • Docker: docker start {container_id} │
|
|
|
|
|
+│ • Remote: 无需启动 │
|
|
|
|
|
+└────┬─────────────────────────────────────┘
|
|
|
|
|
+ │
|
|
|
|
|
+ │ 5. 分发请求到工具实例
|
|
|
|
|
+ ▼
|
|
|
|
|
+┌──────────────────────────────────────────┐
|
|
|
|
|
+│ Dispatcher.dispatch() │
|
|
|
|
|
+│ • 构造HTTP请求 │
|
|
|
|
|
+│ • 添加认证头 (如需要) │
|
|
|
|
|
+│ • 发送到工具端点 │
|
|
|
|
|
+│ http://localhost:{port}/{endpoint} │
|
|
|
|
|
+└────┬─────────────────────────────────────┘
|
|
|
|
|
+ │
|
|
|
|
|
+ │ 6. 工具处理请求
|
|
|
|
|
+ ▼
|
|
|
|
|
+┌──────────────────────────────────────────┐
|
|
|
|
|
+│ Tool Instance (FastAPI) │
|
|
|
|
|
+│ • 参数验证 (Pydantic) │
|
|
|
|
|
+│ • 执行业务逻辑 │
|
|
|
|
|
+│ • 返回结果 │
|
|
|
|
|
+└────┬─────────────────────────────────────┘
|
|
|
|
|
+ │
|
|
|
|
|
+ │ 7. 返回结果给用户
|
|
|
|
|
+ ▼
|
|
|
|
|
+┌──────────────────────────────────────────┐
|
|
|
|
|
+│ Response │
|
|
|
|
|
+│ { │
|
|
|
|
|
+│ "status": "success", │
|
|
|
|
|
+│ "result": { │
|
|
|
|
|
+│ "image": "base64...", │
|
|
|
|
|
+│ "width": 1024, │
|
|
|
|
|
+│ "height": 512 │
|
|
|
|
|
+│ } │
|
|
|
|
|
+│ } │
|
|
|
|
|
+└──────────────────────────────────────────┘
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 流程3: 通过 ServiceAgent 对话调用工具
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+用户
|
|
|
|
|
+ │
|
|
|
|
|
+ │ 1. POST /chat
|
|
|
|
|
+ │ {
|
|
|
|
|
+ │ "message": "帮我把这两张图片横向拼接",
|
|
|
|
|
+ │ "chat_id": "user_123"
|
|
|
|
|
+ │ }
|
|
|
|
|
+ ▼
|
|
|
|
|
+Router
|
|
|
|
|
+ │
|
|
|
|
|
+ │ 2. 转发到 SessionManager
|
|
|
|
|
+ ▼
|
|
|
|
|
+ServiceAgent
|
|
|
|
|
+ │
|
|
|
|
|
+ │ 3. 理解用户意图
|
|
|
|
|
+ │ • 解析需求: 图片拼接
|
|
|
|
|
+ │ • 搜索工具: search_tools("图片拼接")
|
|
|
|
|
+ ▼
|
|
|
|
|
+ │ 4. 找到匹配工具
|
|
|
|
|
+ │ • tool_id: image_stitcher
|
|
|
|
|
+ │ • 确认参数需求
|
|
|
|
|
+ ▼
|
|
|
|
|
+ │ 5. 调用工具
|
|
|
|
|
+ │ submit_task() 或 直接调用 /run_tool
|
|
|
|
|
+ ▼
|
|
|
|
|
+Router
|
|
|
|
|
+ │
|
|
|
|
|
+ │ 6. 执行工具调用 (同流程2)
|
|
|
|
|
+ ▼
|
|
|
|
|
+ServiceAgent
|
|
|
|
|
+ │
|
|
|
|
|
+ │ 7. 格式化结果返回用户
|
|
|
|
|
+ ▼
|
|
|
|
|
+用户收到结果
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## API接口说明
|
|
|
|
|
+
|
|
|
|
|
+### 1. GET /health
|
|
|
|
|
+
|
|
|
|
|
+**功能**: 健康检查
|
|
|
|
|
+
|
|
|
|
|
+**请求**: 无参数
|
|
|
|
|
+
|
|
|
|
|
+**响应**:
|
|
|
|
|
+```json
|
|
|
|
|
+{
|
|
|
|
|
+ "status": "ok"
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+### 2. GET /tools
|
|
|
|
|
+
|
|
|
|
|
+**功能**: 获取完整工具列表
|
|
|
|
|
+
|
|
|
|
|
+**请求**: 无参数
|
|
|
|
|
+
|
|
|
|
|
+**响应**:
|
|
|
|
|
+```json
|
|
|
|
|
+{
|
|
|
|
|
+ "backend_runtimes": [
|
|
|
|
|
+ {
|
|
|
|
|
+ "backend_runtime": "local",
|
|
|
|
|
+ "name": "本地 Python 运行时",
|
|
|
|
|
+ "description": "使用 uv 管理的本地 Python 进程"
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ "backend_runtime": "docker",
|
|
|
|
|
+ "name": "Docker 容器运行时",
|
|
|
|
|
+ "description": "运行在 Docker 容器中"
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ "backend_runtime": "remote",
|
|
|
|
|
+ "name": "远程 API / 云端服务",
|
|
|
|
|
+ "description": "调用外部 API"
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ "groups": [
|
|
|
|
|
+ {
|
|
|
|
|
+ "group_id": "runcomfy_lifecycle",
|
|
|
|
|
+ "name": "ComfyUI 生命周期管理",
|
|
|
|
|
+ "description": "启动、执行、停止 ComfyUI 环境",
|
|
|
|
|
+ "backend_runtime": "remote",
|
|
|
|
|
+ "tool_ids": ["launch_comfy_env", "runcomfy_workflow_executor", "runcomfy_stop_env"],
|
|
|
|
|
+ "usage_order": ["launch_comfy_env", "runcomfy_workflow_executor", "runcomfy_stop_env"]
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ "tools": [
|
|
|
|
|
+ {
|
|
|
|
|
+ "tool_id": "image_stitcher",
|
|
|
|
|
+ "name": "图片拼接工具",
|
|
|
|
|
+ "description": "将多张图片拼接成一张",
|
|
|
|
|
+ "category": "cv",
|
|
|
|
|
+ "backend_runtime": "local",
|
|
|
|
|
+ "group_ids": [],
|
|
|
|
|
+ "input_schema": { ... },
|
|
|
|
|
+ "output_schema": { ... },
|
|
|
|
|
+ "state": "running",
|
|
|
|
|
+ "port": 8001
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ "total": 5
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**字段说明**:
|
|
|
|
|
+- `backend_runtimes`: 后端运行环境分类
|
|
|
|
|
+- `groups`: 工具组 (相关工具的集合)
|
|
|
|
|
+- `tools`: 所有已注册工具
|
|
|
|
|
+ - `state`: 工具状态 (`running` / `stopped`)
|
|
|
|
|
+ - `port`: 工具运行端口 (如果正在运行)
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+### 3. POST /run_tool
|
|
|
|
|
+
|
|
|
|
|
+**功能**: 调用指定工具
|
|
|
|
|
+
|
|
|
|
|
+**请求**:
|
|
|
|
|
+```json
|
|
|
|
|
+{
|
|
|
|
|
+ "tool_id": "image_stitcher",
|
|
|
|
|
+ "params": {
|
|
|
|
|
+ "images": ["base64_image_1", "base64_image_2"],
|
|
|
|
|
+ "direction": "horizontal",
|
|
|
|
|
+ "spacing": 10
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**响应 (成功)**:
|
|
|
|
|
+```json
|
|
|
|
|
+{
|
|
|
|
|
+ "status": "success",
|
|
|
|
|
+ "result": {
|
|
|
|
|
+ "image": "base64_result_image",
|
|
|
|
|
+ "width": 1024,
|
|
|
|
|
+ "height": 512
|
|
|
|
|
+ },
|
|
|
|
|
+ "error": null
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**响应 (失败)**:
|
|
|
|
|
+```json
|
|
|
|
|
+{
|
|
|
|
|
+ "status": "error",
|
|
|
|
|
+ "result": null,
|
|
|
|
|
+ "error": "Tool 'xxx' is not running or has no active endpoint"
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+### 4. POST /chat
|
|
|
|
|
+
|
|
|
|
|
+**功能**: 与 ServiceAgent 对话
|
|
|
|
|
+
|
|
|
|
|
+**请求**:
|
|
|
|
|
+```json
|
|
|
|
|
+{
|
|
|
|
|
+ "message": "帮我生成一张猫的图片",
|
|
|
|
|
+ "chat_id": "user_123_session_1"
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**响应**:
|
|
|
|
|
+```json
|
|
|
|
|
+{
|
|
|
|
|
+ "response": "好的,我使用 LibLib ControlNet 工具为您生成图片...",
|
|
|
|
|
+ "chat_id": "user_123_session_1"
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**说明**:
|
|
|
|
|
+- `chat_id`: 每个对话窗口的唯一标识,用于保持上下文
|
|
|
|
|
+- ServiceAgent 会自动搜索和调用合适的工具
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 使用示例
|
|
|
|
|
+
|
|
|
|
|
+### 示例1: Python 客户端调用
|
|
|
|
|
+
|
|
|
|
|
+```python
|
|
|
|
|
+import httpx
|
|
|
|
|
+import base64
|
|
|
|
|
+
|
|
|
|
|
+# 1. 查看可用工具
|
|
|
|
|
+async with httpx.AsyncClient() as client:
|
|
|
|
|
+ response = await client.get("http://localhost:8001/tools")
|
|
|
|
|
+ tools = response.json()
|
|
|
|
|
+ print(f"可用工具: {len(tools['tools'])}个")
|
|
|
|
|
+
|
|
|
|
|
+# 2. 准备图片数据
|
|
|
|
|
+with open("image1.png", "rb") as f:
|
|
|
|
|
+ img1_b64 = base64.b64encode(f.read()).decode()
|
|
|
|
|
+with open("image2.png", "rb") as f:
|
|
|
|
|
+ img2_b64 = base64.b64encode(f.read()).decode()
|
|
|
|
|
+
|
|
|
|
|
+# 3. 调用图片拼接工具
|
|
|
|
|
+async with httpx.AsyncClient(timeout=60.0) as client:
|
|
|
|
|
+ response = await client.post(
|
|
|
|
|
+ "http://localhost:8001/run_tool",
|
|
|
|
|
+ json={
|
|
|
|
|
+ "tool_id": "image_stitcher",
|
|
|
|
|
+ "params": {
|
|
|
|
|
+ "images": [img1_b64, img2_b64],
|
|
|
|
|
+ "direction": "horizontal",
|
|
|
|
|
+ "spacing": 20,
|
|
|
|
|
+ "background_color": "#FFFFFF"
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+ result = response.json()
|
|
|
|
|
+
|
|
|
|
|
+ if result["status"] == "success":
|
|
|
|
|
+ # 保存结果
|
|
|
|
|
+ result_img = base64.b64decode(result["result"]["image"])
|
|
|
|
|
+ with open("result.png", "wb") as f:
|
|
|
|
|
+ f.write(result_img)
|
|
|
|
|
+ print(f"拼接完成! 尺寸: {result['result']['width']}x{result['result']['height']}")
|
|
|
|
|
+ else:
|
|
|
|
|
+ print(f"错误: {result['error']}")
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 示例2: curl 命令行调用
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# 1. 查看工具列表
|
|
|
|
|
+curl http://localhost:8001/tools | jq '.tools[] | {tool_id, name, state}'
|
|
|
|
|
+
|
|
|
|
|
+# 2. 调用工具
|
|
|
|
|
+curl -X POST http://localhost:8001/run_tool \
|
|
|
|
|
+ -H "Content-Type: application/json" \
|
|
|
|
|
+ -d '{
|
|
|
|
|
+ "tool_id": "image_stitcher",
|
|
|
|
|
+ "params": {
|
|
|
|
|
+ "images": ["'$(base64 -w0 image1.png)'", "'$(base64 -w0 image2.png)'"],
|
|
|
|
|
+ "direction": "horizontal"
|
|
|
|
|
+ }
|
|
|
|
|
+ }' | jq '.result.image' -r | base64 -d > result.png
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 示例3: 通过 ServiceAgent 对话
|
|
|
|
|
+
|
|
|
|
|
+```python
|
|
|
|
|
+import httpx
|
|
|
|
|
+
|
|
|
|
|
+async with httpx.AsyncClient() as client:
|
|
|
|
|
+ # 创建对话
|
|
|
|
|
+ response = await client.post(
|
|
|
|
|
+ "http://localhost:8001/chat",
|
|
|
|
|
+ json={
|
|
|
|
|
+ "message": "帮我把两张图片横向拼接,间距10像素",
|
|
|
|
|
+ "chat_id": "my_session_001"
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+ print(response.json()["response"])
|
|
|
|
|
+
|
|
|
|
|
+ # 继续对话 (保持上下文)
|
|
|
|
|
+ response = await client.post(
|
|
|
|
|
+ "http://localhost:8001/chat",
|
|
|
|
|
+ json={
|
|
|
|
|
+ "message": "改成垂直拼接",
|
|
|
|
|
+ "chat_id": "my_session_001" # 同一个 chat_id
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+ print(response.json()["response"])
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 工具状态管理
|
|
|
|
|
+
|
|
|
|
|
+### 工具状态生命周期
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+┌──────────┐
|
|
|
|
|
+│ INACTIVE │ 工具已注册但未启动
|
|
|
|
|
+└────┬─────┘
|
|
|
|
|
+ │
|
|
|
|
|
+ │ start_tool()
|
|
|
|
|
+ ▼
|
|
|
|
|
+┌──────────┐
|
|
|
|
|
+│ STARTING │ 正在启动中
|
|
|
|
|
+└────┬─────┘
|
|
|
|
|
+ │
|
|
|
|
|
+ │ 健康检查通过
|
|
|
|
|
+ ▼
|
|
|
|
|
+┌──────────┐
|
|
|
|
|
+│ ACTIVE │ 工具运行中,可接受请求
|
|
|
|
|
+└────┬─────┘
|
|
|
|
|
+ │
|
|
|
|
|
+ │ stop_tool() 或 超时无请求
|
|
|
|
|
+ ▼
|
|
|
|
|
+┌──────────┐
|
|
|
|
|
+│ STOPPED │ 工具已停止
|
|
|
|
|
+└──────────┘
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 自动启动机制
|
|
|
|
|
+
|
|
|
|
|
+当调用 `/run_tool` 时:
|
|
|
|
|
+1. **检查状态**: 如果工具状态为 `stopped` 或 `inactive`
|
|
|
|
|
+2. **自动启动**:
|
|
|
|
|
+ - Local: 执行 `uv run main.py --port {port}` (后台进程)
|
|
|
|
|
+ - Docker: 执行 `docker start {container_id}`
|
|
|
|
|
+ - Remote: 无需启动
|
|
|
|
|
+3. **健康检查**: 轮询 `GET /health` 直到返回 `{"status": "ok"}`
|
|
|
|
|
+4. **更新状态**: 标记为 `running`
|
|
|
|
|
+5. **执行请求**: 转发用户请求到工具端点
|
|
|
|
|
+
|
|
|
|
|
+### 端口分配规则
|
|
|
|
|
+
|
|
|
|
|
+- Router: `8001` (默认)
|
|
|
|
|
+- Local工具: `8002, 8003, 8004...` (自动递增)
|
|
|
|
|
+- Docker工具: 容器内部端口映射到宿主机
|
|
|
|
|
+- Remote工具: 使用外部API的端口
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 工具调用流程总结
|
|
|
|
|
+
|
|
|
|
|
+### 直接调用 (适合程序化调用)
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+用户 → POST /run_tool → Router → Dispatcher → Tool Instance → 返回结果
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**优点**:
|
|
|
|
|
+- 快速、直接
|
|
|
|
|
+- 完全控制参数
|
|
|
|
|
+- 适合自动化脚本
|
|
|
|
|
+
|
|
|
|
|
+**缺点**:
|
|
|
|
|
+- 需要了解工具的 input_schema
|
|
|
|
|
+- 需要手动处理错误
|
|
|
|
|
+
|
|
|
|
|
+### 通过 ServiceAgent 调用 (适合自然语言交互)
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+用户 → POST /chat → ServiceAgent → 搜索工具 → 调用工具 → 格式化结果 → 返回用户
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**优点**:
|
|
|
|
|
+- 自然语言交互
|
|
|
|
|
+- 自动选择合适工具
|
|
|
|
|
+- 智能参数推断
|
|
|
|
|
+- 友好的错误提示
|
|
|
|
|
+
|
|
|
|
|
+**缺点**:
|
|
|
|
|
+- 响应稍慢 (需要LLM推理)
|
|
|
|
|
+- 可能需要多轮对话确认参数
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 常见问题
|
|
|
|
|
+
|
|
|
|
|
+### Q1: 工具调用失败,提示 "Tool is not running"?
|
|
|
|
|
+
|
|
|
|
|
+**A**: 工具可能未启动。解决方法:
|
|
|
|
|
+1. 检查工具状态: `GET /tools`
|
|
|
|
|
+2. 手动启动工具 (如果自动启动失败):
|
|
|
|
|
+ ```bash
|
|
|
|
|
+ cd tools/local/{tool_id}
|
|
|
|
|
+ uv run main.py --port 8002
|
|
|
|
|
+ ```
|
|
|
|
|
+3. 检查端口是否被占用
|
|
|
|
|
+
|
|
|
|
|
+### Q2: 如何查看工具的输入参数要求?
|
|
|
|
|
+
|
|
|
|
|
+**A**: 调用 `GET /tools`,查看返回的 `input_schema` 字段:
|
|
|
|
|
+```python
|
|
|
|
|
+tools = requests.get("http://localhost:8001/tools").json()
|
|
|
|
|
+tool = next(t for t in tools["tools"] if t["tool_id"] == "image_stitcher")
|
|
|
|
|
+print(tool["input_schema"])
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Q3: 可以同时调用多个工具吗?
|
|
|
|
|
+
|
|
|
|
|
+**A**: 可以。每个工具运行在独立端口,支持并发调用:
|
|
|
|
|
+```python
|
|
|
|
|
+import asyncio
|
|
|
|
|
+
|
|
|
|
|
+async def call_tool(tool_id, params):
|
|
|
|
|
+ async with httpx.AsyncClient() as client:
|
|
|
|
|
+ return await client.post(
|
|
|
|
|
+ "http://localhost:8001/run_tool",
|
|
|
|
|
+ json={"tool_id": tool_id, "params": params}
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+# 并发调用
|
|
|
|
|
+results = await asyncio.gather(
|
|
|
|
|
+ call_tool("image_stitcher", {...}),
|
|
|
|
|
+ call_tool("liblibai_controlnet", {...})
|
|
|
|
|
+)
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Q4: 工具调用超时怎么办?
|
|
|
|
|
+
|
|
|
|
|
+**A**:
|
|
|
|
|
+1. 检查工具日志: `tools/local/{tool_id}/tests/last_run.log`
|
|
|
|
|
+2. 增加超时时间 (Dispatcher 默认 600秒)
|
|
|
|
|
+3. 优化工具性能或使用异步处理
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 下一步
|
|
|
|
|
+
|
|
|
|
|
+- 查看 [任务书编写指南](../task_specs/README.md) 了解如何创建新工具
|
|
|
|
|
+- 查看 [工具开发文档](./TOOL_DEVELOPMENT.md) 了解工具实现细节
|
|
|
|
|
+- 查看 [API参考文档](./API_REFERENCE.md) 了解完整API规范
|
|
|
|
|
+
|