# Luxx 项目架构 ## 技术栈 - **框架**: FastAPI 0.109+ - **数据库**: SQLAlchemy 2.0+ (同步模式) - **认证**: JWT (PyJWT) - **HTTP客户端**: httpx, requests - **配置**: YAML (PyYAML) - **代码执行**: Python 原生执行 - **网页爬虫**: - `httpx` - HTTP 客户端 - `beautifulsoup4` - HTML 解析 - `lxml` - XML/HTML 解析器 ## 目录结构 ``` luxx/ ├── __init__.py # FastAPI 应用工厂 ├── config.py # 配置管理(YAML) ├── database.py # 数据库连接 ├── models.py # ORM 模型 ├── routes/ # API 路由层 │ ├── __init__.py # 路由聚合 │ ├── auth.py # 认证 (登录/注册) │ ├── agents.py # Agent 模板管理 (CRUD) │ ├── chat_rooms.py # 聊天室管理 (多 Agent 协作) │ ├── conversations.py # 会话管理 (CRUD) │ ├── messages.py # 消息处理 (流式/同步) │ ├── providers.py # LLM 提供商管理 │ ├── agents.py # Agent 模板管理 (CRUD) │ └── tools.py # 工具管理 ├── services/ # 服务层 │ ├── __init__.py # 服务导出 │ ├── chat.py # 聊天服务门面 │ ├── chat_room.py # 多 Agent 聊天室编排器 │ ├── agentic_loop.py # Agentic Loop 执行器 │ ├── stream_context.py # 流式状态管理 │ ├── events.py # SSE 事件工具 │ ├── llm_response.py # LLM 响应数据类 │ ├── task.py # 任务系统 (Task/TaskGraph/TaskService) │ ├── llm_client.py # LLM 客户端 │ └── llm_adapters/ # LLM API 适配器 │ ├── __init__.py # 适配器导出 │ ├── base.py # ProviderAdapter 基类 │ ├── openai_adapter.py # OpenAI/DeepSeek/GLM 适配器 │ └── anthropic_adapter.py # Anthropic Claude 适配器 ├── tools/ # 工具系统 │ ├── __init__.py # 工具注册入口 │ ├── core.py # 核心类 (ToolRegistry, ToolDefinition, ToolResult, ToolContext) │ ├── factory.py # @tool 装饰器 │ ├── executor.py # 工具执行器 (缓存/并行) │ ├── services.py # 工具服务层 │ └── builtin/ # 内置工具 │ ├── __init__.py # 工具注册入口 │ ├── code.py # 代码执行 (python_execute, python_eval) │ ├── crawler.py # 网页爬虫 (web_search, web_fetch, batch_fetch) │ ├── data.py # 数据处理 (process_data) │ ├── file.py # 文件操作 (file_read, file_write, file_list, file_exists, file_grep) │ └── shell.py # Shell 命令 (shell_execute) └── utils/ # 工具函数 ├── __init__.py └── helpers.py # 密码哈希、ID生成、响应封装 run.py # 应用入口文件 config.yaml # 配置文件 ``` ## 核心组件 ### 1. 应用工厂 (`__init__.py`) FastAPI 应用入口,使用 lifespan 管理生命周期: - 启动:初始化数据库、注册内置工具、创建默认管理员用户 - 关闭:清理资源 ```python # 默认管理员账号 username: admin password: admin123 ``` ### 2. 配置管理 (`config.py`) 使用 YAML 文件管理配置: - 配置文件:`config.yaml` - 环境变量替换:`${VAR_NAME}` - 单例模式全局访问 - 默认值支持 ```yaml # config.yaml 示例 app: secret_key: ${APP_SECRET_KEY} debug: true host: 0.0.0.0 port: 8000 database: type: sqlite url: sqlite:///./chat.db workspace: root: ./workspaces # 用户工作空间根目录 auto_create: true # 自动创建用户目录 llm: provider: deepseek api_key: ${DEEPSEEK_API_KEY} api_url: https://api.deepseek.com/v1 tools: enable_cache: true cache_ttl: 300 max_workers: 4 max_iterations: 10 logging: level: INFO ``` **工作空间隔离机制:** - 每个用户的工作空间路径基于 `user_id` 的 SHA256 哈希值 - 格式:`{workspace_root}/{hash_of_user_id}` - 所有文件操作必须在用户工作空间内,防止路径穿越攻击 ``` ### 3. 数据库 (`database.py`) - SQLAlchemy 同步支持 - SQLite 默认数据库 - 依赖注入获取会话 ### 4. ORM 模型 (`models.py`) ```mermaid erDiagram USER { int id PK string username UK string email UK string password_hash string role int permission_level "1=READ_ONLY, 2=WRITE, 3=EXECUTE, 4=ADMIN" string workspace_path "用户工作空间路径" boolean is_active datetime created_at } USER_SETTINGS { int id PK int user_id FK UK int default_provider_id FK "optional" float temperature int max_tokens boolean thinking_enabled text system_prompt datetime created_at datetime updated_at } PROJECT { string id PK int user_id FK string name text description datetime created_at datetime updated_at } CONVERSATION { string id PK int user_id FK int provider_id FK "optional" string project_id FK "optional" string title string model text system_prompt float temperature int max_tokens boolean thinking_enabled datetime created_at datetime updated_at } MESSAGE { string id PK string conversation_id FK "optional" string room_id FK "optional" string role longtext content "JSON 格式" int token_count text usage "JSON 格式" string sender_name "聊天室: 发送者名称" string sender_color "聊天室: 发送者颜色" int round_number "聊天室: 轮次编号" datetime created_at } LLM_PROVIDER { int id PK int user_id FK string name string provider_type string base_url string api_key string default_model int max_tokens boolean is_default boolean enabled datetime created_at datetime updated_at } AGENT { int id PK int user_id FK string name string role int provider_id FK "optional" string model text system_prompt string color datetime created_at datetime updated_at } CHAT_ROOM { string id PK int user_id FK string title text task string status "idle/running/paused/completed/error" int max_rounds int current_round datetime created_at datetime updated_at } ROOM_AGENT { int id PK string room_id FK int agent_id FK "optional" string name string role int provider_id FK "optional" string model text system_prompt string color int turn_order } USER ||--|| USER_SETTINGS : "has" USER ||--o{ PROJECT : "has" USER ||--o{ CONVERSATION : "has" USER ||--o{ LLM_PROVIDER : "configures" USER ||--o{ AGENT : "creates" USER ||--o{ CHAT_ROOM : "creates" PROJECT ||--o{ CONVERSATION : "contains" LLM_PROVIDER ||--o{ CONVERSATION : "uses" LLM_PROVIDER ||--o{ AGENT : "used_by" LLM_PROVIDER ||--o{ ROOM_AGENT : "used_by" CONVERSATION ||--o{ MESSAGE : "has" CHAT_ROOM ||--o{ MESSAGE : "has" CHAT_ROOM ||--o{ ROOM_AGENT : "contains" AGENT ||--o{ ROOM_AGENT : "linked_to" ``` **用户权限级别 (permission_level):** | 级别 | 名称 | 说明 | |------|------|------| | 1 | READ_ONLY | 只读权限 | | 2 | WRITE | 写入权限(文件写入) | | 3 | EXECUTE | 执行权限(代码执行、Shell命令) | | 4 | ADMIN | 管理员权限 | ### Message Content JSON 结构 `content` 字段统一使用 JSON 格式存储: **User 消息:** ```json { "text": "用户输入的文本内容", "attachments": [ {"name": "utils.py", "extension": "py", "content": "..."} ] } ``` **Assistant 消息:** ```json { "steps": [ {"id": "step-0", "index": 0, "type": "thinking", "content": "..."}, {"id": "step-1", "index": 1, "type": "text", "content": "..."}, {"id": "step-2", "index": 2, "type": "tool_call", "id_ref": "call_xxx", "name": "...", "arguments": "..."}, {"id": "step-3", "index": 3, "type": "tool_result", "id_ref": "call_xxx", "name": "...", "content": "...", "success": true} ] } ``` `steps` 字段是**唯一数据源**,按 `index` 顺序排列。thinking、text、tool_call、tool_result 可以在多轮迭代中穿插出现。 **注意**:`text` 和 `content` 字段通过解析 `steps` 中所有 `type: "text"` 的内容动态计算得出。 ### 5. 工具系统 ```mermaid classDiagram class ToolDefinition { +str name +str description +dict parameters +Callable handler +str category +CommandPermission required_permission +to_openai_format() dict } class ToolContext { +int user_id +str username +str workspace +int user_permission_level } class CommandPermission { <> READ_ONLY = 1 WRITE = 2 EXECUTE = 3 ADMIN = 4 } class ToolResult { +bool success +Any data +str error +to_dict() dict +ok(data) ToolResult$ +fail(error) ToolResult$ } class ToolRegistry { +_tools: Dict +register(tool) void +get(name) ToolDefinition? +list_all() List~dict~ +list_by_category(category) List~dict~ +execute(name, arguments, context) dict +remove(name) bool } class ToolExecutor { +enable_cache: bool +cache_ttl: int +max_workers: int +_cache: Dict +_call_history: List +process_tool_calls(tool_calls, context) list +process_tool_calls_parallel(tool_calls, context) list +clear_cache() void +get_history(limit) List } ``` #### 内置工具 **代码执行 (code.py)** | 工具 | 功能 | 权限 | |------|------|------| | `python_execute` | 执行 Python 代码 | EXECUTE | | `python_eval` | 计算表达式 | EXECUTE | **文件操作 (file.py)** | 工具 | 功能 | 权限 | |------|------|------| | `file_read` | 读取文件内容 | READ_ONLY | | `file_write` | 写入文件内容 | WRITE | | `file_list` | 列出目录内容 | READ_ONLY | | `file_exists` | 检查文件是否存在 | READ_ONLY | | `file_grep` | 正则搜索文件内容 | READ_ONLY | **Shell 命令 (shell.py)** | 工具 | 功能 | 权限 | |------|------|------| | `shell_execute` | 执行 Shell 命令 | EXECUTE | **网页爬虫 (crawler.py)** | 工具 | 功能 | 权限 | |------|------|------| | `web_search` | DuckDuckGo HTML 搜索 | READ_ONLY | | `web_fetch` | 网页抓取 | READ_ONLY | | `batch_fetch` | 批量并发抓取 | READ_ONLY | **数据处理 (data.py)** | 工具 | 功能 | 权限 | |------|------|------| | `process_data` | JSON 转换、格式化 | READ_ONLY | #### 权限检查机制 工具执行时自动检查用户权限: ``` 工具要求的权限 <= 用户拥有的权限 → 允许执行 工具要求的权限 > 用户拥有的权限 → 拒绝执行 ``` #### 工具开发规范 所有工具必须遵循统一的开发规范,确保错误处理和返回格式一致。 **核心原则:装饰器自动处理一切,工具函数只写业务逻辑** ```python from luxx.tools.factory import tool @tool( name="my_tool", description="工具描述", parameters={...}, required_params=["arg1"], # 自动验证 category="my_category" ) def my_tool(arguments: dict): # 业务逻辑 - 只管返回数据 data = fetch_data(arguments["arg1"]) return {"items": data, "count": len(data)} # 或者直接抛出异常(装饰器自动捕获并转换) if invalid: raise ValueError("Invalid input") ``` **装饰器自动处理:** 1. 必需参数验证(`required_params`) 2. 所有异常捕获和转换 3. 结果格式统一包装 **返回格式转换** | 工具函数返回/抛出 | 装饰器转换为 | |-------------------|-------------| | `return {"result": "ok"}` | `{"success": true, "data": {...}, "error": null}` | | `raise ValueError("msg")` | `{"success": false, "data": null, "error": "ValueError: msg"}` | | `raise Exception()` | `{"success": false, "data": null, "error": "..."}` | **工具调用流程** ``` LLM 请求 ↓ ToolRegistry.execute(name, args) ↓ @tool 装饰器 ├─ 验证 required_params ├─ 执行工具函数 (try-except 包裹) ├─ 捕获异常 → 转换为 error ├─ 包装返回格式 └─ 返回 ToolResult ↓ ToolExecutor 返回结果 ↓ 前端 ProcessBlock 显示 ``` ### 6. 服务层 #### LLM 适配器 (`services/llm_adapters/`) 适配器模式统一处理不同 LLM API 格式: ```mermaid classDiagram class ProviderAdapter { <> +str provider_type +build_request() tuple +parse_stream_chunk() AsyncGenerator +parse_response() Dict +supports_thinking() bool +supports_tools() bool } class OpenAIAdapter { +str provider_type = "openai" +build_request() tuple +parse_stream_chunk() AsyncGenerator +parse_response() Dict +supports_tools() bool } class AnthropicAdapter { +str provider_type = "anthropic" +build_request() tuple +parse_stream_chunk() AsyncGenerator +parse_response() Dict +supports_thinking() bool +supports_tools() bool } ProviderAdapter <|-- OpenAIAdapter ProviderAdapter <|-- AnthropicAdapter ``` **支持的功能对比:** | 适配器 | 工具调用 | Thinking/Reasoning | 流式响应 | |--------|----------|-------------------|----------| | OpenAI | ✅ | ✅ (DeepSeek) | ✅ | | Anthropic | ✅ | ✅ | ✅ | #### LLM 响应数据类 (`services/llm_response.py`) ```python class StepType: """步骤类型常量""" THINKING = "thinking" TEXT = "text" TOOL_CALL = "tool_call" TOOL_RESULT = "tool_result" @dataclass class Step: """单个步骤 - 用于存储和传输""" id: str index: int type: str # thinking, text, tool_call, tool_result content: str = "" name: str = "" # tool_call/tool_result arguments: str = "" # tool_call id_ref: str = "" # tool_result success: bool = True @dataclass class ParsedDelta: """LLM 流式响应增量""" thinking: str = "" # 思考内容(增量) text: str = "" # 文本内容(增量) tool_call: Optional[Dict] = None # 单个工具调用 usage: Dict[str, int] = {} # Token 用量 is_complete: bool = False ``` #### ChatService (`services/chat.py`) 核心聊天服务: - Agentic Loop 迭代执行(最多 10 轮) - 流式 SSE 响应 - 工具调用编排(并行执行) - 消息历史管理 - Token 用量追踪 - 工作空间上下文传递 #### AgenticLoop (`services/agentic_loop.py`) 执行 Agentic Loop 的核心循环: - 调用 LLM 获取响应(流式) - 解析 ParsedDelta,更新步骤状态 - 管理 thinking/text/tool_call/tool_result 步骤 - 工具并行执行 - 最大迭代次数:10 ```python # 执行流程 async for delta in llm.stream_call(...): events = self._process_delta(delta, context, total_usage) yield from events # 工具调用时 tool_results = self.tool_executor.process_tool_calls_parallel(...) messages.append({"role": "assistant", ...}) messages.extend(tool_results) ``` #### StreamContext (`services/stream_context.py`) 流式状态管理: - 追踪当前步骤类型和索引 - 累积 thinking 和 text 内容 - 管理 tool_calls 列表和 tool_results - 生成 SSE 事件 - 构建完整消息内容 #### LLMClient (`services/llm_client.py`) LLM API 客户端: - 多提供商:OpenAI、DeepSeek、Anthropic - 自动适配器选择 - 流式/同步调用 - 错误处理和重试 - Token 计数 ### 7. 任务系统 (`services/task.py`) 用于自主任务执行和计划管理: ```mermaid classDiagram class Task { +str id +str name +str goal +TaskStatus status +List~Step~ steps +str metadata +get_step() Step? +is_complete() bool } class Step { +str id +str name +str goal +List~str~ depends_on +StepStatus status +Dict tool_calls } class TaskGraph { +topological_sort() List~Step~ +get_ready_steps() List~Step~ +get_parallel_levels() List~List~Step~~ +detect_cycles() List~List~str~~ +validate() tuple } class TaskService { +create_task() Task +get_task() Task +update_task_status() Task +add_steps() List~Step~ +set_steps_from_plan() List~Step~ +build_graph() TaskGraph } class Planner { +plan() List~Dict~ +plan_sync() List~Dict~ } Task "1" o-- "*" Step TaskService ..> TaskGraph Planner ..> TaskService ``` **任务状态 (TaskStatus) - 五状态模型:** - `PENDING` - 待处理/就绪 - `RUNNING` - 运行中 - `BLOCK` - 阻塞 - `TERMINATED` - 终止 - `COMPLETED` - 完成 **步骤状态 (StepStatus):** - `PENDING` - 待执行 - `RUNNING` - 执行中 - `COMPLETED` - 已完成 - `FAILED` - 失败 - `SKIPPED` - 跳过 **TaskGraph 功能:** - `topological_sort()` - 拓扑排序获取执行顺序 - `get_ready_steps()` - 获取就绪步骤(依赖已满足) - `get_parallel_levels()` - 获取并行执行层级 - `detect_cycles()` - 检测循环依赖 - `validate()` - 验证图结构 **Planner 功能:** - 调用 LLM 自动分解目标为步骤 - 支持上下文(可用工具、约束条件) - 返回结构化步骤列表 ### 8. 任务执行服务 (`services/task_executor.py`) 将 Task/Plan 集成到 Agent 执行流程: ```mermaid classDiagram class TaskExecutorService { +llm: LLMClient +generate_plan() List~Dict~ +create_task_with_plan() Task +get_execution_plan() Dict } class AgentWithPlan { +chat_service +execute_with_plan() AsyncGenerator } TaskExecutorService --> TaskService AgentWithPlan --> TaskExecutorService AgentWithPlan --> ChatService ``` **执行流程:** 1. 用户输入目标 → AgentWithPlan 接收 2. TaskExecutorService.generate_plan() 调用 LLM 分解目标 3. 创建 Task 并设置步骤 4. 按 TaskGraph 拓扑顺序执行每个步骤 5. 每个步骤作为独立 Agent 对话执行 6. 步骤完成后更新状态,继续下一个 **SSE 事件:** - `planning` - 计划生成中 - `plan_created` - 计划已创建 - `step_start` - 步骤开始 - `step_complete` - 步骤完成 - `task_complete` - 任务完成 ### 7. 认证系统 (`routes/auth.py`) - JWT Bearer Token - Bcrypt 密码哈希 - 用户注册/登录 ### 8. Agent 系统 (`routes/agents.py`, `models.py`) Agent 是独立的可复用 AI 助手模板,可以在聊天室中使用: ```mermaid classDiagram class Agent { +int id +int user_id +str name +str role +int provider_id +str model +str system_prompt +str color +to_dict() dict } class LLMProvider { +int id +str name +str api_key +str default_model } Agent --> LLMProvider : uses ``` **Agent 字段说明:** | 字段 | 类型 | 说明 | |------|------|------| | `id` | int | Agent 唯一标识 | | `user_id` | int | 所属用户 ID | | `name` | string | Agent 显示名称 | | `role` | string | Agent 角色描述(如"后端开发") | | `provider_id` | int | 使用的 LLM 提供商 | | `model` | string | 模型名称 | | `system_prompt` | string | 系统提示词 | | `color` | string | 显示颜色(Hex) | ### 9. 聊天室系统 (`routes/chat_rooms.py`, `services/chat_room.py`) 聊天室支持多个 Agent 同时参与讨论,协作完成复杂任务: ```mermaid classDiagram class ChatRoom { +str id +int user_id +str title +str task +str status +int max_rounds +int current_round +List~RoomAgent~ agents } class RoomAgent { +int id +str room_id +int agent_id +str name +str role +str model +str system_prompt +str color +int turn_order } class ChatRoomOrchestrator { -Dict~str, Task~ _running_rooms +is_running(room_id) bool +cancel(room_id) void +run_room(room_id) AsyncGenerator } ChatRoom "1" o-- "*" RoomAgent : contains ChatRoomOrchestrator ..> ChatRoom : orchestrates ChatRoomOrchestrator ..> RoomAgent : executes ``` **聊天室状态:** | 状态 | 说明 | |------|------| | `idle` | 空闲,未开始 | | `running` | 运行中 | | `paused` | 已暂停(被手动停止) | | `completed` | 已完成(达到最大轮次) | | `error` | 错误(执行出错) | **聊天室执行流程:** ``` 1. 用户调用 /chat-rooms/{id}/start 2. ChatRoomOrchestrator.run_room() 被调用 3. 按 turn_order 顺序执行每个 Agent 的发言轮次 4. 每个 Agent 根据历史消息和系统提示生成回复 5. SSE 流式推送消息块 (message_chunk) 6. 消息结束时推送 message_end 7. 一轮结束后推送 round_end 8. 达到 max_rounds 或被停止时结束 ``` **SSE 事件流:** ``` room_started → round_start → (message_start → message_chunk* → message_end → message) × N_agents → round_end → (重复下一轮) → room_completed ``` ### 10. API 路由 | 路由 | 方法 | 说明 | |------|------|------| | `/auth/register` | POST | 用户注册 | | `/auth/login` | POST | 用户登录 | | `/auth/logout` | POST | 用户登出 | | `/auth/me` | GET | 当前用户信息 | | `/auth/users` | GET | 用户列表(管理员) | | `/auth/users/{user_id}` | PUT | 更新用户权限 | | `/conversations` | GET | 会话列表(分页) | | `/conversations` | POST | 创建会话 | | `/conversations/{id}` | GET | 会话详情 | | `/conversations/{id}` | PUT | 更新会话 | | `/conversations/{id}` | DELETE | 删除会话 | | `/messages` | GET | 消息列表 | | `/messages` | POST | 发送消息(同步) | | `/messages/stream` | POST | 发送消息(流式 SSE) | | `/messages/{id}` | DELETE | 删除消息 | | `/providers` | GET | LLM 提供商列表 | | `/providers` | POST | 创建提供商 | | `/providers/{id}` | GET | 提供商详情 | | `/providers/{id}` | PUT | 更新提供商 | | `/providers/{id}` | DELETE | 删除提供商 | | `/providers/{id}/test` | POST | 测试提供商连接 | | `/agents` | GET | Agent 列表 | | `/agents` | POST | 创建 Agent | | `/agents/{id}` | GET | Agent 详情 | | `/agents/{id}` | PUT | 更新 Agent | | `/agents/{id}` | DELETE | 删除 Agent | | `/chat-rooms` | GET | 聊天室列表 | | `/chat-rooms` | POST | 创建聊天室 | | `/chat-rooms/{id}` | GET | 聊天室详情 | | `/chat-rooms/{id}` | PUT | 更新聊天室 | | `/chat-rooms/{id}` | DELETE | 删除聊天室 | | `/chat-rooms/{id}/start` | POST | 启动聊天室 | | `/chat-rooms/{id}/stop` | POST | 停止聊天室 | | `/chat-rooms/{id}/reset` | POST | 重置聊天室 | | `/chat-rooms/{id}/messages` | GET | 聊天室消息 | | `/chat-rooms/{id}/agents` | POST | 添加 Agent | | `/chat-rooms/{id}/agents/{agent_id}` | PUT | 更新 Agent | | `/chat-rooms/{id}/agents/{agent_id}` | DELETE | 移除 Agent | | `/tools` | GET | 可用工具列表 | | `/tools/{name}` | GET | 工具详情 | | `/tools/{name}/execute` | POST | 执行工具 | | `/tasks` | GET | 任务列表 | | `/tasks` | POST | 创建任务 | | `/tasks/{id}` | GET | 任务详情 | | `/tasks/{id}` | PUT | 更新任务 | | `/tasks/{id}` | DELETE | 删除任务 | | `/tasks/{id}/steps` | POST | 添加步骤 | | `/tasks/{id}/steps/{step_id}` | PUT | 更新步骤 | | `/tasks/{id}/graph` | GET | 获取任务图 | | `/tasks/{id}/ready-steps` | GET | 获取就绪步骤 | | `/tasks/{id}/execute` | POST | 执行任务 | | `/tasks/{id}/export` | GET | 导出任务 | | `/tasks/import` | POST | 导入任务 | | `/health` | GET | 健康检查 | | `/` | GET | 服务信息 | ## 数据流 ### 消息处理流程 ```mermaid sequenceDiagram participant Client participant API as POST /messages/stream participant CS as ChatService participant AL as AgenticLoop participant Parser as LLMResponseParser participant LLM as LLM API participant TE as ToolExecutor Client->>API: POST {content, tools, thinking_enabled} API->>CS: stream_response() CS->>AL: execute() loop MAX_ITERATIONS (10) AL->>LLM: stream_call(messages, tools) LLM-->>AL: SSE Stream AL->>Parser: parse_chunk() Parser-->>AL: ParsedDelta {thinking, text, tool_calls} alt tool_calls AL->>TE: process_tool_calls_parallel() TE-->>AL: tool_results AL->>AL: 追加到 messages end end AL->>CS: done event CS->>CS: _save_message() CS->>API: SSE Stream API-->>Client: 流式响应 ``` ## SSE 事件 ### 普通会话 SSE 事件 | 事件 | 说明 | |------|------| | `process_step` | 结构化步骤(thinking/text/tool_call/tool_result),携带 `id`、`index` 确保渲染顺序 | | `done` | 响应完成,携带 message_id、token_count、usage | | `error` | 错误信息 | ### 聊天室 SSE 事件 | 事件 | 说明 | |------|------| | `room_started` | 聊天室启动,携带 room_id 和 task | | `round_start` | 回合开始,携带 round 和 max_rounds | | `message_start` | 消息开始,携带 msg_id、sender_name、sender_color、round_number | | `message_chunk` | 消息内容增量,携带 content 和 accumulated | | `message_end` | 消息结束,携带 msg_id、content、token_count | | `message` | 完整消息(用于存储和显示) | | `round_end` | 回合结束 | | `room_completed` | 聊天室完成 | | `room_paused` | 聊天室暂停 | | `agent_error` | Agent 执行错误 | | `error` | 通用错误 | ### process_step 事件格式 ```json {"type": "process_step", "step": {"id": "step-0", "index": 0, "type": "thinking", "content": "..."}} {"type": "process_step", "step": {"id": "step-1", "index": 1, "type": "text", "content": "回复文本..."}} {"type": "process_step", "step": {"id": "step-2", "index": 2, "type": "tool_call", "id_ref": "call_abc", "name": "web_search", "arguments": "{\"query\": \"...\"}"}} {"type": "process_step", "step": {"id": "step-3", "index": 3, "type": "tool_result", "id_ref": "call_abc", "name": "web_search", "content": "{...}", "success": true}} ``` | 字段 | 说明 | |------|------| | `id` | 步骤唯一标识(格式 `step-{index}`) | | `index` | 步骤序号,确保按正确顺序显示 | | `type` | 步骤类型:`thinking` / `text` / `tool_call` / `tool_result` | | `id_ref` | 工具调用引用 ID(仅 tool_call/tool_result) | | `name` | 工具名称(仅 tool_call/tool_result) | | `arguments` | 工具调用参数 JSON 字符串(仅 tool_call) | | `content` | 内容(thinking 的思考内容、text 的文本、tool_result 的返回结果) | | `success` | 工具执行是否成功(仅 tool_result) | ### done 事件格式 ```json {"type": "done", "message_id": "uuid", "token_count": 1234, "usage": {"prompt_tokens": 100, "completion_tokens": 200, "total_tokens": 300}} ``` ## 配置示例 ### config.yaml ```yaml app: secret_key: ${APP_SECRET_KEY} debug: true host: 0.0.0.0 port: 8000 database: type: sqlite url: sqlite:///./chat.db workspace: root: ./workspaces # 用户工作空间根目录 auto_create: true # 自动创建用户工作空间 llm: provider: deepseek api_key: ${DEEPSEEK_API_KEY} api_url: https://api.deepseek.com/v1 tools: enable_cache: true cache_ttl: 300 max_workers: 4 max_iterations: 10 logging: level: INFO ``` ## 环境变量 | 变量 | 说明 | 示例 | |------|------|------| | `APP_SECRET_KEY` | 应用密钥 | `your-secret-key` | | `DEEPSEEK_API_KEY` | DeepSeek API | `sk-xxxx` | | `DATABASE_URL` | 数据库连接 | `sqlite:///./chat.db` | ## LLM 适配器配置 ### OpenAI 兼容 (DeepSeek/GLM 等) ```yaml llm: provider: openai api_key: ${API_KEY} api_url: https://api.deepseek.com/v1 # 或其他兼容端点 ``` ### Anthropic Claude ```yaml llm: provider: anthropic api_key: ${ANTHROPIC_API_KEY} api_url: https://api.anthropic.com/v1 ``` ## 项目结构说明 ### 入口文件 - `run.py` - 启动 Uvicorn 服务器 ### 响应格式 所有 API 统一使用响应封装: ```json // 成功 {"success": true, "data": {...}, "message": "操作成功"} // 错误 {"success": false, "error": "错误信息", "code": 404} ``` ### 工具缓存机制 ToolExecutor 支持结果缓存: - TTL: 5 分钟(可配置) - 缓存 Key: `{tool_name}:{sorted_arguments_json}` - 调用历史记录最近 1000 条 ### 流式响应特点 1. 实时返回 thinking_content(模型思考过程) 2. 实时返回 text 增量更新 3. 工具调用并行执行,结果批量返回 4. 最终 `done` 事件包含完整 message_id 和 token 用量 ### 工作空间隔离 每个用户的工作空间完全隔离: - 用户目录基于 user_id 的 SHA256 哈希生成 - 所有文件操作强制在用户工作空间内 - 支持权限级别控制文件操作能力 ### MessageBuilder 用于构建发送给 LLM 的消息列表: - `add_system()` - 添加系统消息 - `add_user()` - 添加用户消息(JSON 格式) - `add_assistant()` - 添加助手消息 - `add_tool_result()` - 添加工具结果消息 - `extract_text()` - 从 JSON 内容中提取文本