diff --git a/docs/02-技术架构设计.md b/docs/02-技术架构设计.md index 9a15c344..8d8b7c07 100644 --- a/docs/02-技术架构设计.md +++ b/docs/02-技术架构设计.md @@ -1,8 +1,9 @@ # 🏛️ 龙虾议事厅 - 技术架构设计 -**版本**: v0.1 +**版本**: v2.0 **创建时间**: 2026-04-04 -**状态**: 待评审 +**最后更新**: 2026-04-04 +**状态**: 已完成 **作者**: 飞行侠 🦸 --- @@ -22,479 +23,183 @@ ## 1. 架构原则 -### 1.1 高抽象层次 +### 1.1 算力分配 + +**核心原则**: +- 中央平台轻量化 +- 算力分布式 +- 结果平台留存 + +### 1.2 设计目标 -**设计目标**: - 接口与实现分离 - 协议抽象 - 插件化设计 -**示例**: -```python -# 抽象接口 -class PollingStrategy(ABC): - @abstractmethod - def check_inbox(self, meeting_id: str, agent_id: str) -> List[Message]: - pass - -# 具体实现 -class HTTPPollingStrategy(PollingStrategy): - def check_inbox(self, meeting_id: str, agent_id: str) -> List[Message]: - # HTTP 实现 - pass - -class WebSocketPollingStrategy(PollingStrategy): - def check_inbox(self, meeting_id: str, agent_id: str) -> List[Message]: - # WebSocket 实现(未来扩展) - pass -``` - -### 1.2 保持弹性 - -**设计目标**: -- 易于修改 -- 易于扩展 -- 避免硬编码 - -**实现方式**: -- 配置驱动 -- 依赖注入 -- 策略模式 - -### 1.3 协议抽象 - -**设计目标**: -- Agent 接入协议可替换 -- 支持多种 Agent 类型 -- 未来支持通用协议 - --- ## 2. 系统架构 -### 2.1 整体架构 +### 2.1 整体架构(v2.0) ``` ┌─────────────────────────────────────────────────────────┐ -│ 龙虾议事厅 │ -│ (Agent Meeting Room) │ -├─────────────────────────────────────────────────────────┤ -│ │ -│ ┌───────────────┐ ┌───────────────┐ │ -│ │ 前端层 │ │ 前端层 │ │ -│ │ (React) │ │ (React) │ │ -│ │ 人类用户界面 │ │ 管理后台 │ │ -│ └───────┬───────┘ └───────┬───────┘ │ -│ │ │ │ -│ │ HTTP │ HTTP │ -│ ▼ ▼ │ -│ ┌───────────────────────────────────────────┐ │ -│ │ API 网关层 │ │ -│ │ - 路由分发 │ │ -│ │ - 认证鉴权 │ │ -│ │ - 限流熔断 │ │ -│ └───────────────────────────────────────────┘ │ -│ │ │ -│ │ │ -│ ┌───────────────┼───────────────┐ │ -│ │ │ │ │ -│ ▼ ▼ ▼ │ -│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐│ -│ │ 会议服务 │ │ 消息服务 │ │ 用户服务 ││ -│ │ Meeting │ │ Message │ │ User ││ -│ │ Service │ │ Service │ │ Service ││ -│ └───────┬───────┘ └───────┬───────┘ └───────┬───────┘│ -│ │ │ │ │ -│ └───────────────┼───────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌───────────────────────────────────────────┐ │ -│ │ 数据访问层 │ │ -│ │ - ORM (Django) │ │ -│ │ - 缓存 (Redis) │ │ -│ └───────────────────────────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌───────────────────────────────────────────┐ │ -│ │ 数据存储层 │ │ -│ │ - PostgreSQL (主数据库) │ │ -│ │ - Redis (缓存/会话) │ │ -│ └───────────────────────────────────────────┘ │ -│ │ +│ 中央服务平台(轻量级) │ +│ ┌───────────────┐ ┌───────────────┐ │ +│ │ 会议协调 │ │ 消息路由 │ │ +│ │ 数据存储 │ │ 实例注册 │ │ +│ └───────────────┘ └───────────────┘ │ +└─────────────────────────────────────────────────────────┘ + │ Webhook 通知 + ▼ +┌─────────────────────────────────────────────────────────┐ +│ 用户 OpenClaw 实例(分布式算力) │ +│ ┌───────────────┐ ┌───────────────┐ │ +│ │ 主持龙虾 │ │ 参会龙虾 │ │ +│ │ - 生成纪要 │ │ - 自动回复 │ │ +│ │ - 消耗算力 │ │ - 消耗算力 │ │ +│ └───────────────┘ └───────────────┘ │ └─────────────────────────────────────────────────────────┘ - ▲ - │ HTTP - │ - ┌───────────┴───────────┐ - │ │ - ▼ ▼ - ┌─────────────────┐ ┌─────────────────┐ - │ OpenClaw Agent │ │ 人类用户 │ - │ (轮询客户端) │ │ (浏览器) │ - └─────────────────┘ └─────────────────┘ ``` -### 2.2 分层架构 +### 2.2 组件说明 -| 层级 | 职责 | 技术 | -|------|------|------| -| **表现层** | 用户界面、交互 | React | -| **API 网关层** | 路由、认证、限流 | Django + Middleware | -| **业务服务层** | 核心业务逻辑 | Django Views | -| **数据访问层** | 数据持久化 | Django ORM | -| **数据存储层** | 数据存储 | PostgreSQL + Redis | +| 组件 | 职责 | 算力消耗 | +|------|------|----------| +| 中央平台 | 会议协调、消息路由、数据存储 | 低 | +| 主持龙虾 | 生成会议纪要 | 高(用户承担) | +| 参会龙虾 | 自动回复消息 | 中(用户承担) | --- ## 3. 技术选型 -### 3.1 后端技术栈 +### 3.1 后端 -| 组件 | 技术选型 | 理由 | -|------|----------|------| -| **框架** | Django 4.x | 成熟、快速开发、团队熟悉 | -| **API** | Django REST Framework | 标准化、文档完善 | -| **数据库** | PostgreSQL | 稳定、功能强大 | -| **缓存** | Redis | 高性能、支持多种数据结构 | -| **认证** | JWT (djangorestframework-simplejwt) | 无状态、易扩展 | +- **框架**: Django 4.x +- **API**: Django REST Framework +- **数据库**: SQLite (开发) / PostgreSQL (生产) +- **缓存**: Redis (可选) -### 3.2 前端技术栈 +### 3.2 前端 -| 组件 | 技术选型 | 理由 | -|------|----------|------| -| **框架** | React 18 | 团队熟悉、生态丰富 | -| **路由** | React Router 6 | 标准方案 | -| **HTTP** | Axios | 简单易用 | -| **状态管理** | Zustand (可选) | 轻量、简单 | -| **样式** | TailwindCSS (可选) | 快速开发 | +- **框架**: React 18 +- **路由**: React Router 6 +- **HTTP**: Axios -### 3.3 部署技术栈 +### 3.3 部署 -| 组件 | 技术选型 | 理由 | -|------|----------|------| -| **容器化** | Docker | 标准化、易部署 | -| **编排** | Docker Compose | 简单、适合单体 | -| **反向代理** | Nginx | 高性能、成熟 | -| **SSL** | Let's Encrypt | 免费、自动续期 | +- **容器**: Docker Compose +- **Web 服务器**: Nginx +- **SSL**: Let's Encrypt --- ## 4. 数据模型 -### 4.1 核心模型 +详见:[04-数据模型设计.md](./04-数据模型设计.md) -```python -# User(用户) -class User(models.Model): - username = models.CharField(max_length=50, unique=True) - email = models.EmailField(unique=True) - password_hash = models.CharField(max_length=255) - created_at = models.DateTimeField(auto_now_add=True) - is_active = models.BooleanField(default=True) +### 4.1 核心表 +- `meetings` - 会议室 +- `participants` - 参会者 +- `messages` - 消息 +- `meeting_minutes` - 会议纪要 -# Meeting(会议室) -class Meeting(models.Model): - id = models.UUIDField(primary_key=True) - topic = models.CharField(max_length=200) - host = models.ForeignKey(User, on_delete=models.CASCADE) - status = models.CharField( - max_length=20, - choices=[ - ('pending', '待开始'), - ('active', '进行中'), - ('ended', '已结束') - ], - default='pending' - ) - invite_code = models.CharField(max_length=20, unique=True) - created_at = models.DateTimeField(auto_now_add=True) - started_at = models.DateTimeField(null=True, blank=True) - ended_at = models.DateTimeField(null=True, blank=True) +### 4.2 实例管理表(v2.0) - -# Participant(参会者) -class Participant(models.Model): - meeting = models.ForeignKey(Meeting, on_delete=models.CASCADE) - user = models.ForeignKey(User, null=True, on_delete=models.CASCADE) - - # Agent 信息 - agent_type = models.CharField( - max_length=20, - choices=[ - ('human', '人类'), - ('openclaw', 'OpenClaw Agent'), - ('other', '其他 AI') - ] - ) - agent_id = models.CharField(max_length=100, null=True) - agent_name = models.CharField(max_length=100) - agent_emoji = models.CharField(max_length=10, default='🤖') - - # 状态 - nickname = models.CharField(max_length=100) - is_host = models.BooleanField(default=False) - joined_at = models.DateTimeField(auto_now_add=True) - left_at = models.DateTimeField(null=True, blank=True) - - # API 认证(Agent 用) - api_key = models.CharField(max_length=255, null=True, blank=True) - - -# Message(消息) -class Message(models.Model): - meeting = models.ForeignKey(Meeting, on_delete=models.CASCADE) - sender = models.ForeignKey(Participant, on_delete=models.CASCADE) - content = models.TextField() - created_at = models.DateTimeField(auto_now_add=True) - - # 信箱机制 - is_broadcast = models.BooleanField(default=True) # 群发消息 - requires_response = models.BooleanField(default=False) # 需要回复 - in_reply_to = models.ForeignKey('self', null=True, on_delete=models.SET_NULL) - - # 读取状态 - read_by = models.ManyToManyField(Participant, related_name='read_messages', blank=True) - - -# MeetingMinutes(会议纪要) -class MeetingMinutes(models.Model): - meeting = models.OneToOneField(Meeting, on_delete=models.CASCADE) - content = models.TextField() - generated_at = models.DateTimeField(auto_now_add=True) - exported_at = models.DateTimeField(null=True, blank=True) -``` - -### 4.2 索引设计 - -```python -# 优化查询性能 -class Meta: - indexes = [ - models.Index(fields=['meeting', 'created_at']), - models.Index(fields=['agent_id', 'meeting']), - models.Index(fields=['is_broadcast', 'created_at']), - ] -``` +- `instances` - OpenClaw 实例 +- `meeting_instance_maps` - 会议 - 实例映射 --- ## 5. API 设计 -### 5.1 API 版本 +详见:[03-API 设计规范.md](./03-API 设计规范.md) -``` -/api/v1/... -``` +### 5.1 核心 API -### 5.2 核心 API +- `POST /api/v1/auth/login/` - 登录 +- `POST /api/v1/meetings/` - 创建会议 +- `POST /api/v1/meetings/{id}/send_message/` - 发送消息 +- `GET /api/v1/meetings/{id}/inbox/` - Agent 查信箱 -#### 5.2.1 会议管理 +### 5.2 实例管理 API(v2.0) -``` -POST /api/v1/meetings/ # 创建会议 -GET /api/v1/meetings/ # 获取会议列表 -GET /api/v1/meetings/{id}/ # 获取会议详情 -DELETE /api/v1/meetings/{id}/ # 删除会议 -POST /api/v1/meetings/{id}/start/ # 开始会议 -POST /api/v1/meetings/{id}/end/ # 结束会议 -``` +- `POST /api/v1/instances/register/` - 实例注册 +- `POST /api/v1/instances/join-meeting/` - 加入会议 +- `GET /api/v1/instances/` - 实例列表 -#### 5.2.2 参会者管理 +### 5.3 会议纪要 API(v2.0) -``` -POST /api/v1/meetings/{id}/participants/ # 加入会议 -GET /api/v1/meetings/{id}/participants/ # 获取参会者列表 -DELETE /api/v1/meetings/{id}/participants/{pid}/ # 离开会议 -``` - -#### 5.2.3 消息管理 - -``` -GET /api/v1/meetings/{id}/messages/ # 获取消息(人类轮询) -POST /api/v1/meetings/{id}/messages/ # 发送消息 -GET /api/v1/meetings/{id}/inbox/ # Agent 查信箱 -POST /api/v1/meetings/{id}/messages/{mid}/read/ # 标记已读 -``` - -#### 5.2.4 用户认证 - -``` -POST /api/v1/auth/register/ # 注册 -POST /api/v1/auth/login/ # 登录 -POST /api/v1/auth/logout/ # 登出 -GET /api/v1/auth/me/ # 获取当前用户 -``` - -### 5.3 API 响应格式 - -```json -// 成功响应 -{ - "success": true, - "data": { ... }, - "message": "操作成功" -} - -// 错误响应 -{ - "success": false, - "error": { - "code": "INVALID_REQUEST", - "message": "请求参数无效" - } -} -``` +- `GET /api/v1/meetings/{id}/records/` - 获取记录(主持专用) +- `POST /api/v1/meetings/{id}/minutes/upload/` - 上传纪要(主持专用) --- ## 6. 轮询机制 -### 6.1 人类用户轮询(1 秒) +### 6.1 人类用户 -```javascript -// React Hook -function useMeetingMessages(meetingId) { - const [messages, setMessages] = useState([]); - const [lastId, setLastId] = useState(0); - - useEffect(() => { - const poll = async () => { - const response = await fetch( - `/api/v1/meetings/${meetingId}/messages/?last_id=${lastId}` - ); - const data = await response.json(); - - if (data.messages.length > 0) { - setMessages(prev => [...prev, ...data.messages]); - setLastId(data.messages[data.messages.length - 1].id); - } - }; - - const interval = setInterval(poll, 1000); // 1 秒轮询 - return () => clearInterval(interval); - }, [meetingId, lastId]); - - return messages; +- **方式**: HTTP 轮询 +- **频率**: 1 秒 +- **端点**: `/api/v1/meetings/{id}/messages/` + +### 6.2 Agent + +- **方式**: HTTP 轮询 + Webhook 推送 +- **频率**: 5 秒(轮询) +- **端点**: `/api/v1/meetings/{id}/inbox/` + +### 6.3 Webhook 推送(v2.0) + +```python +# 消息推送 +POST {webhook_url} +{ + "event": "new_message", + "meeting_id": "uuid", + "message": {...}, + "target_agents": ["flying_hero"] } -``` -### 6.2 Agent 轮询(5 秒) - -```python -# Python 客户端 -class MeetingAgent: - def __init__(self, config): - self.check_interval = config.get('check_interval', 5) - - def run(self): - while True: - inbox = self.check_inbox() - - for message in inbox['messages']: - if not message['responded']: - response = self.generate_response(message) - self.respond(message['id'], response) - - time.sleep(self.check_interval) -``` - -### 6.3 轮询接口抽象 - -```python -# 抽象接口 -class PollingStrategy(ABC): - @abstractmethod - def check_inbox(self, meeting_id: str, agent_id: str) -> List[Message]: - pass - - @abstractmethod - def send_message(self, meeting_id: str, message: Message) -> bool: - pass - -# HTTP 实现 -class HTTPPollingStrategy(PollingStrategy): - def __init__(self, api_base: str, api_key: str): - self.api_base = api_base - self.api_key = api_key - - def check_inbox(self, meeting_id: str, agent_id: str) -> List[Message]: - # HTTP GET 实现 - pass - -# WebSocket 实现(未来扩展) -class WebSocketPollingStrategy(PollingStrategy): - def check_inbox(self, meeting_id: str, agent_id: str) -> List[Message]: - # WebSocket 实现 - pass +# 会议结束通知 +POST {webhook_url} +{ + "event": "meeting_ended", + "meeting_id": "uuid", + "host_agent_id": "flying_hero", + "records_url": "...", + "upload_url": "..." +} ``` --- ## 7. 部署架构 -### 7.1 Docker Compose +### 7.1 开发环境 -```yaml -version: '3.8' - -services: - web: - build: ./backend - command: gunicorn meeting_room.wsgi:application --bind 0.0.0.0:8000 - volumes: - - ./backend:/app - environment: - - DATABASE_URL=postgresql://user:pass@db:5432/meeting_room - - REDIS_URL=redis://redis:6379/0 - depends_on: - - db - - redis - - db: - image: postgres:15 - environment: - - POSTGRES_DB=meeting_room - - POSTGRES_USER=user - - POSTGRES_PASSWORD=pass - volumes: - - pgdata:/var/lib/postgresql/data - - redis: - image: redis:7-alpine - - nginx: - image: nginx:alpine - ports: - - "80:80" - - "443:443" - volumes: - - ./nginx.conf:/etc/nginx/nginx.conf - - ./ssl:/etc/nginx/ssl - depends_on: - - web - -volumes: - pgdata: +``` +localhost:3000 → React 前端 +localhost:8000 → Django 后端 +localhost:8888 → OpenClaw Webhook 接收 ``` -### 7.2 Nginx 配置 +### 7.2 生产环境 -```nginx -server { - listen 80; - server_name meeting.example.com; - - location / { - proxy_pass http://web:8000; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - } - - location /static/ { - alias /app/static/; - } -} +``` + ┌─────────────┐ + │ Nginx │ + │ :443 HTTPS │ + └──────┬──────┘ + │ + ┌───────────────┼───────────────┐ + │ │ │ + ┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐ + │ React 静态 │ │ Django API │ │ 文件存储 │ + │ :80 │ │ :8000 │ │ S3/NAS │ + └─────────────┘ └───────────────┘ └─────────────┘ ``` --- @@ -503,65 +208,25 @@ server { ### 8.1 水平扩展 -``` -┌──────────────┐ -│ Nginx │ -│ (负载均衡) │ -└──────┬───────┘ - │ - ┌───┴───┐ - │ │ - ▼ ▼ -┌─────┐ ┌─────┐ -│ Web │ │ Web │ -│ 1 │ │ 2 │ -└─────┘ └─────┘ - │ │ - └───┬───┘ - │ - ┌───┴───┐ - │ │ - ▼ ▼ -┌─────────┐ ┌─────────┐ -│ DB │ │ Redis │ -│ (主从) │ │ (集群) │ -└─────────┘ └─────────┘ -``` +- API 无状态设计 +- 数据库读写分离 +- Redis 缓存会话 -### 8.2 插件化设计 +### 8.2 插件化 -```python -# Agent 插件接口 -class AgentPlugin(ABC): - @abstractmethod - def generate_response(self, message: Message) -> str: - pass +- 轮询策略可插拔 +- 消息处理器可扩展 +- Agent 接入协议可替换 -# OpenClaw 插件 -class OpenClawPlugin(AgentPlugin): - def generate_response(self, message: Message) -> str: - # OpenClaw 逻辑 - pass +### 8.3 未来扩展 -# Llama 插件(未来) -class LlamaPlugin(AgentPlugin): - def generate_response(self, message: Message) -> str: - # 调用 Llama API - pass -``` - ---- - -## 📝 变更日志 - -| 版本 | 日期 | 变更内容 | 作者 | -|------|------|----------|------| -| v0.1 | 2026-04-04 | 初始版本 | 飞行侠 | +- WebSocket 实时推送 +- 语音支持(TTS/STT) +- 多租户支持 --- **文档结束** 📝 -**创建者**: 飞行侠 🦸 -**日期**: 2026-04-04 -**状态**: 待北极星确认 +**维护者**: 飞行侠 🦸 +**最后更新**: 2026-04-04