354 lines
9.7 KiB
Markdown
354 lines
9.7 KiB
Markdown
# 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)
|
||
├── core/
|
||
│ ├── __init__.py
|
||
│ ├── config.py # 配置管理
|
||
│ └── database.py # 数据库连接
|
||
├── models/ # ORM 模型
|
||
│ ├── __init__.py
|
||
│ ├── user.py # User, LLMProvider, Project
|
||
│ ├── chat.py # Conversation, Message
|
||
│ ├── room.py # ChatRoom, Agent, RoomParticipant, ChatRoomMessage
|
||
│ └── participant.py # Participant (统一参与者抽象)
|
||
├── services/ # 服务层
|
||
│ ├── __init__.py
|
||
│ ├── chat.py # 聊天服务 (Agentic Loop)
|
||
│ ├── room.py # 聊天室服务 (多 Agent 编排)
|
||
│ ├── participant.py # 统一参与者服务
|
||
│ ├── room_ws.py # WebSocket 处理
|
||
│ ├── llm_service.py # LLM 服务
|
||
│ ├── message_service.py # 消息服务
|
||
│ ├── stream_service.py # 流式响应服务
|
||
│ ├── task.py # 任务服务
|
||
│ └── agent.py # Agent 管理
|
||
├── agents/ # Agent 系统
|
||
│ ├── __init__.py
|
||
│ ├── base.py # BaseAgent 抽象类
|
||
│ └── registry.py # Agent 注册表
|
||
├── api/ # API 路由层
|
||
│ ├── __init__.py
|
||
│ ├── auth.py # 认证 (登录/注册)
|
||
│ ├── conversations.py # 会话管理 (CRUD)
|
||
│ ├── messages.py # 消息处理
|
||
│ ├── providers.py # LLM 提供商管理
|
||
│ ├── tools.py # 工具管理
|
||
│ ├── agents.py # Agent 管理
|
||
│ └── rooms.py # 聊天室管理
|
||
├── tools/ # 工具系统
|
||
│ ├── __init__.py
|
||
│ ├── core.py # 核心类 (ToolRegistry, ToolDefinition, ToolResult)
|
||
│ ├── factory.py # @tool 装饰器
|
||
│ ├── executor.py # 工具执行器
|
||
│ └── builtin/ # 内置工具
|
||
│ ├── __init__.py
|
||
│ ├── code.py # 代码执行
|
||
│ ├── crawler.py # 网页爬虫
|
||
│ └── data.py # 数据处理
|
||
└── utils/ # 工具函数
|
||
└── helpers.py # 密码哈希、ID生成、响应封装
|
||
|
||
run.py # 应用入口文件
|
||
config.yaml # 配置文件
|
||
```
|
||
|
||
## 核心组件
|
||
|
||
### 1. 应用工厂 (`__init__.py`)
|
||
FastAPI 应用入口,使用 lifespan 管理生命周期:
|
||
- 启动:初始化数据库、注册内置工具、创建默认管理员用户
|
||
- 关闭:清理资源
|
||
|
||
### 2. 配置管理 (`core/config.py`)
|
||
使用 YAML 文件管理配置:
|
||
- 配置文件:`config.yaml`
|
||
- 环境变量替换:`${VAR_NAME}`
|
||
- 单例模式全局访问
|
||
|
||
### 3. 数据库 (`core/database.py`)
|
||
- SQLAlchemy 同步支持
|
||
- SQLite 默认数据库
|
||
- 依赖注入获取会话
|
||
|
||
### 4. ORM 模型
|
||
|
||
#### 统一参与者架构
|
||
|
||
```mermaid
|
||
classDiagram
|
||
class Participant {
|
||
+str participant_id
|
||
+str name
|
||
+ParticipantType participant_type
|
||
+from_user(User) Participant
|
||
+from_agent(...) Participant
|
||
+from_participant_id(str) Participant
|
||
}
|
||
|
||
class ParticipantType {
|
||
<<enumeration>>
|
||
USER = "user"
|
||
AGENT = "agent"
|
||
}
|
||
|
||
class RoomParticipant {
|
||
+str room_id
|
||
+str agent_id
|
||
+int user_id
|
||
+str role
|
||
+participant_id property
|
||
+participant_type property
|
||
}
|
||
|
||
class ChatRoomMessage {
|
||
+str participant_id
|
||
+sender_type property
|
||
+sender_id property
|
||
}
|
||
|
||
Participant --> ParticipantType
|
||
RoomParticipant --> Participant
|
||
ChatRoomMessage --> Participant
|
||
```
|
||
|
||
### 5. 聊天室系统
|
||
|
||
#### WebSocket 端点
|
||
- `/ws/chat-room/{room_id}?participant_type=user&participant_id=123&participant_name=John`
|
||
- `/ws/chat-room/{room_id}?participant_type=agent&participant_id=agent-1&participant_name=Assistant`
|
||
|
||
#### ParticipantService
|
||
统一处理用户和 Agent 的消息:
|
||
- `process_message()` - 处理来自任何参与者的消息
|
||
- `send_message()` - 主动发送消息
|
||
|
||
### 6. 工具系统
|
||
|
||
```mermaid
|
||
classDiagram
|
||
class ToolDefinition {
|
||
+str name
|
||
+str description
|
||
+dict parameters
|
||
+Callable handler
|
||
+str category
|
||
+to_openai_format() dict
|
||
}
|
||
|
||
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~
|
||
+execute(name, arguments) dict
|
||
}
|
||
|
||
class ToolExecutor {
|
||
+enable_cache: bool
|
||
+process_tool_calls(tool_calls, context) list
|
||
+process_tool_calls_parallel(tool_calls, context) list
|
||
}
|
||
```
|
||
|
||
#### 内置工具
|
||
|
||
| 工具 | 功能 | 说明 |
|
||
|------|------|------|
|
||
| `python_execute` | 执行 Python 代码 | 支持 print 输出、变量访问 |
|
||
| `python_eval` | 计算表达式 | 快速求值 |
|
||
| `web_search` | DuckDuckGo HTML | DuckDuckGo HTML 搜索 |
|
||
| `web_fetch` | 网页抓取 | httpx + BeautifulSoup,支持 text/links/structured |
|
||
| `batch_fetch` | 批量抓取 | 并发获取多个页面 |
|
||
| `process_data` | 数据处理 | JSON 转换、格式化等 |
|
||
|
||
#### 工具开发规范
|
||
|
||
**核心原则:装饰器自动处理一切,工具函数只写业务逻辑**
|
||
|
||
```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": "..."}` |
|
||
|
||
#### 工具调用流程
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
A[LLM 请求] --> B{ToolRegistry.execute}
|
||
B --> C[@tool 装饰器]
|
||
C --> D{验证 required_params}
|
||
D -->|失败| E[返回 error]
|
||
D -->|成功| F[执行工具函数]
|
||
F --> G{try-except}
|
||
G -->|成功| H[包装 ToolResult]
|
||
G -->|异常| I[捕获并转换 error]
|
||
I --> H
|
||
H --> J[返回 ToolResult]
|
||
J --> K[前端 ProcessBlock 显示]
|
||
```
|
||
|
||
#### Message Content JSON 结构
|
||
|
||
`content` 字段统一使用 JSON 格式存储:
|
||
|
||
**User 消息:**
|
||
```json
|
||
{
|
||
"text": "用户输入的文本内容",
|
||
"attachments": [
|
||
{"name": "utils.py", "extension": "py", "content": "..."}
|
||
]
|
||
}
|
||
```
|
||
|
||
**Assistant 消息:**
|
||
```json
|
||
{
|
||
"text": "AI 回复的文本内容",
|
||
"tool_calls": [...],
|
||
"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` 顺序排列。
|
||
|
||
## 数据流
|
||
|
||
### 消息处理流程
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant Client
|
||
participant API as WebSocket/API
|
||
participant PS as ParticipantService
|
||
participant RS as ChatRoomService
|
||
participant LLM as LLM API
|
||
participant TE as ToolExecutor
|
||
|
||
Client->>API: send_message(content)
|
||
API->>PS: process_message()
|
||
PS->>RS: save_message()
|
||
PS->>RS: dispatch to agents
|
||
|
||
loop Agentic Loop
|
||
RS->>LLM: call(messages, tools)
|
||
LLM-->>RS: SSE Stream
|
||
alt tool_calls
|
||
RS->>TE: process_tool_calls_parallel()
|
||
TE-->>RS: tool_results
|
||
end
|
||
end
|
||
|
||
RS-->>PS: process_step events
|
||
PS-->>Client: SSE Stream
|
||
```
|
||
|
||
## WebSocket 事件
|
||
|
||
| 事件 | 说明 |
|
||
|------|------|
|
||
| `connected` | 连接成功 |
|
||
| `history` | 历史消息 |
|
||
| `agents` | 聊天室 Agent 列表 |
|
||
| `message` | 新消息 |
|
||
| `typing` | 打字状态 |
|
||
| `process_step` | Agent 处理步骤 |
|
||
| `done` | 处理完成 |
|
||
| `error` | 错误信息 |
|
||
| `system` | 系统消息 (join/leave) |
|
||
|
||
## 配置示例
|
||
|
||
### 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
|
||
|
||
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
|
||
```
|
||
|
||
## 环境变量
|
||
|
||
| 变量 | 说明 | 示例 |
|
||
|------|------|------|
|
||
| `APP_SECRET_KEY` | 应用密钥 | `your-secret-key` |
|
||
| `DEEPSEEK_API_KEY` | DeepSeek API | `sk-xxxx` |
|
||
| `DATABASE_URL` | 数据库连接 | `sqlite:///./chat.db` |
|