diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md deleted file mode 100644 index 7ae26a7..0000000 --- a/docs/ARCHITECTURE.md +++ /dev/null @@ -1,835 +0,0 @@ -# X-Agents 智能体平台架构设计 - -## 一、整体架构 - -``` -┌─────────────────────────────────────────────────────────────────────────────┐ -│ 用户层 │ -│ Web / App / API Consumer │ -└─────────────────────────────────┬───────────────────────────────────────────┘ - │ HTTP / WebSocket - ▼ -┌─────────────────────────────────────────────────────────────────────────────┐ -│ Go API Gateway │ -│ ┌─────────────────────────────────────────────────────────────────────────┐│ -│ │ • HTTP Server (Gin) • 认证鉴权 (JWT) ││ -│ │ • 路由管理 • 限流熔断 ││ -│ │ • 业务逻辑 • 日志监控 ││ -│ │ • 数据库操作 • 权限控制 (RBAC) ││ -│ └─────────────────────────────────────────────────────────────────────────┘│ -└─────────────────────────────────┬───────────────────────────────────────────┘ - │ HTTP JSON API - ▼ -┌─────────────────────────────────────────────────────────────────────────────┐ -│ Python Agent Engine │ -│ ┌─────────────────────────────────────────────────────────────────────────┐│ -│ │ • FastAPI Server • Agent Core (LangChain/AutoGen) ││ -│ │ • LLM Adapter • Tool Registry (白名单) ││ -│ │ • Memory Manager • Sandbox Executor (沙盒) ││ -│ │ • RAG Pipeline • Audit Logger ││ -│ └─────────────────────────────────────────────────────────────────────────┘│ -└─────────────────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 二、系统分层 - -### 2.1 Go 后端层 (server/) - -``` -server/ # Go API Gateway 服务 -├── cmd/api/ # 程序入口 -│ └── main.go -├── internal/ -│ ├── config/ # 配置管理 -│ │ └── config.go -│ ├── handler/ # HTTP处理器 -│ │ ├── auth_handler.go # 认证接口 -│ │ ├── chat_handler.go # 聊天接口 -│ │ └── approval_handler.go # 审批接口 -│ ├── service/ # 业务逻辑 -│ │ ├── auth_service.go -│ │ ├── chat_service.go -│ │ └── approval_service.go -│ ├── repository/ # 数据访问层 -│ │ ├── user_repo.go -│ │ ├── agent_repo.go -│ │ └── audit_repo.go -│ ├── middleware/ # 中间件 -│ │ └── auth.go -│ └── model/ # 数据模型 -│ ├── user.go -│ ├── agent.go -│ └── audit.go -├── config/ # 配置文件 -│ └── config.yaml -├── Dockerfile -├── go.mod -└── go.sum -``` - -### 2.2 Python Agent 层 (agent/) - -``` -agent/ # Python Agent Engine -├── app/ -│ ├── main.py # FastAPI入口 -│ ├── api/ -│ │ └── routes.py # API路由 -│ ├── agent/ -│ │ ├── core/ -│ │ │ ├── agent.py # Agent管理器 -│ │ │ └── executor.py # Agent执行器 -│ │ ├── tools/ -│ │ │ ├── registry.py # 工具注册表(白名单) -│ │ │ └── impl/ # 工具实现 -│ │ │ ├── search.py -│ │ │ ├── calculator.py -│ │ │ └── time_tool.py -│ │ └── memory/ -│ │ └── session.py # 会话管理 -│ ├── llm/ -│ │ └── factory.py # LLM工厂 -│ └── security/ -│ ├── audit.py # 审计日志 -│ └── approval.py # 审批服务 -├── requirements.txt -├── Dockerfile -└── pyproject.toml -``` - -### 2.3 根目录结构 - -``` -X-Agents/ -├── server/ # Go API Gateway -├── agent/ # Python Agent Engine -├── web/ # 前端 (Vue.js) -├── docs/ -│ └── ARCHITECTURE.md # 架构文档 -├── docker-compose.yml # 容器编排 -├── .env.example # 环境变量模板 -└── README.md -│ ├── service/ # 业务逻辑 -│ │ ├── chat_service.go -│ │ ├── agent_service.go -│ │ └── approval_service.go # 审批服务 -│ ├── repository/ # 数据访问层 -│ │ ├── user_repo.go -│ │ ├── agent_repo.go -│ │ └── audit_repo.go -│ ├── middleware/ # 中间件 -│ │ ├── auth.go # 认证中间件 -│ │ ├── rbac.go # 权限中间件 -│ │ └── audit.go # 审计中间件 -│ ├── client/ # 外部服务客户端 -│ │ └── python_client.go # Python服务HTTP客户端 -│ └── model/ # 数据模型 -│ ├── user.go -│ ├── agent.go -│ └── audit.go -├── pkg/ -│ ├── utils/ # 工具函数 -│ └── errors/ # 错误定义 -└── go.mod -``` - -### 2.2 Python AI 层 (智能逻辑) - -``` -python/ -├── app/ -│ ├── main.py # FastAPI入口 -│ ├── api/ -│ │ ├── routes.py # 路由定义 -│ │ └── dependencies.py # 依赖注入 -│ ├── agent/ -│ │ ├── core/ -│ │ │ ├── agent.py # Agent核心 -│ │ │ ├── executor.py # 执行器 -│ │ │ └── memory.py # 记忆管理 -│ │ ├── tools/ -│ │ │ ├── registry.py # 工具注册表 -│ │ │ ├── base.py # 工具基类 -│ │ │ ├── security.py # 安全检查 -│ │ │ └── impl/ # 具体工具实现 -│ │ │ ├── search.py -│ │ │ ├── calculator.py -│ │ │ ├── database.py -│ │ │ └── sandbox.py # 沙盒执行 -│ │ └── sandbox/ -│ │ ├── docker_sandbox.py -│ │ └── wasm_sandbox.py -│ ├── llm/ -│ │ ├── factory.py # LLM工厂 -│ │ ├── openai_adapter.py -│ │ ├── anthropic_adapter.py -│ │ └── base.py -│ ├── rag/ -│ │ ├── vector_store.py # 向量存储 -│ │ ├── retriever.py # 检索器 -│ │ └── pipeline.py # RAG流程 -│ └── security/ -│ ├── permission.py # 权限检查 -│ ├── approval.py # 审批管理 -│ └── audit.py # 安全审计 -├── requirements.txt -└── pyproject.toml -``` - ---- - -## 三、通信机制 - -### 3.1 HTTP API 通信 - -``` -┌──────────────────┐ HTTP POST ┌──────────────────┐ -│ │ ─────────────▶ │ │ -│ Go Service │ JSON Request │ Python Service │ -│ (Port: 8080) │ │ (Port: 8081) │ -│ │ ◀───────────── │ │ -└──────────────────┘ JSON Response └──────────────────┘ -``` - -#### 接口设计 - -**1. Agent 聊天接口** - -``` -POST /api/v1/agent/chat -Content-Type: application/json -Authorization: Bearer - -Request: -{ - "agent_id": "agent_001", - "message": "帮我查询用户数据", - "session_id": "session_xxx", - "context": {} // 额外上下文 -} - -Response: -{ - "reply": "查询结果...", - "session_id": "session_xxx", - "tools_used": ["query_database"], - "metadata": {} -} -``` - -**2. 工具执行审批接口** - -``` -POST /api/v1/tool/approve -Request: -{ - "request_id": "req_001", - "tool_name": "execute_sql", - "params": {"sql": "SELECT * FROM users"}, - "reason": "用户查询自己的订单", - "approved": true // true=批准, false=拒绝 -} -``` - -**3. 工具执行状态查询** - -``` -GET /api/v1/tool/request/{request_id} -Response: -{ - "status": "pending|approved|rejected|completed", - "tool_name": "execute_sql", - "created_at": "2024-01-01T00:00:00Z", - "result": null // 如果已完成 -} -``` - -### 3.2 Go → Python 客户端 - -```go -// internal/client/python_client.go - -package client - -type PythonAgentClient struct { - baseURL string - client *http.Client -} - -type ChatRequest struct { - AgentID string `json:"agent_id"` - Message string `json:"message"` - SessionID string `json:"session_id"` - Context map[string]interface{} `json:"context"` -} - -type ChatResponse struct { - Reply string `json:"reply"` - SessionID string `json:"session_id"` - ToolsUsed []string `json:"tools_used"` - Metadata map[string]interface{} `json:"metadata"` -} - -// Chat 调用Python Agent服务 -func (c *PythonAgentClient) Chat(ctx context.Context, req ChatRequest) (*ChatResponse, error) { - // 1. 构建请求 - // 2. 添加超时 - // 3. 发送请求 - // 4. 处理响应 - // 5. 错误处理 -} -``` - ---- - -## 四、沙盒安全机制 - -### 4.1 安全架构总览 - -``` -┌─────────────────────────────────────────────────────────────────────────┐ -│ 安全控制层 │ -│ │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌──────────┐ │ -│ │ 权限管理 │ │ 工具分级 │ │ 人工审批 │ │ 审计日志 │ │ -│ │ (RBAC) │ │ (白名单) │ │ (Approval) │ │ (Audit) │ │ -│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └────┬─────┘ │ -└─────────┼─────────────────┼─────────────────┼─────────────────┼────────┘ - │ │ │ │ - ▼ ▼ ▼ ▼ -┌─────────────────────────────────────────────────────────────────────────┐ -│ Agent 执行层 │ -│ │ -│ User Request ─▶ Permission Check ─▶ Tool Lookup ─▶ Execute ─▶ Result │ -│ │ │ │ │ -│ ▼ ▼ ▼ │ -│ [Need Approval] ──▶ [Pending Queue] ──▶ [Notify] │ -└─────────────────────────────────────────────────────────────────────────┘ -``` - -### 4.2 工具安全等级 - -```python -# python/app/agent/tools/security.py - -from enum import Enum -from dataclasses import dataclass -from typing import List, Callable - -class SecurityLevel(Enum): - """工具安全等级""" - SAFE = "safe" # 安全操作:搜索、计算、读取公开数据 - REVIEW = "review" # 需要审核:修改数据、发送消息 - DANGER = "danger" # 危险操作:删除数据、执行代码、敏感API - -@dataclass -class ToolMetadata: - """工具元数据""" - name: str - description: str - security_level: SecurityLevel - require_approval: bool # 是否需要人工审批 - allowed_roles: List[str] # 允许调用的角色 - rate_limit: int # 调用频率限制 - timeout: int # 超时时间(秒) - -class ToolSecurity: - """工具安全管理""" - - # 安全等级阈值 - APPROVAL_THRESHOLD = SecurityLevel.REVIEW - - @staticmethod - def check_permission(tool: ToolMetadata, user_role: str) -> bool: - """检查用户权限""" - if user_role in tool.allowed_roles: - return True - return False - - @staticmethod - def need_approval(tool: ToolMetadata) -> bool: - """判断是否需要审批""" - return tool.security_level.value >= ToolSecurity.APPROVAL_THRESHOLD.value -``` - -### 4.3 工具注册与执行 - -```python -# python/app/agent/tools/registry.py - -from typing import Dict, Callable, Any -from .security import ToolMetadata, SecurityLevel - -class ToolRegistry: - """工具注册表 - 白名单机制""" - - def __init__(self): - self._tools: Dict[str, tuple[Callable, ToolMetadata]] = {} - - def register( - self, - name: str, - func: Callable, - security_level: SecurityLevel = SecurityLevel.SAFE, - require_approval: bool = False, - allowed_roles: List[str] = None, - description: str = "" - ): - """注册工具到白名单""" - metadata = ToolMetadata( - name=name, - description=description, - security_level=security_level, - require_approval=require_approval or security_level == SecurityLevel.REVIEW, - allowed_roles=allowed_roles or ["user", "admin"], - rate_limit=100, - timeout=30 - ) - self._tools[name] = (func, metadata) - - def get_tool(self, name: str) -> tuple[Callable, ToolMetadata]: - """获取工具(必须在白名单中)""" - if name not in self._tools: - raise ValueError(f"Tool '{name}' not found in whitelist") - return self._tools[name] - - def list_tools(self) -> List[ToolMetadata]: - """列出所有可用工具""" - return [meta for _, meta in self._tools.values()] -``` - -### 4.4 沙盒执行 - -```python -# python/app/agent/tools/sandbox/docker_sandbox.py - -import subprocess -import tempfile -import shutil -import os -from typing import Any, Dict - -class DockerSandbox: - """Docker沙盒执行环境""" - - def __init__(self, image: str = "python-sandbox:latest", timeout: int = 30): - self.image = image - self.timeout = timeout - - def execute(self, code: str, language: str = "python") -> Dict[str, Any]: - """在沙盒中执行代码""" - - # 1. 创建临时文件 - with tempfile.NamedTemporaryFile( - mode='w', - suffix=f'.{language}', - delete=False - ) as f: - f.write(code) - temp_path = f.name - - try: - # 2. Docker容器执行 - result = subprocess.run( - [ - "docker", "run", - "--rm", - "--network", "none", # 断网 - "--memory", "256m", # 内存限制 - "--cpus", "0.5", # CPU限制 - "-v", f"{temp_path}:/code/{os.path.basename(temp_path)}", - self.image, - "python", f"/code/{os.path.basename(temp_path)}" - ], - capture_output=True, - timeout=self.timeout - ) - - return { - "success": result.returncode == 0, - "output": result.stdout.decode(), - "error": result.stderr.decode() - } - - except subprocess.TimeoutExpired: - return { - "success": False, - "output": "", - "error": "Execution timeout" - } - finally: - # 3. 清理临时文件 - os.unlink(temp_path) - -# 使用示例 -@sandbox.execute -def execute_code(code: str) -> str: - """安全执行用户代码""" - pass -``` - -### 4.5 Human in the Loop (人工审批) - -```python -# python/app/security/approval.py - -from enum import Enum -from dataclasses import dataclass -from typing import Optional -from datetime import datetime -import asyncio - -class ApprovalStatus(Enum): - PENDING = "pending" - APPROVED = "approved" - REJECTED = "rejected" - -@dataclass -class ApprovalRequest: - """审批请求""" - request_id: str - tool_name: str - params: dict - user_id: str - reason: str - status: ApprovalStatus - created_at: datetime - reviewed_at: Optional[datetime] - reviewed_by: Optional[str] - -class ApprovalService: - """审批服务""" - - def __init__(self, http_client): - self.client = http_client - self.pending: Dict[str, ApprovalRequest] = {} - - async def request_approval( - self, - tool_name: str, - params: dict, - user_id: str, - reason: str - ) -> str: - """请求审批""" - request_id = generate_uuid() - - approval_req = ApprovalRequest( - request_id=request_id, - tool_name=tool_name, - params=params, - user_id=user_id, - reason=reason, - status=ApprovalStatus.PENDING, - created_at=datetime.now(), - reviewed_at=None, - reviewed_by=None - ) - - self.pending[request_id] = approval_req - - # 通知Go后端有新审批 - await self.notify_go_service(approval_req) - - return request_id - - async def wait_for_approval(self, request_id: str, timeout: int = 300) -> bool: - """等待审批结果""" - start = datetime.now() - - while (datetime.now() - start).seconds < timeout: - if request_id in self.pending: - status = self.pending[request_id].status - if status == ApprovalStatus.APPROVED: - return True - elif status == ApprovalStatus.REJECTED: - return False - await asyncio.sleep(1) - - raise TimeoutError("Approval request timeout") -``` - -### 4.6 全链路审计 - -```python -# python/app/security/audit.py - -from datetime import datetime -from typing import Any, Dict -import json - -class AuditLogger: - """审计日志""" - - def __init__(self, log_file: str = "audit.log"): - self.log_file = log_file - - def log( - self, - action: str, - user_id: str, - agent_id: str, - details: Dict[str, Any], - result: str = "success" - ): - """记录审计日志""" - entry = { - "timestamp": datetime.now().isoformat(), - "action": action, - "user_id": user_id, - "agent_id": agent_id, - "details": details, - "result": result - } - - # 写入日志文件 - with open(self.log_file, 'a') as f: - f.write(json.dumps(entry) + '\n') - - # 发送到Go后端 - self.send_to_backend(entry) - - def log_tool_execution( - self, - user_id: str, - tool_name: str, - params: Dict[str, Any], - approved: bool, - result: Any - ): - """记录工具执行""" - self.log( - action="tool_execution", - user_id=user_id, - agent_id="", - details={ - "tool_name": tool_name, - "params": params, - "approved": approved, - "result_preview": str(result)[:100] - } - ) -``` - ---- - -## 五、权限模型 (Go端) - -### 5.1 用户角色 - -```go -// go/internal/model/user.go - -package model - -// 权限级别 -type PermissionLevel int - -const ( - PermissionRead PermissionLevel = 1 // 只读 - PermissionWrite PermissionLevel = 2 // 读写 - PermissionExecute PermissionLevel = 3 // 可执行工具 - PermissionAdmin PermissionLevel = 4 // 管理员 -) - -// 角色定义 -type Role struct { - ID string `json:"id"` - Name string `json:"name"` - Permissions []PermissionLevel `json:"permissions"` -} - -// 用户 -type User struct { - ID string `json:"id"` - Username string `json:"username"` - RoleID string `json:"role_id"` - Role *Role `json:"role,omitempty"` -} -``` - -### 5.2 Agent定义 - -```go -// go/internal/model/agent.go - -package model - -type Agent struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - OwnerID string `json:"owner_id"` - - // Agent能力配置 - Capabilities []string `json:"capabilities"` // 可用工具列表 - MemoryLimit int64 `json:"memory_limit"` // 内存限制 - Timeout int `json:"timeout"` // 超时时间 - - // 安全配置 - SecurityLevel SecurityLevel `json:"security_level"` - AllowDangerousTools bool `json:"allow_dangerous_tools"` - - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` -} -``` - ---- - -## 六、部署架构 - -### 6.1 Docker Compose - -```yaml -# docker-compose.yml - -version: '3.8' - -services: - # Go API 服务 - go-api: - build: ./go - ports: - - "8080:8080" - environment: - - DATABASE_URL=postgres://user:pass@db:5432/agents - - PYTHON_SERVICE_URL=http://python-agent:8081 - - JWT_SECRET=your-secret - depends_on: - - db - - python-agent - - # Python Agent 服务 - python-agent: - build: ./python - ports: - - "8081:8081" - environment: - - OPENAI_API_KEY=${OPENAI_API_KEY} - - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} - volumes: - - ./python/app:/app - - /var/run/docker.sock:/var/run/docker.sock # 如果需要Docker沙盒 - - # 数据库 - db: - image: postgres:15 - environment: - POSTGRES_USER: user - POSTGRES_PASSWORD: pass - POSTGRES_DB: agents - volumes: - - db-data:/var/lib/postgresql/data - - # Redis (缓存/会话) - redis: - image: redis:7 - volumes: - - redis-data:/data - - # 向量数据库 (可选) - qdrant: - image: qdrant/qdrant - volumes: - - qdrant-data:/qdrant/storage - -volumes: - db-data: - redis-data: - qdrant-data: -``` - ---- - -## 七、开发流程 - -### 7.1 请求流程图 - -``` -┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ -│ 用户 │────▶│ Go │────▶│ Python │────▶│ LLM │────▶│ 返回 │ -│ 请求 │ │ 鉴权 │ │ Agent │ │ +Tools │ │ 结果 │ -└─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ - │ │ - │ │ - ▼ ▼ - ┌─────────┐ ┌─────────┐ - │ 检查 │ │ 权限 │ - │ 权限 │ │ 检查 │ - └─────────┘ └─────────┘ - │ - ▼ - ┌─────────────────────┐ - │ 工具安全等级判断 │ - └─────────────────────┘ - │ - ┌─────────────────┼─────────────────┐ - │ │ │ - ▼ ▼ ▼ - ┌──────────┐ ┌──────────┐ ┌──────────┐ - │ Safe │ │ Review │ │ Danger │ - │ 直接执行 │ │ 等待审批 │ │ 拒绝执行 │ - └──────────┘ └──────────┘ └──────────┘ -``` - -### 7.2 目录结构总览 - -``` -X-Agents/ -├── docs/ -│ └── ARCHITECTURE.md # 本文档 -│ -├── go/ # Go 后端 -│ ├── cmd/ -│ ├── internal/ -│ ├── pkg/ -│ ├── go.mod -│ └── Dockerfile -│ -├── python/ # Python AI 层 -│ ├── app/ -│ │ ├── api/ -│ │ ├── agent/ -│ │ ├── llm/ -│ │ ├── rag/ -│ │ └── security/ -│ ├── requirements.txt -│ └── Dockerfile -│ -├── web/ # 前端 (Vue) -│ ├── src/ -│ └── package.json -│ -├── docker-compose.yml # 容器编排 -└── README.md -``` - ---- - -## 八、总结 - -### 架构核心原则 - -| 原则 | 实现方式 | -|------|----------| -| **分层治理** | Go负责业务/权限,Python负责AI逻辑 | -| **安全优先** | 工具分级+权限控制+人工审批+审计日志 | -| **通信简洁** | HTTP JSON API,后续可升级gRPC | -| **可扩展** | 模块化设计,支持多Agent/多Python服务 | -| **可观测** | 全链路日志+监控 | - -### 安全特性 - -- [x] 工具白名单机制 -- [x] 安全等级分级 (Safe/Review/Danger) -- [x] RBAC权限控制 -- [x] Human in the Loop 人工审批 -- [x] 沙盒执行环境 (Docker) -- [x] 全链路审计日志 - ---- - -*本文档将随项目开发持续更新* diff --git a/docs/agents.html b/docs/agents.html deleted file mode 100644 index 4a6370f..0000000 --- a/docs/agents.html +++ /dev/null @@ -1,337 +0,0 @@ - - - - - - Remo MVP Design Interface - - - - - - - - - - -
-
-
-
-
-
-
- - Remo MVP Design -
-
- - -
-
- - -
- - - - -
- -
- -
-
-
- -
- - Figma -
-
-
- - -
-
-

1. Start your project from sketch

-
- - -
- - -
-
-
-
- -
-
- Action -
-
-
- -
-
-

2. Take a frame and start designing

-
- - -
- - -
-
-
- -
- - Figma -
-
-
- - -
-
-

3. Add few shapes

-
- - -
- - -
-
-
- -
- - Figma -
-
-
- - -
-
-

4. Split into paths

-
- - -
-
-
-
-
-
-
-
-
-
- - -
- Path A - Path B -
- - -
- -
-
-
- -
- - Figma -
-
-
- - -
-
-

5. Split into paths

-
- - -
-
-
- -
- - Figma -
-
-
- - -
-
-

6. Split into paths

-
-
-
- - -
- - - - - - - -
- -
-
- - - -
- - \ No newline at end of file diff --git a/docs/dashboard.html b/docs/dashboard.html deleted file mode 100644 index b0c82a2..0000000 --- a/docs/dashboard.html +++ /dev/null @@ -1,692 +0,0 @@ - - - - - - Saasfactor Dashboard - - - - - - - - - - - - - -
- -
-
- - Dashboard -
-
- Date Range -
- 10 December - To - 12 December - -
- -
-
- - -
- - -
-
-

Active Agents

-
- Errors - -
-
-
-
-
-
3
- -
-
-
-
-
-
-
- -
    -
  • -
    - - template-google-adk-api -
    - 1 -
  • -
  • -
    - - mcp-google-adk-api - Error -
    - 1 -
  • -
  • -
    - - template-openai-api - Error -
    - 1 -
  • -
-
- - -
-
-

Active MCP Servers

-
- Errors - -
-
-
-
-
-
21
- -
-
-
-
-
-
-
- -
    -
  • -
    - - linear-demo -
    - 15 -
  • -
  • -
    - - google-maps -
    - 4 -
  • -
  • -
    - - explorer-mcp -
    - 2 -
  • -
-
- - -
-
-

Active Models

-
- Errors - -
-
-
-
-
-
13
- -
-
-
-
-
-
-
- -
    -
  • -
    - - gpt-40-2024-08-12 -
    - 2 -
  • -
  • -
    - - cerebras-sandbox -
    - 6 -
  • -
  • -
    - - sandbox-openai -
    - 5 -
  • -
-
- - - -
-

All deployment request Insights

- -
-
-
Requests
-
36
-
-
-
Agents calls
-
3
-
-
-
MCP servers calls
-
21
-
-
-
Models requests
-
13
-
-
- - -
- -
- -
-
-
-
-
-
-
- - -
- 8 - 6 - 4 - 2 - 0 -
- - -
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
-
-
- - -
- 3:02 PM - 3:07 PM - 3:12 PM - 3:17 PM - 3:22 PM - 3:27 PM - 3:32 PM - 3:37 PM - 3:42 PM - 3:47 PM -
-
- - -
-
- - Agents calls -
-
- - MCP servers calls -
-
- - Models requests -
-
-
- - -
-

Top 10 requests

- -
- - -
- -
    -
  • -
    - - gpt-40-2024-08-12 -
    - 7 -
  • -
  • -
    - - google-maps -
    - 4 -
  • -
  • -
    - - explorer-mcp -
    - 2 -
  • -
  • -
    - - template-google-adk-api -
    - 4 -
  • -
  • -
    - - linear-demo -
    - 2 -
  • -
  • -
    - - cerebras-sandbox -
    - 1 -
  • -
  • -
    - - sandbox-openai -
    - 2 -
  • -
-
- - - -
-
-

What's new

- - Full change log - - -
-

Stay up to date with our latest feature and improvements

- -
    -
  • -
    -

    New framework supported: PydanticAI

    -

    Added support for PydanticAI framework

    -
    - 2025-04-12 -
  • -
  • -
    -

    New framework supported: Google ADK

    -

    Added support for Google ADK (Agent Development Kit) framework

    -
    - 2025-04-07 -
  • -
  • -
    -

    Improved Analytics Dashboard

    -

    Enhanced real-time monitoring with faster data refresh

    -
    - 2025-04-15 -
  • -
-
- - -
-

Recent requests (10)

- -
    -
  • - -
    -
    - linear-demo - in 21 hours -
    -
    - - Success -
    -
    -
  • -
  • - -
    -
    - myagent - in 21 hours -
    -
    - - Success -
    -
    -
  • -
  • - -
    -
    - linear-demo - in 21 hours -
    -
    - - Success -
    -
    -
  • -
  • - -
    -
    - gpt-40 - in 21 hours -
    -
    - - Success -
    -
    -
  • -
  • - -
    -
    - linear-demo - in 21 hours -
    -
    - - Success -
    -
    -
  • -
-
-
-
- - \ No newline at end of file diff --git a/docs/graph.html b/docs/graph.html deleted file mode 100644 index e3c08a8..0000000 --- a/docs/graph.html +++ /dev/null @@ -1,909 +0,0 @@ - - - - - - - 思维本体元模型 — 知识图谱 - - - - - - -
-
- 🧠 -
-

思维本体元模型 — 知识图谱

-
Thinking Ontology Meta-Model · ECharts Force-Directed Graph
-
-
-
- - - - -
-
- -
-
-
-
节点类型图例
-
-
- 语义对象 - -
-
-
- 对象行为 - -
-
-
- 约束规则 - -
-
-
- 编排流程 - -
-
-
-
场景联动筛选
-
- -
-
-
关系类型
-
-
语义对象关系 -
-
-
行为操作关系 -
-
-
-
规则引用关系 -
-
-
流程调用关系 -
-
-
⭐ 核心关系 -
-
-
-
-
-
节点
-
-
- -
关系
-
-
-
- -
-
-
🖱 拖拽节点 · 滚轮缩放 · 点击查看详情 · 双击流程触发场景
-
-
- 🎬 - 问题分析与解决 — 动态模拟 - - 0 / 14 -
-
-
-
-
-
-
点击「下一步」开始模拟
-
逐步展示问题分析与解决的完整调用链路。
-
-
- - - - -
-
-
-
- -
-
-
🔍
-
点击图谱中任意节点
查看详细元数据信息
-
- -
-
- - - - - \ No newline at end of file diff --git a/docs/memory.html b/docs/memory.html deleted file mode 100644 index 6563936..0000000 --- a/docs/memory.html +++ /dev/null @@ -1,304 +0,0 @@ - - - - - \ No newline at end of file diff --git a/docs/plan.html b/docs/plan.html deleted file mode 100644 index ae1422e..0000000 --- a/docs/plan.html +++ /dev/null @@ -1,212 +0,0 @@ - - - - - - 计划任务管理 - - - - - -
- -
- default - - - 运行中 - - 网页访问 - 远程地址 - 1 端点 -
- - -
- - - - -
- 计划任务 已启用 - -
-
-
- - -
- -
- -
-

计划任务

-
- - - -
-
- - -
-
- - -
-
- - - - -
-
-
- - -
- -
-
-
- - 活人感心跳 - 系统任务 - Agent 任务 - 间隔重复 -
-
- - -
-
-
- 状态: 已调度 - 触发方式: 间隔重复 30 分钟 - 下次执行: 2026/03/10 16:26 - 上次执行: 2026/03/10 15:56 - 通知通道: - - 执行次数: 13 -
-
- 检查是否需要发送主动消息 (问候/提醒/跟进) -
-
- - -
-
-
- - 记忆整理 - 系统任务 - Agent 任务 - 间隔重复 -
-
- - -
-
-
- 状态: 已调度 - 触发方式: 间隔重复 3 小时 - 下次执行: 2026/03/10 18:35 - 上次执行: 2026/03/10 15:35 - 通知通道: - - 执行次数: 2 -
-
- 执行记忆整理: 整理对话历史, 提取精华记忆, 刷新 MEMORY.md -
-
- - -
-
-
- - 系统自检 - 系统任务 - Agent 任务 - 每天 -
-
- - -
-
-
- 状态: 已调度 - 触发方式: 每天 04:00 - 下次执行: 2026/03/11 04:00 - 上次执行: 从未 - 通知通道: - - 执行次数: 0 -
-
- 执行系统自检: 分析 ERROR 日志, 尝试修复工具问题, 生成报告 -
-
-
-
- - \ No newline at end of file diff --git a/multi_agent_plan/group_chat_implementation_plan.md b/multi_agent_plan/group_chat_implementation_plan.md deleted file mode 100644 index 75c3b8a..0000000 --- a/multi_agent_plan/group_chat_implementation_plan.md +++ /dev/null @@ -1,874 +0,0 @@ -# 多智能体群聊系统实现计划 - -## 项目概述 - -实现类似"一人公司"的多智能体群聊系统,支持多个 Agent 在群聊中讨论问题,类似于人类的团队会议。 - -### 核心特性 -- **三阶段流程**: 观点提出 → 讨论完善 → CEO 总结决策 -- **智能轮数**: AI 判断讨论是否充分,自动决定轮数 -- **用户插话**: 用户可以随时打断发表意见 -- **角色扮演**: 可配置不同角色的 Agent(CEO、CTO、Designer 等) -- **复用架构**: 复用现有的 LLM、ToolRegistry、SessionManager - ---- - -## 一、系统架构 - -### 1.1 整体架构图 - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ Agent Group Chat System │ -│ ┌─────────────────────────────────────────────────────────────┐│ -│ │ GroupChatManager ││ -│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││ -│ │ │ Presenter │ │ Discusser │ │ Summarizer │ ││ -│ │ │ Controller │ │ Controller │ │ Controller │ ││ -│ │ └─────────────┘ └─────────────┘ └─────────────┘ ││ -│ │ │ │ │ ││ -│ │ └────────────────┴────────────────┘ ││ -│ │ │ ││ -│ │ SmartRoundController ││ -│ └─────────────────────────────────────────────────────────────┘│ -│ │ │ -│ ┌──────────────────┼──────────────────┐ │ -│ ▼ ▼ ▼ │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ -│ │ CEO Agent │ │ CTO Agent │ │Designer Agent│ │ -│ │ Participant │ │ Participant │ │ Participant │ │ -│ └─────────────┘ └─────────────┘ └─────────────┘ │ -│ │ │ │ │ -│ └──────────────────┴──────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌─────────────┐ │ -│ │GroupContext │ │ -│ │(共享上下文) │ │ -│ └─────────────┘ │ -└─────────────────────────────────────────────────────────────────┘ -``` - -### 1.2 核心组件 - -| 组件 | 职责 | 文件位置 | -|------|------|----------| -| **GroupChatManager** | 群聊管理器,控制整体流程 | `group_chat/manager.py` | -| **Participant** | 参与群聊的 Agent 实例 | `group_chat/participant.py` | -| **StageController** | 阶段控制器,管理各阶段 | `group_chat/stages/controller.py` | -| **PresenterStage** | 观点提出阶段 | `group_chat/stages/presenter.py` | -| **DiscusserStage** | 讨论完善阶段 | `group_chat/stages/discusser.py` | -| **SummarizerStage** | 总结决策阶段 | `group_chat/stages/summarizer.py` | -| **SmartRoundController** | 智能轮数控制 | `group_chat/round_controller.py` | -| **GroupContext** | 共享讨论上下文 | `group_chat/context.py` | -| **GroupMessage** | 群聊消息 | `group_chat/message.py` | - ---- - -## 二、数据结构设计 - -### 2.1 消息定义 - -```python -# group_chat/message.py -from typing import Optional -from pydantic import BaseModel, Field -from datetime import datetime -from enum import Enum - - -class MessageStage(str, Enum): - """消息所属阶段""" - PRESENT = "present" # 观点提出 - DISCUSS = "discuss" # 讨论完善 - SUMMARIZE = "summarize" # 总结决策 - - -class GroupMessage(BaseModel): - """群聊消息""" - id: str = Field(..., description="消息唯一标识") - agent_id: str = Field(..., description="Agent ID") - agent_name: str = Field(..., description="Agent 名称") - agent_role: str = Field(..., description="Agent 角色") - content: str = Field(..., description="消息内容") - timestamp: datetime = Field(default_factory=datetime.now) - stage: MessageStage = Field(..., description="所属阶段") - round: int = Field(default=1, description="轮数") - replying_to: Optional[str] = Field(default=None, description="回复的消息ID") - - -class UserInterruption(BaseModel): - """用户插话""" - id: str - content: str - timestamp: datetime = Field(default_factory=datetime.now) - stage: MessageStage - round: int -``` - -### 2.2 共享上下文 - -```python -# group_chat/context.py -from typing import Optional -from pydantic import BaseModel, Field -from .message import GroupMessage, UserInterruption - - -class GroupContext(BaseModel): - """群聊共享上下文""" - topic: str = Field(..., description="讨论主题") - stage: str = Field(default="present", description="当前阶段") - round: int = Field(default=1, description="当前轮数") - messages: list[GroupMessage] = Field(default_factory=list) - user_interruptions: list[UserInterruption] = Field(default_factory=list) - final_decision: Optional[str] = Field(default=None, description="最终决策") - status: str = Field(default="running", description="running/completed/failed") - - -class GroupState(BaseModel): - """群聊状态""" - context: GroupContext - participants: dict[str, dict] # {agent_id: config} - config: dict # 群聊配置 -``` - ---- - -## 三、核心实现 - -### 3.1 Agent 角色定义 - -```python -# group_chat/roles.py -from typing import Optional - -# 默认角色配置 -DEFAULT_ROLES = { - "ceo": { - "id": "ceo", - "name": "CEO", - "role": "首席执行官", - "system_prompt": """你是一家公司的 CEO,负责制定公司战略方向和重大决策。 -你的特点是:高瞻远瞩、战略思维、注重长远利益。 -在讨论中,你应该: -- 从公司整体战略角度分析问题 -- 权衡短期和长期利益 -- 做最终决策并承担责任 -- 善于总结和归纳各方观点""", - "stages": ["present", "summarize"], - "is_final_decider": True, - "priority": 1 - }, - "cto": { - "id": "cto", - "name": "CTO", - "role": "首席技术官", - "system_prompt": """你是一家公司的 CTO,负责技术决策和技术团队管理。 -你的特点是:技术深厚、注重可行性、关注技术趋势。 -在讨论中,你应该: -- 从技术角度分析方案的可行性和风险 -- 提供技术实现建议 -- 评估技术选型 -- 关注系统的可扩展性和稳定性""", - "stages": ["present", "discuss"], - "is_final_decider": False, - "priority": 2 - }, - "designer": { - "id": "designer", - "name": "Designer", - "role": "产品设计师", - "system_prompt": """你是公司的产品设计师,负责用户体验和界面设计。 -你的特点是:创意丰富、注重用户体验、审美在线。 -在讨论中,你应该: -- 从用户角度分析问题 -- 提出用户体验优化建议 -- 关注产品细节 -- 平衡美观和实用性""", - "stages": ["present", "discuss"], - "is_final_decider": False, - "priority": 3 - }, - "analyst": { - "id": "analyst", - "name": "Analyst", - "role": "数据分析师", - "system_prompt": """你是公司的数据分析师,负责数据分析和决策支持。 -你的特点是:数据敏感、逻辑严谨、注重证据。 -在讨论中,你应该: -- 用数据支撑观点 -- 提供数据分析结果 -- 指出数据驱动的机会和风险 -- 关注关键指标""", - "stages": ["present", "discuss"], - "is_final_decider": False, - "priority": 4 - } -} -``` - -### 3.2 Participant(参与者 Agent) - -```python -# group_chat/participant.py -import uuid -from datetime import datetime -from typing import Optional -from langchain_core.language_models import BaseChatModel -from langchain_core.messages import HumanMessage, SystemMessage - -from .message import GroupMessage, MessageStage -from .context import GroupContext - - -class Participant: - """参与群聊的 Agent""" - - def __init__( - self, - llm: BaseChatModel, - config: dict, - stage: str = "present" - ): - self.llm = llm - self.config = config - self.id = config["id"] - self.name = config["name"] - self.role = config["role"] - self.system_prompt = config["system_prompt"] - self.stages = config.get("stages", ["present", "discuss", "summarize"]) - self.is_final_decider = config.get("is_final_decider", False) - - async def generate_message( - self, - context: GroupContext, - stage: MessageStage, - round_num: int, - replying_to: Optional[str] = None - ) -> GroupMessage: - """生成消息""" - - # 构建 prompt - prompt = self._build_prompt(context, stage, round_num) - - # 调用 LLM - response = await self.llm.ainvoke([ - SystemMessage(content=prompt), - HumanMessage(content=f"请就「{context.topic}」发表你的观点。") - ]) - - content = response.content if hasattr(response, 'content') else str(response) - - # 创建消息 - message = GroupMessage( - id=str(uuid.uuid4()), - agent_id=self.id, - agent_name=self.name, - agent_role=self.role, - content=content, - timestamp=datetime.now(), - stage=stage, - round=round_num, - replying_to=replying_to - ) - - return message - - def _build_prompt(self, context: GroupContext, stage: MessageStage, round_num: int) -> str: - """构建 prompt""" - - base_prompt = self.system_prompt - - # 添加上下文 - context_info = f""" -## 当前讨论 -主题:{context.topic} -阶段:{stage.value} -轮数:{round_num} - -## 历史消息 -""" - - # 添加历史消息(限制数量) - recent_messages = context.messages[-10:] if context.messages else [] - for msg in recent_messages: - context_info += f"\n【{msg.agent_name}】{msg.content}\n" - - # 添加用户插话 - if context.user_interruptions: - context_info += "\n## 用户插话\n" - for interruption in context.user_interruptions[-3:]: - context_info += f"\n【用户】{interruption.content}\n" - - # 阶段特定的指令 - stage_instruction = { - "present": "请简洁地提出你的观点和建议。", - "discuss": "请回应其他人的观点,进行讨论和完善。", - "summarize": "请总结各方观点,给出最终决策建议。" - } - - full_prompt = f"{base_prompt}\n\n{context_info}\n\n{stage_instruction.get(stage.value, '')}" - - return full_prompt - - def can_participate(self, stage: MessageStage) -> bool: - """判断是否可以参与当前阶段""" - return stage.value in self.stages -``` - -### 3.3 智能轮数控制器 - -```python -# group_chat/round_controller.py -from langchain_core.language_models import BaseChatModel -from langchain_core.messages import SystemMessage, HumanMessage - -from .context import GroupContext -from .message import MessageStage - - -class SmartRoundController: - """智能轮数控制器""" - - def __init__(self, llm: BaseChatModel, max_rounds: int = 3): - self.llm = llm - self.max_rounds = max_rounds - - async def should_continue( - self, - context: GroupContext, - stage: MessageStage - ) -> tuple[bool, str]: - """ - 判断是否继续下一轮 - - Returns: - (是否继续, 原因) - """ - - # 达到最大轮数 - if context.round >= self.max_rounds: - return False, "max_rounds_reached" - - # 构建判断 prompt - prompt = self._build_judge_prompt(context, stage) - - # 调用 LLM 判断 - response = await self.llm.ainvoke([ - SystemMessage(content=prompt), - HumanMessage(content="请判断讨论是否已经充分,是否需要更多轮数。") - ]) - - content = response.content.lower() if hasattr(response, 'content') else str(response) - - # 解析判断结果 - if "充分" in content or "足够" in content or "不需要" in content: - return False, "discussion_sufficient" - elif "不充分" in content or "不够" in content or "需要" in content: - return True, "need_more_discussion" - - # 默认继续 - return True, "default_continue" - - def _build_judge_prompt(self, context: GroupContext, stage: MessageStage) -> str: - """构建判断 prompt""" - - messages_summary = "\n".join([ - f"【{msg.agent_name}】{msg.content[:200]}..." - for msg in context.messages[-5:] - ]) - - return f"""你是一个讨论质量评估专家。请判断当前的讨论是否已经充分。 - -## 讨论信息 -主题:{context.topic} -当前阶段:{stage.value} -当前轮数:{context.round} -最大轮数:{self.max_rounds} - -## 最近的讨论内容 -{messages_summary} - -## 判断标准 -- 各方观点是否已经充分表达? -- 是否有建设性的讨论和回应? -- 是否已经形成明确的结论或方向? - -## 请输出 -如果讨论已经充分,请输出"充分",并简要说明原因。 -如果还需要更多讨论,请输出"不充分",并说明需要讨论哪些方面。 -""" -``` - -### 3.4 群聊管理器 - -```python -# group_chat/manager.py -import uuid -from typing import Optional -from datetime import datetime - -from langchain_core.language_models import BaseChatModel - -from .context import GroupContext -from .message import GroupMessage, MessageStage, UserInterruption -from .participant import Participant -from .roles import DEFAULT_ROLES -from .round_controller import SmartRoundController - - -class GroupChatManager: - """群聊管理器""" - - def __init__( - self, - llm: BaseChatModel, - roles: dict = None, - max_rounds: int = 3, - enable_user_interrupt: bool = True - ): - self.llm = llm - self.roles = roles or DEFAULT_ROLES - self.max_rounds = max_rounds - self.enable_user_interrupt = enable_user_interrupt - - # 初始化组件 - self.round_controller = SmartRoundController(llm, max_rounds) - - # 运行时状态 - self.context: Optional[GroupContext] = None - self.participants: dict[str, Participant] = {} - - async def start_chat(self, topic: str) -> dict: - """开始群聊""" - - # 创建上下文 - self.context = GroupContext( - topic=topic, - stage="present", - round=1, - messages=[], - user_interruptions=[], - status="running" - ) - - # 创建参与者 - self.participants = { - role_id: Participant(self.llm, config) - for role_id, config in self.roles.items() - } - - # 按优先级排序参与者 - sorted_participants = sorted( - self.participants.values(), - key=lambda p: p.config.get("priority", 999) - ) - - # 开始第一阶段 - result = await self._run_stage(MessageStage.PRESENT, sorted_participants) - - return result - - async def _run_stage( - self, - stage: MessageStage, - participants: list[Participant] - ) -> dict: - """运行指定阶段""" - - # 更新上下文 - self.context.stage = stage.value - - # 按阶段获取参与者 - stage_participants = [p for p in participants if p.can_participate(stage)] - - # 执行多轮 - for round_num in range(1, self.max_rounds + 1): - self.context.round = round_num - - # 当前阶段参与者发言 - messages = await self._run_round(stage, stage_participants, round_num) - - # 智能判断是否继续 - should_continue, reason = await self.round_controller.should_continue( - self.context, stage - ) - - if not should_continue: - break - - # 阶段完成后的处理 - if stage == MessageStage.PRESENT: - # 进入讨论阶段 - if any(p.can_participate(MessageStage.DISCUSS) for p in participants): - return await self._run_stage(MessageStage.DISCUSS, participants) - - elif stage == MessageStage.DISCUSS: - # 进入总结阶段 - summarizer = next( - (p for p in participants if p.is_final_decider), - participants[0] - ) - return await self._run_stage(MessageStage.SUMMARIZE, [summarizer]) - - elif stage == MessageStage.SUMMARIZE: - # 完成 - self.context.status = "completed" - - return self._build_result() - - async def _run_round( - self, - stage: MessageStage, - participants: list[Participant], - round_num: int - ) -> list[GroupMessage]: - """运行一轮发言""" - - messages = [] - - for participant in participants: - # 获取前一轮的最新消息(用于回复) - replying_to = None - if self.context.messages: - last_message = self.context.messages[-1] - if last_message.agent_id != participant.id: - replying_to = last_message.id - - # 生成消息 - message = await participant.generate_message( - context=self.context, - stage=stage, - round_num=round_num, - replying_to=replying_to - ) - - # 保存消息 - self.context.messages.append(message) - messages.append(message) - - return messages - - async def add_interruption(self, content: str) -> dict: - """添加用户插话""" - - if not self.enable_user_interrupt: - return {"error": "用户插话已禁用"} - - interruption = UserInterruption( - id=str(uuid.uuid4()), - content=content, - timestamp=datetime.now(), - stage=MessageStage(self.context.stage), - round=self.context.round - ) - - self.context.user_interruptions.append(interruption) - - return {"success": True, "interruption_id": interruption.id} - - def get_messages(self) -> list[GroupMessage]: - """获取所有消息""" - return self.context.messages if self.context else [] - - def get_result(self) -> dict: - """获取结果""" - return self._build_result() - - def _build_result(self) -> dict: - """构建结果""" - return { - "topic": self.context.topic, - "status": self.context.status, - "messages": [ - { - "agent_name": m.agent_name, - "agent_role": m.agent_role, - "content": m.content, - "stage": m.stage.value, - "round": m.round - } - for m in self.context.messages - ], - "final_decision": self.context.final_decision, - "user_interruptions": [ - {"content": i.content, "timestamp": i.timestamp.isoformat()} - for i in self.context.user_interruptions - ] - } -``` - ---- - -## 四、阶段实现 - -### 4.1 Presenter Stage(观点提出) - -```python -# group_chat/stages/presenter.py -from typing import list -from ..participant import Participant -from ..message import GroupMessage - - -class PresenterStage: - """观点提出阶段""" - - async def execute( - self, - participants: list[Participant], - context - ) -> list[GroupMessage]: - """执行观点提出""" - - messages = [] - - # 按优先级顺序发言 - for participant in participants: - if not participant.can_participate("present"): - continue - - message = await participant.generate_message( - context=context, - stage="present", - round=context.round - ) - - messages.append(message) - context.messages.append(message) - - return messages -``` - -### 4.2 Discusser Stage(讨论完善) - -```python -# group_chat/stages/discusser.py -from ..participant import Participant -from ..message import GroupMessage - - -class DiscusserStage: - """讨论完善阶段""" - - async def execute( - self, - participants: list[Participant], - context - ) -> list[GroupMessage]: - """执行讨论完善""" - - messages = [] - - # 获取上一轮的消息 - last_round_messages = [ - m for m in context.messages - if m.stage == "present" and m.round == context.round - 1 - ] - - for participant in participants: - if not participant.can_participate("discuss"): - continue - - # 选择要回复的消息 - replying_to = None - for msg in reversed(last_round_messages): - if msg.agent_id != participant.id: - replying_to = msg.id - break - - message = await participant.generate_message( - context=context, - stage="discuss", - round=context.round, - replying_to=replying_to - ) - - messages.append(message) - context.messages.append(message) - - return messages -``` - -### 4.3 Summarizer Stage(总结决策) - -```python -# group_chat/stages/summarizer.py -from ..participant import Participant -from ..message import GroupMessage - - -class SummarizerStage: - """总结决策阶段""" - - async def execute( - self, - participants: list[Participant], - context - ) -> GroupMessage: - """执行总结决策""" - - # CEO 总结 - summarizer = next( - (p for p in participants if p.is_final_decider), - participants[0] - ) - - message = await summarizer.generate_message( - context=context, - stage="summarize", - round=context.round - ) - - # 保存最终决策 - context.final_decision = message.content - context.messages.append(message) - - return message -``` - ---- - -## 五、与现有系统集成 - -### 5.1 复用现有组件 - -```python -# group_chat/integration.py -from typing import Optional -from app.llm.factory import LLMFactory -from app.agent.tools.registry import ToolRegistry -from app.agent.memory.session import SessionManager - -from .manager import GroupChatManager - - -class GroupChatSystem: - """群聊系统 - 集成现有组件""" - - def __init__( - self, - llm_provider: str = "openai", - openai_api_key: Optional[str] = None, - anthropic_api_key: Optional[str] = None, - roles: dict = None, - max_rounds: int = 3, - enable_user_interrupt: bool = True - ): - # 初始化 LLM Factory - self.llm_factory = LLMFactory( - provider=llm_provider, - openai_api_key=openai_api_key, - anthropic_api_key=anthropic_api_key - ) - - # 初始化 Tool Registry - self.tool_registry = ToolRegistry() - - # 初始化 Session Manager - self.session_manager = SessionManager() - - # 配置 - self.roles = roles - self.max_rounds = max_rounds - self.enable_user_interrupt = enable_user_interrupt - - async def start_group_chat( - self, - topic: str, - session_id: str = None - ) -> dict: - """开始群聊""" - - # 获取 LLM - llm = self.llm_factory.get_llm() - - # 创建群聊管理器 - manager = GroupChatManager( - llm=llm, - roles=self.roles, - max_rounds=self.max_rounds, - enable_user_interrupt=self.enable_user_interrupt - ) - - # 开始群聊 - result = await manager.start_chat(topic) - - # 保存到 session - if session_id: - self.session_manager.add_message(session_id, "user", topic) - self.session_manager.add_message( - session_id, - "assistant", - result.get("final_decision", str(result)) - ) - - return result - - async def add_message( - self, - message: str, - session_id: str - ) -> dict: - """添加用户消息(插话)""" - - # 获取 session 中的 manager - # ... 实现获取逻辑 - - return manager.add_interruption(message) -``` - ---- - -## 六、文件结构 - -``` -agent/app/agent/multi/ -├── group_chat/ -│ ├── __init__.py -│ ├── roles.py # Agent 角色定义 -│ ├── message.py # 消息类型 -│ ├── context.py # 共享上下文 -│ ├── participant.py # 参与者 Agent -│ ├── manager.py # 群聊管理器 -│ ├── round_controller.py # 智能轮数控制器 -│ ├── stages/ -│ │ ├── __init__.py -│ │ ├── controller.py # 阶段控制器 -│ │ ├── presenter.py # 观点提出阶段 -│ │ ├── discusser.py # 讨论完善阶段 -│ │ └── summarizer.py # 总结决策阶段 -│ └── integration.py # 与现有系统集成 -``` - ---- - -## 七、实现顺序 - -1. **Phase 1: 基础架构** - - 定义数据类型 (message.py, context.py) - - 创建角色配置 (roles.py) - -2. **Phase 2: 核心组件** - - 实现 Participant (participant.py) - - 实现 SmartRoundController (round_controller.py) - -3. **Phase 3: 阶段实现** - - 实现 PresenterStage - - 实现 DiscusserStage - - 实现 SummarizerStage - -4. **Phase 4: 集成** - - 实现 GroupChatManager - - 与现有系统集成 - ---- - -## 八、测试计划 - -1. **单元测试**: 测试各 Participant 的消息生成 -2. **集成测试**: 测试完整的群聊流程 -3. **轮数控制测试**: 测试智能轮数判断 -4. **用户插话测试**: 测试插话机制 -5. **端到端测试**: 模拟真实群聊场景 diff --git a/multi_agent_plan/group_chat_notes.md b/multi_agent_plan/group_chat_notes.md deleted file mode 100644 index 1943954..0000000 --- a/multi_agent_plan/group_chat_notes.md +++ /dev/null @@ -1,80 +0,0 @@ -# Notes: 多智能体群聊系统研究 - -## 核心概念 - -### 群聊系统 vs 之前的 Supervisor 系统 - -| 特性 | Supervisor 系统 | 群聊系统 | -|------|----------------|----------| -| 流程 | 线性:规划 → 执行 → 汇总 | 多阶段循环 | -| Agent 关系 | 层级:Supervisor 管理 Workers | 平等协作 | -| 通信方式 | 单向:任务分发 | 多向:互相讨论 | -| 决策方式 | Supervisor 决定 | CEO 最终决策 | -| 用户参与 | 旁观 | 可插话 | - -### 设计模式 - -#### 1. 流水线模式 -``` -Stage 1 (Presenter) → Stage 2 (Discusser) → Stage 3 (Summarizer) -``` - -#### 2. 消息传递 -- 每个 Stage 维护一个消息队列 -- Agent 的输出成为下一个 Agent 的输入 -- 使用 Shared Context 存储共享状态 - -#### 3. 智能轮数 -```python -class SmartRoundController: - def should_continue(self, stage, round_num, messages): - # 使用 LLM 判断是否继续 - prompt = f""" - 当前阶段: {stage} - 当前轮数: {round_num} - 讨论内容: {messages} - - 讨论是否已经充分?是否需要更多轮数? - """ - return llm.judge(prompt) -``` - -## 复用现有架构 - -### 可复用的组件 -1. **LLM Factory** - 语言模型 -2. **Tool Registry** - 工具注册 -3. **Session Manager** - 会话管理 -4. **Agent Executor** - Agent 执行逻辑(部分) - -### 需要新增的组件 -1. **GroupChatManager** - 群聊管理器 -2. **Participant** - 参与者 Agent -3. **Stage Controller** - 阶段控制器 -4. **SmartRoundController** - 智能轮数控制器 - -## 关键数据结构 - -### GroupMessage -```python -class GroupMessage(BaseModel): - id: str - agent_id: str - agent_name: str - content: str - timestamp: datetime - stage: str # presenter/discusser/summarizer - round: int - replying_to: Optional[str] # 回复的消息 ID -``` - -### GroupContext -```python -class GroupContext(BaseModel): - topic: str # 讨论主题 - stage: str # 当前阶段 - round: int # 当前轮数 - messages: list[GroupMessage] # 所有消息 - user_interruptions: list[str] # 用户插话 - final_decision: Optional[str] # 最终决策 -``` diff --git a/multi_agent_plan/group_chat_task_plan.md b/multi_agent_plan/group_chat_task_plan.md deleted file mode 100644 index cac821b..0000000 --- a/multi_agent_plan/group_chat_task_plan.md +++ /dev/null @@ -1,32 +0,0 @@ -# Task Plan: 多智能体群聊系统实现计划 - -## Goal -实现类似"一人公司"的多智能体群聊系统,支持头脑风暴、任务协作、角色扮演等多模式讨论。 - -## Phases -- [x] Phase 1: 基础架构设计和核心组件规划 -- [ ] Phase 2: 群聊管理器 (GroupChatManager) 实现 -- [ ] Phase 3: 参与 Agent (Participant) 实现 -- [ ] Phase 4: 三个阶段实现 (Presenter/Discusser/Summarizer) -- [ ] Phase 5: 智能轮数控制实现 -- [ ] Phase 6: 用户插话机制实现 -- [ ] Phase 7: 与现有系统集成和 API 接口 - -## Key Questions -1. 如何复用现有的 Supervisor + Workers 架构? -2. 如何实现智能轮数控制? -3. 如何处理用户插话? - -## Decisions Made -- 架构:任务流水线模式(观点提出 → 讨论完善 → 总结决策) -- 决策机制:CEO Agent 最终决策 -- 轮数控制:AI 智能判断 -- 用户参与:插话模式 -- 复用策略:复用现有 LLM、ToolRegistry、SessionManager - -## Status -**Currently in Phase 1** - 系统架构设计和核心组件规划已完成 - -## 实现计划文件 -- `group_chat_implementation_plan.md` - 详细实现计划 -- `group_chat_notes.md` - 研究笔记 diff --git a/multi_agent_plan/implementation_plan.md b/multi_agent_plan/implementation_plan.md deleted file mode 100644 index 94899ec..0000000 --- a/multi_agent_plan/implementation_plan.md +++ /dev/null @@ -1,709 +0,0 @@ -# 多智能体联动系统实现计划 - -## 项目概述 - -基于 LangGraph 实现类似 OpenClaw 的多智能体协作系统,采用 Supervisor + Workers 层级架构。 - -### 核心特性 -- **任务规划**: Supervisor 分析任务并生成执行计划 -- **动态分发**: LLM 自主决策调用哪个 Worker -- **并行执行**: 支持多个 Worker 同时处理任务 -- **结果汇总**: Supervisor 汇总所有 Worker 结果 -- **迭代优化**: 支持 Review 机制和迭代重试 - ---- - -## 一、系统架构 - -### 1.1 整体架构图 - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ MultiAgentSystem │ -│ ┌───────────────────────────────────────────────────────────┐ │ -│ │ Supervisor Agent │ │ -│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ -│ │ │ Planner │ │ Dispatcher │ │ Aggregator │ │ │ -│ │ │ (任务规划) │ │ (任务分发) │ │ (结果汇总) │ │ │ -│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ -│ └───────────────────────────────────────────────────────────┘ │ -│ │ │ -│ ┌──────────────────┼──────────────────┐ │ -│ ▼ ▼ ▼ │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ -│ │ Research │ │ Coder │ │ Review │ │ -│ │ Worker │ │ Worker │ │ Worker │ │ -│ └─────────────┘ └─────────────┘ └─────────────┘ │ -│ │ │ │ │ -│ └──────────────────┴──────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌─────────────┐ │ -│ │ Shared State │ │ -│ │ (共享状态) │ │ -│ └─────────────┘ │ -└─────────────────────────────────────────────────────────────────┘ -``` - -### 1.2 核心组件 - -| 组件 | 职责 | 文件位置 | -|------|------|----------| -| **SupervisorAgent** | 任务分析、规划、分发、汇总 | `agent/multi/supervisor.py` | -| **BaseWorker** | Worker 基类,定义执行接口 | `agent/multi/workers/base.py` | -| **ResearchWorker** | 信息搜索和调研 | `agent/multi/workers/research.py` | -| **CoderWorker** | 代码编写和修改 | `agent/multi/workers/coder.py` | -| **ReviewWorker** | 结果检查和评审 | `agent/multi/workers/review.py` | -| **SharedState** | 跨 Agent 共享状态 | `agent/multi/state.py` | -| **TaskQueue** | 任务队列管理 | `agent/multi/queue.py` | -| **MultiAgentGraph** | LangGraph 流程编排 | `agent/multi/graph.py` | - ---- - -## 二、数据结构设计 - -### 2.1 Agent State 定义 - -```python -# agent/multi/types.py -from typing import TypedDict, Annotated, Optional -from operator import add -from pydantic import BaseModel - - -class TaskItem(BaseModel): - """单个任务项""" - id: str - description: str - assigned_agent: str # research / coder / review - status: str # pending / running / completed / failed - result: Optional[dict] = None - error: Optional[str] = None - retry_count: int = 0 - - -class AgentState(TypedDict): - """贯穿整个图的 Agent 状态""" - # 用户输入 - original_task: str # 原始任务描述 - - # 任务规划 - task_plan: list[TaskItem] # 分解后的任务列表 - current_task_index: int # 当前执行的任务索引 - - # 执行结果 - results: dict # {task_id: result} - - # 流程控制 - iteration: int # 当前迭代次数 - next_node: str # 下一个节点名称 - - # 共享上下文 - shared_context: dict # Agent 间共享的数据 - - # 最终输出 - final_output: str - status: str # running / completed / failed -``` - -### 2.2 Supervisor 输出结构 - -```python -# Supervisor 的结构化输出 -class SupervisorDecision(BaseModel): - """Supervisor 的决策""" - analysis: str # 任务分析 - task_plan: list[TaskItem] # 任务计划 - need_aggregation: bool # 是否需要汇总 - next_worker: str # 下一个执行的 Worker -``` - ---- - -## 三、核心实现 - -### 3.1 Supervisor Agent - -```python -# agent/multi/supervisor.py -from langchain_core.language_models import BaseChatModel -from langchain_core.output_parsers import PydanticOutputParser -from pydantic import BaseModel -from typing import Type - -from .types import AgentState, TaskItem, SupervisorDecision -from .prompts import SUPERVISOR_SYSTEM_PROMPT - - -class SupervisorAgent: - """Supervisor Agent - 负责任务规划和分发""" - - def __init__( - self, - llm: BaseChatModel, - max_iterations: int = 3 - ): - self.llm = llm - self.max_iterations = max_iterations - self.output_parser = PydanticOutputParser(pydantic_object=SupervisorDecision) - - def create_node(self): - """创建 Supervisor 节点""" - return self._supervisor_node - - async def _supervisor_node(self, state: AgentState) -> dict: - """Supervisor 节点逻辑""" - # 首次调用:分析任务并生成计划 - if not state.get("task_plan"): - decision = await self._plan_tasks(state["original_task"]) - return { - "task_plan": decision.task_plan, - "next_node": decision.next_worker, - "current_task_index": 0, - "shared_context": {"task_analysis": decision.analysis} - } - - # 检查是否需要继续 - current_task = state["task_plan"][state["current_task_index"]] - - if current_task["status"] == "completed": - # 当前任务完成,检查是否还有更多任务 - if state["current_task_index"] + 1 < len(state["task_plan"]): - next_index = state["current_task_index"] + 1 - next_task = state["task_plan"][next_index] - return { - "current_task_index": next_index, - "next_node": next_task["assigned_agent"] - } - else: - # 所有任务完成,进入汇总 - return {"next_node": "aggregate"} - - elif current_task["status"] == "failed": - # 任务失败,检查是否超过最大重试 - if current_task["retry_count"] >= self.max_iterations: - return {"next_node": "aggregate", "status": "failed"} - else: - # 重试 - return {"next_node": current_task["assigned_agent"]} - - return {"next_node": state.get("next_node", "aggregate")} - - async def _plan_tasks(self, task: str) -> SupervisorDecision: - """调用 LLM 生成任务计划""" - prompt = SUPERVISOR_SYSTEM_PROMPT.format(task=task) - - response = await self.llm.ainvoke([ - {"role": "system", "content": prompt}, - {"role": "user", "content": "请分析任务并制定执行计划。"} - ]) - - # 解析 LLM 输出为结构化决策 - # ... (实现解析逻辑) - return decision -``` - -### 3.2 Worker 基类 - -```python -# agent/multi/workers/base.py -from abc import ABC, abstractmethod -from typing import Any -from langchain_core.language_models import BaseChatModel - -from ..types import AgentState - - -class BaseWorker(ABC): - """Worker Agent 基类""" - - def __init__( - self, - llm: BaseChatModel, - name: str, - system_prompt: str, - tools: list = None - ): - self.llm = llm - self.name = name - self.system_prompt = system_prompt - self.tools = tools or [] - - @abstractmethod - async def execute(self, task: TaskItem, context: dict) -> dict: - """执行任务""" - pass - - def create_node(self): - """创建 LangGraph 节点""" - async def node(state: AgentState) -> dict: - task = state["task_plan"][state["current_task_index"]] - result = await self.execute(task, state.get("shared_context", {})) - - # 更新状态 - return { - "results": {task.id: result}, - "task_plan": self._update_task_status( - state["task_plan"], - task.id, - "completed" if result.get("success") else "failed" - ), - "shared_context": {**state.get("shared_context", {}), **result.get("context", {})} - } - - return node - - def _update_task_status(self, tasks: list, task_id: str, status: str) -> list: - """更新任务状态""" - return [ - {**task, "status": status} if task["id"] == task_id else task - for task in tasks - ] -``` - -### 3.3 任务队列(可选:支持并行执行) - -```python -# agent/multi/queue.py -import asyncio -from typing import Any, Callable -from dataclasses import dataclass -from enum import Enum - - -class TaskStatus(Enum): - PENDING = "pending" - RUNNING = "running" - COMPLETED = "completed" - FAILED = "failed" - - -@dataclass -class QueuedTask: - id: str - agent_name: str - task_data: Any - status: TaskStatus = TaskStatus.PENDING - result: Any = None - error: str = None - - -class TaskQueue: - """任务队列 - 支持并行执行多个 Worker""" - - def __init__(self, max_concurrent: int = 3): - self.max_concurrent = max_concurrent - self.queue: asyncio.Queue = asyncio.Queue() - self.results: dict = {} - self._running = 0 - - async def add_task(self, task: QueuedTask): - """添加任务到队列""" - await self.queue.put(task) - - async def execute_all(self, worker_factory: Callable): - """执行所有任务""" - async def worker(): - while True: - try: - task = self.queue.get_nowait() - except asyncio.QueueEmpty: - break - - self._running += 1 - task.status = TaskStatus.Running - - try: - worker_instance = worker_factory(task.agent_name) - task.result = await worker_instance.execute(task.task_data) - task.status = TaskStatus.COMPLETED - except Exception as e: - task.status = TaskStatus.FAILED - task.error = str(e) - finally: - self._running -= 1 - self.results[task.id] = task - - # 启动多个 worker 协程 - workers = [asyncio.create_task(worker()) for _ in range(self.max_concurrent)] - await asyncio.gather(*workers) - - return self.results -``` - -### 3.4 LangGraph 流程编排 - -```python -# agent/multi/graph.py -from langgraph.graph import StateGraph, END -from langgraph.prebuilt import ToolNode - -from .types import AgentState -from .supervisor import SupervisorAgent -from .workers.research import ResearchWorker -from .workers.coder import CoderWorker -from .workers.review import ReviewWorker -from .aggregator import ResultAggregator - - -def create_multi_agent_graph( - llm, - tool_registry, - max_iterations: int = 3 -) -> StateGraph: - """创建多 Agent 流程图""" - - # 初始化组件 - supervisor = SupervisorAgent(llm, max_iterations) - research_worker = ResearchWorker(llm, tool_registry) - coder_worker = CoderWorker(llm, tool_registry) - review_worker = ReviewWorker(llm, tool_registry) - aggregator = ResultAggregator(llm) - - # 创建图 - graph = StateGraph(AgentState) - - # 添加节点 - graph.add_node("supervisor", supervisor.create_node()) - graph.add_node("research", research_worker.create_node()) - graph.add_node("coder", coder_worker.create_node()) - graph.add_node("review", review_worker.create_node()) - graph.add_node("aggregate", aggregator.create_node()) - - # 设置入口 - graph.set_entry_point("supervisor") - - # 添加边 - graph.add_edge("supervisor", "research") - graph.add_edge("research", "review") - graph.add_edge("coder", "review") - - # 条件边:从 review 回到 supervisor - def should_continue(state: AgentState) -> str: - if state.get("status") == "failed": - return "aggregate" - if state.get("iteration", 0) >= max_iterations: - return "aggregate" - if state.get("current_task_index", 0) >= len(state.get("task_plan", [])): - return "aggregate" - return "supervisor" - - graph.add_conditional_edges( - "review", - should_continue, - { - "supervisor": "supervisor", - "aggregate": "aggregate" - } - ) - - # 结束节点 - graph.add_edge("aggregate", END) - - return graph.compile() -``` - ---- - -## 四、Prompt 设计 - -### 4.1 Supervisor System Prompt - -```python -# agent/multi/prompts.py - -SUPERVISOR_SYSTEM_PROMPT = """你是一个任务规划专家(Supervisor)。你的职责是将复杂任务分解为可执行的子任务,并分配给合适的执行 Agent。 - -## 可用的 Worker Agent -- **research**: 信息搜索和调研 -- **coder**: 代码编写、修改和调试 -- **review**: 结果检查、质量评审 - -## 任务 -{task} - -## 请按以下步骤执行 - -### 步骤 1: 任务分析 -分析任务的性质,确定需要哪些步骤来完成。 - -### 步骤 2: 任务分解 -将任务分解为独立的子任务。每个子任务应该: -- 描述清晰 -- 可以由单个 Agent 完成 -- 有明确的完成标准 - -### 步骤 3: 分配 Agent -为每个子任务选择最合适的执行 Agent。 - -### 步骤 4: 确定执行顺序 -如果有依赖关系,确定正确的执行顺序。 - -## 输出格式 -请以 JSON 格式输出你的决策: -```json -{{ - "analysis": "任务分析...", - "task_plan": [ - {{ - "id": "task_1", - "description": "子任务描述", - "assigned_agent": "research" - }}, - {{ - "id": "task_2", - "description": "子任务描述", - "assigned_agent": "coder" - }} - ], - "need_aggregation": true, - "next_worker": "research" -}} -``` - -## 注意 -- 如果任务很简单,可以只分配给一个 Agent -- 如果任务需要迭代优化,确保有 review 环节 -- 考虑任务之间的依赖关系 -""" -``` - -### 4.2 Review Worker Prompt - -```python -REVIEW_SYSTEM_PROMPT = """你是一个代码和结果评审专家(Reviewer)。你的职责是检查任务执行结果是否符合要求。 - -## 任务描述 -{task_description} - -## 执行结果 -{execution_result} - -## 检查标准 -1. 结果是否完整解决了原始任务? -2. 输出格式是否正确? -3. 是否存在明显的错误或遗漏? -4. 代码是否有潜在问题? - -## 请输出评审结果 -```json -{{ - "passed": true/false, - "issues": [ - {{"severity": "high/medium/low", "description": "问题描述"}} - ], - "suggestions": ["改进建议"] -}} -``` -""" -``` - ---- - -## 五、迭代控制 - -### 5.1 迭代逻辑 - -```python -# agent/multi/iteration.py -from typing import Optional - - -class IterationController: - """迭代控制器""" - - def __init__(self, max_iterations: int = 3): - self.max_iterations = max_iterations - - def should_continue( - self, - iteration: int, - task_status: str, - review_result: dict - ) -> tuple[bool, str]: - """ - 判断是否继续迭代 - - Returns: - (是否继续, 原因) - """ - # 超过最大迭代次数 - if iteration >= self.max_iterations: - return False, "max_iterations_reached" - - # 任务成功完成 - if task_status == "completed" and review_result.get("passed"): - return False, "task_completed" - - # 任务失败且不可重试 - if task_status == "failed" and not review_result.get("retryable"): - return False, "task_failed" - - # 需要重试 - if review_result.get("issues") and review_result.get("passed") is False: - return True, "needs_retry" - - return True, "continue" - - def get_next_action( - self, - review_result: dict, - current_worker: str - ) -> str: - """确定下一步动作""" - if review_result.get("passed"): - return "supervisor" # 返回 Supervisor - - # 根据问题类型决定下一步 - issues = review_result.get("issues", []) - high_severity = any(i.get("severity") == "high" for i in issues) - - if high_severity: - # 严重问题,重新执行相同任务 - return current_worker - else: - # 轻微问题,可以继续 - return "supervisor" -``` - ---- - -## 六、与现有系统集成 - -### 6.1 复用现有组件 - -```python -# agent/multi/integration.py -from app.agent.core.agent import AgentManager -from app.agent.tools.registry import ToolRegistry -from app.agent.memory.session import SessionManager -from app.llm.factory import LLMFactory - - -class MultiAgentSystem: - """多智能体系统 - 集成现有组件""" - - def __init__(self, config: dict): - # 复用现有 LLM Factory - self.llm_factory = LLMFactory( - provider=config.get("llm_provider", "openai"), - openai_api_key=config.get("openai_api_key"), - anthropic_api_key=config.get("anthropic_api_key") - ) - - # 复用现有 Tool Registry - self.tool_registry = ToolRegistry() - self._register_default_tools() - - # 复用现有 Session Manager - self.session_manager = SessionManager() - - # 配置 - self.max_iterations = config.get("max_iterations", 3) - - def _register_default_tools(self): - """注册默认工具""" - # 从现有 Agent 复制工具注册逻辑 - from app.agent.tools.impl import search, calculator - self.tool_registry.register( - name="search", - func=search.search_web, - description="Search the web", - security_level="safe" - ) - # ... 其他工具 - - async def execute(self, task: str, session_id: str = None) -> dict: - """执行多 Agent 任务""" - # 创建 LangGraph - from .graph import create_multi_agent_graph - - llm = self.llm_factory.get_llm() - graph = create_multi_agent_graph( - llm=llm, - tool_registry=self.tool_registry, - max_iterations=self.max_iterations - ) - - # 初始化状态 - initial_state = { - "original_task": task, - "task_plan": [], - "current_task_index": 0, - "results": {}, - "iteration": 0, - "next_node": "supervisor", - "shared_context": {}, - "final_output": "", - "status": "running" - } - - # 执行 - result = await graph.ainvoke(initial_state) - - # 保存到 session - if session_id: - self.session_manager.add_message(session_id, "user", task) - self.session_manager.add_message(session_id, "assistant", result["final_output"]) - - return result -``` - ---- - -## 七、文件结构 - -``` -agent/ -├── __init__.py -├── multi/ -│ ├── __init__.py -│ ├── types.py # 数据类型定义 -│ ├── prompts.py # Prompt 模板 -│ ├── supervisor.py # Supervisor Agent -│ ├── graph.py # LangGraph 流程图 -│ ├── iteration.py # 迭代控制 -│ ├── integration.py # 与现有系统集成 -│ ├── queue.py # 任务队列(可选) -│ └── workers/ -│ ├── __init__.py -│ ├── base.py # Worker 基类 -│ ├── research.py # Research Worker -│ ├── coder.py # Coder Worker -│ └── review.py # Review Worker -``` - ---- - -## 八、实现顺序 - -1. **Phase 1: 基础架构** - - 定义数据类型 (types.py) - - 创建 Prompt 模板 (prompts.py) - -2. **Phase 2: Supervisor** - - 实现 SupervisorAgent - - 实现任务规划和分发逻辑 - -3. **Phase 3: Workers** - - 实现 BaseWorker - - 实现 ResearchWorker - - 实现 CoderWorker - - 实现 ReviewWorker - -4. **Phase 4: 流程编排** - - 实现 LangGraph 流程图 - - 添加条件边和迭代控制 - -5. **Phase 5: 集成** - - 与现有 Agent 系统集成 - - 添加 API 接口 - ---- - -## 九、测试计划 - -1. **单元测试**: 测试各 Worker 的执行逻辑 -2. **集成测试**: 测试完整的 Supervisor + Workers 流程 -3. **迭代测试**: 测试重试和迭代逻辑 -4. **端到端测试**: 模拟真实任务执行 diff --git a/multi_agent_plan/notes.md b/multi_agent_plan/notes.md deleted file mode 100644 index f133b9e..0000000 --- a/multi_agent_plan/notes.md +++ /dev/null @@ -1,107 +0,0 @@ -# Notes: LangGraph 多智能体研究 - -## 核心概念 - -### LangGraph 基础 -- **StateGraph**: 有向无环图(DAG),节点是 Agent/函数,边是流转逻辑 -- **State**: 贯穿整个图流动的状态对象 -- **Node**: 执行单元(可以是 Agent、函数、条件判断) -- **Edge**: 连接节点的边,支持条件边(conditional edges) - -### Supervisor + Workers 模式参考 - -#### 1. LangChain 官方 Supervisor 示例 -```python -from langgraph.prebuilt import create_react_agent -from langgraph.graph import StateGraph, END - -# 定义 Workers -research_agent = create_react_agent(llm, tools=[search]) -coder_agent = create_react_agent(llm, tools=[write_file]) - -# 定义 Supervisor 节点 -def supervisor_node(state): - # LLM 决定下一步调用哪个 Agent - response = llm.with_structured_output(SupervisorOutput).invoke( - [SystemMessage(content=SUPERVISOR_PROMPT)] + state["messages"] - ) - return {"next": response.next_agent} - -# 构建图 -graph = StateGraph(AgentState) -graph.add_node("supervisor", supervisor_node) -graph.add_node("research", research_agent) -graph.add_node("code", coder_agent) -``` - -#### 2. 状态定义 -```python -from typing import TypedDict, Annotated -import operator - -class AgentState(TypedDict): - messages: Annotated[list, operator.add] - task: str - plan: list - results: dict - iteration: int - next: str # 控制下一步流向 -``` - -#### 3. 条件边实现 -```python -def should_continue(state): - if state["iteration"] >= MAX_ITERATIONS: - return "end" - if state.get("task_complete"): - return "end" - return "continue" - -graph.add_conditional_edges( - "review", - should_continue, - { - "continue": "supervisor", - "end": END - } -) -``` - -## 设计决策 - -### 架构优势 -1. **清晰的分层**: Supervisor 负责任务规划,Workers 负责执行 -2. **可扩展**: 容易添加新的 Worker 类型 -3. **可控**: 迭代次数全局配置 -4. **灵活**: 支持条件分支和循环 - -### 需要解决的问题 -1. **Supervisor 如何做规划**: 需要设计 prompt 让 LLM 生成任务列表 -2. **任务队列**: 需要支持并行分发多个 Worker -3. **共享上下文**: 需要设计数据结构在 Agent 间共享状态 -4. **Review 机制**: 需要定义检查标准和重试逻辑 - -## 关键 Prompt 设计 - -### Supervisor System Prompt -``` -你是一个任务规划专家(Supervisor)。用户的任务是:{task} - -请按以下步骤执行: -1. 分析任务需求和约束 -2. 将任务分解为可执行的子任务 -3. 为每个子任务选择合适的执行 Agent: - - research: 信息搜索和调研 - - coder: 代码编写和修改 - - review: 结果检查和评审 -4. 确定执行顺序和依赖关系 - -当前任务进度:{progress} -共享上下文:{context} - -请输出你的决策,格式如下: -- 需要执行的子任务列表 -- 每个任务的执行 Agent -- 任务执行顺序 -- 是否需要汇总结果 -``` diff --git a/multi_agent_plan/task_plan.md b/multi_agent_plan/task_plan.md deleted file mode 100644 index d567018..0000000 --- a/multi_agent_plan/task_plan.md +++ /dev/null @@ -1,33 +0,0 @@ -# Task Plan: 多智能体联动系统实现计划 - -## Goal -基于 LangGraph 实现类似 OpenClaw 的多智能体联动系统,支持任务规划、动态分发、结果汇总和迭代优化。 - -## Phases -- [x] Phase 1: 系统架构设计和核心组件规划 -- [ ] Phase 2: Supervisor Agent 实现 -- [ ] Phase 3: Worker Agent 实现 -- [ ] Phase 4: 任务队列和共享上下文实现 -- [ ] Phase 5: State Machine 流程控制实现 -- [ ] Phase 6: 迭代控制和 Review 机制实现 -- [ ] Phase 7: 与现有 Agent 系统集成 - -## Key Questions -1. 如何用 LangGraph 实现 Supervisor + Workers 架构? -2. 如何设计任务队列支持并行执行? -3. 如何实现共享上下文在 Agent 间传递? -4. 如何控制迭代次数和流程分支? - -## Decisions Made -- 架构:Supervisor + Workers 层级模式 -- 协作方式:LLM 自主决策任务分配 -- 通信:共享内存(Shared Context) -- 迭代控制:全局最大迭代次数配置 -- Workers 定义:复用现有 tool_registry - -## Status -**Currently in Phase 1** - 系统架构设计和核心组件规划已完成 - -## 实现计划文件 -- `implementation_plan.md` - 详细的实现计划 -- `notes.md` - LangGraph 研究笔记 diff --git a/screenshots/agent管理.png b/screenshots/agent管理.png deleted file mode 100644 index d77cc89..0000000 Binary files a/screenshots/agent管理.png and /dev/null differ diff --git a/screenshots/实际弹窗高度.png b/screenshots/实际弹窗高度.png deleted file mode 100644 index aa55e6c..0000000 Binary files a/screenshots/实际弹窗高度.png and /dev/null differ diff --git a/screenshots/对话界面.png b/screenshots/对话界面.png deleted file mode 100644 index b8a01b9..0000000 Binary files a/screenshots/对话界面.png and /dev/null differ diff --git a/screenshots/文件解析失败.png b/screenshots/文件解析失败.png deleted file mode 100644 index 9f4821a..0000000 Binary files a/screenshots/文件解析失败.png and /dev/null differ diff --git a/screenshots/窗口bug.png b/screenshots/窗口bug.png deleted file mode 100644 index c21170a..0000000 Binary files a/screenshots/窗口bug.png and /dev/null differ diff --git a/screenshots/计划任务.png b/screenshots/计划任务.png deleted file mode 100644 index ff50381..0000000 Binary files a/screenshots/计划任务.png and /dev/null differ diff --git a/screenshots/记忆整理.png b/screenshots/记忆整理.png deleted file mode 100644 index 37f3091..0000000 Binary files a/screenshots/记忆整理.png and /dev/null differ diff --git a/team-require/ai/ai-core-api.md b/team-require/ai/ai-core-api.md deleted file mode 100644 index bec446c..0000000 --- a/team-require/ai/ai-core-api.md +++ /dev/null @@ -1,137 +0,0 @@ -# AI-Core 文档解析服务 API 对接文档 - -## 服务地址 - -``` -localhost:50051 -``` - -## VLM 配置(可选) - -VLM 用于提升图片文件的解析效果。如果不配置 VLM,则使用默认的 MarkItDown 解析。 - -### 方式一:环境变量 - -```bash -# 设置环境变量 -export VLM_API_KEY="your-api-key" -export VLM_PROVIDER="openai" # openai / anthropic / qwen -export VLM_MODEL="gpt-4o" -``` - -### 方式二:配置文件 - -在 `ai-core/config.yaml` 中配置: - -```yaml -vlm: - enabled: true - provider: "openai" # openai / anthropic / qwen - model: "gpt-4o" # 模型名称 - api_key: "sk-xxx" # API Key - base_url: "" # 自定义 API 地址(可选) - prompt: "" # 自定义提示词(可选) -``` - -### 支持的 VLM 提供商 - -| 提供商 | 示例模型 | -|--------|----------| -| openai | gpt-4o, gpt-4o-mini | -| anthropic | claude-3-opus, claude-3-sonnet | -| qwen | qwen-vl-max, qwen2-vl-72b | - ---- - -## gRPC API 定义 - -### 1. ParseDocument - 解析文档 - -**请求 (ParseRequest)** -```protobuf -message ParseRequest { - string file_url = 1; // 文件 URL(必填) - string file_name = 2; // 文件名,带扩展名(必填) - string file_type = 3; // 文件类型(可选,自动检测) - string parser_engine = 4; // 解析引擎(可选) - map engine_overrides = 5; // 引擎配置 - - // VLM 配置(可选,优先级高于全局配置) - VLMConfig vlm_config = 6; -} - -message VLMConfig { - bool enabled = 1; - string provider = 2; - string model = 3; - string api_key = 4; - string base_url = 5; - string prompt = 6; -} -``` - -**响应 (ParseResponse)** -```protobuf -message ParseResponse { - bool success = 1; - string content = 2; // Markdown 内容 - string message = 3; - int32 content_length = 4; - string file_type = 5; - string parser_engine = 6; -} -``` - ---- - -## Golang 对接示例 - -### 基础调用(无 VLM 配置时使用 MarkItDown) - -```go -req := &pb.ParseRequest{ - FileUrl: "https://example.com/document.pdf", - FileName: "document.pdf", -} - -resp, client.ParseDocument(ctx, req) -``` - -### 带 VLM 配置调用 - -```go -req := &pb.ParseRequest{ - FileUrl: "https://example.com/image.png", - FileName: "image.png", - VlmConfig: &pb.VLMConfig{ - Enabled: Provider: "open true, - ai", - Model: "gpt-4o", - ApiKey: "sk-xxx", - }, -} - -resp, err := client.ParseDocument(ctx, req) -``` - ---- - -## 解析逻辑 - -1. **图片文件** (jpg, png, webp 等) - - 如果配置了 VLM → 使用 VLM 解析 - - 如果没有配置 VLM → 使用 MarkItDown 解析 - -2. **PDF/DOCX/PPTX 等文档** - - 使用 MarkItDown 解析 - -3. **VLM 优先级** - - gRPC 请求中的 vlm_config > 全局配置(config.yaml/环境变量) - ---- - -## 注意事项 - -1. **文件 URL**: 必须是可直接访问的 URL -2. **文件名**: 必须带扩展名(如 `.pdf`, `.png`) -3. **返回内容**: Markdown 格式文本 diff --git a/team-require/ai/todo.md b/team-require/ai/todo.md deleted file mode 100644 index 08f7396..0000000 --- a/team-require/ai/todo.md +++ /dev/null @@ -1,20 +0,0 @@ -# AI 服务需求 TODO - -## 2026年3月 - -### 2026-03-09 - -- [ ] **AI-Core 文档解析服务对接** - - 服务:ai-core (gRPC, 端口 50051) - - 功能:将文档(PDF/DOCX/PPTX/图片等)转换为 Markdown - - 对接方式:gRPC 调用 - - 详细需求:[ai-core-api.md](./ai-core-api.md) - -- [ ] **VLM 调用支持** - - 支持 OpenAI GPT-4o、Anthropic Claude、阿里 Qwen VL - - 通过 vlm_config 配置启用 - - 适用场景:图片文件(jpg, png 等)自动使用 VLM 解析 - ---- - -> 需求完成后请完成者打 ✔ diff --git a/team-require/api/README.md b/team-require/api/README.md deleted file mode 100644 index bd76b18..0000000 --- a/team-require/api/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# API 接口文档 - -## 目录 - -### Database 相关 - -- [检查数据库连接并获取表结构](database-check.md) -- [创建数据库配置](database-create.md) -- [获取数据库列表](database-list.md) -- [获取子表列表](subtable-list.md) - -### Neo4j 相关 - -- [Neo4j 连接测试](neo4j-check.md) - ---- - -> 接口如有更新,请同步更新此文档 diff --git a/team-require/api/database-check.md b/team-require/api/database-check.md deleted file mode 100644 index 8370434..0000000 --- a/team-require/api/database-check.md +++ /dev/null @@ -1,200 +0,0 @@ -# 检查数据库连接并获取表结构 - -## 接口地址 - -``` -POST /database/check -``` - -## 请求参数 - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| db_type | string | 是 | 数据库类型:`mysql`、`postgres`、`neo4j` | -| host | string | 是 | 数据库主机 | -| port | int | 是 | 数据库端口 | -| username | string | 是 | 用户名 | -| password | string | 否 | 密码 | -| database | string | 是 | 数据库名 | -| charset | string | 否 | 字符集,默认 `utf8mb4` | -| ssl_mode | string | 否 | SSL 模式 | -| database_id | string | 否 | 已存在的数据库ID,用于恢复字段映射 | -| uri | string | 否 | Neo4j 连接地址(如 bolt://localhost:7687),Neo4j 类型必填 | - -## 请求示例(MySQL/PostgreSQL) - -```json -{ - "db_type": "mysql", - "host": "localhost", - "port": 3306, - "username": "root", - "password": "root", - "database": "students", - "charset": "utf8mb4", - "database_id": "xxx-xxx-xxx" -} -``` - -## 请求示例(Neo4j) - -```json -{ - "db_type": "neo4j", - "uri": "bolt://localhost:7687", - "username": "neo4j", - "password": "password", - "database": "neo4j" -} -``` - -## 返回参数 - -| 参数 | 类型 | 说明 | -|------|------|------| -| success | bool | 是否连接成功 | -| message | string | 消息 | -| database | string | 数据库名 | -| tables | array | 表结构列表(MySQL/PostgreSQL) | -| graphs | object | 图谱数据(Neo4j) | - -### tables[] 详情(关系型数据库) - -| 参数 | 类型 | 说明 | -|------|------|------| -| table_name | string | 表名 | -| table_comment | string | 表注释 | -| ddl | string | 建表 DDL(带 COMMENT 的映射后 DDL) | -| columns | array | 列信息列表 | - -### columns[] 详情 - -| 参数 | 类型 | 说明 | -|------|------|------| -| column_name | string | 列名 | -| data_type | string | 数据类型 | -| column_type | string | 完整列类型 | -| is_nullable | string | 是否可空(YES/NO) | -| default_value | string | 默认值 | -| column_key | string | 主键标识(PRI/MUL/UNI) | -| extra | string | 额外信息(如 auto_increment) | -| column_comment | string | 列注释 | -| mapped_name | string | 字段中文映射名(已保存的映射) | - -### graphs 详情(Neo4j) - -| 参数 |类型| 说明 | -|------|------|------| -| labels | array | 标签列表 | -| relationshipTypes | array | 关系类型列表 | -| nodes | array | 节点属性定义 | -| relationships | array | 关系属性定义 | - -### graphs.labels[] - -| 参数 | 类型 | 说明 | -|------|------|------| -| name | string | 标签名称 | -| count | int | 节点数量 | - -### graphs.relationshipTypes[] - -| 参数 | 类型 | 说明 | -|------|------|------| -| name | string | 关系类型名称 | -| count | int | 关系数量 | - -### graphs.nodes[] - -| 参数 | 类型 | 说明 | -|------|------|------| -| label | string | 节点标签名 | -| properties | array | 属性列表 | - -### graphs.relationships[] - -| 参数 | 类型 | 说明 | -|------|------|------| -| type | string | 关系类型名 | -| startLabel | string | 起始节点标签 | -| endLabel | string | 目标节点标签 | -| properties | array | 属性列表 | - -## 返回示例(MySQL/PostgreSQL) - -```json -{ - "success": true, - "message": "connection successful", - "database": "students", - "tables": [ - { - "table_name": "users", - "table_comment": "用户表", - "ddl": "CREATE TABLE `users` (\n `id` int(10) unsigned NOT NULL COMMENT '用户ID'\n ...\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", - "columns": [ - { - "column_name": "id", - "data_type": "int", - "column_type": "int(10) unsigned", - "is_nullable": "NO", - "default_value": "", - "column_key": "PRI", - "extra": "auto_increment", - "column_comment": "", - "mapped_name": "用户ID" - } - ] - } - ] -} -``` - -## 返回示例(Neo4j) - -```json -{ - "success": true, - "message": "connection successful", - "database": "neo4j", - "graphs": { - "labels": [ - {"name": "User", "count": 100}, - {"name": "Order", "count": 50} - ], - "relationshipTypes": [ - {"name": "KNOWS", "count": 30}, - {"name": "OWNS", "count": 20} - ], - "nodes": [ - { - "label": "User", - "properties": [ - {"name": "id", "type": "string"}, - {"name": "name", "type": "string"} - ] - } - ], - "relationships": [ - { - "type": "KNOWS", - "startLabel": "User", - "endLabel": "User", - "properties": [ - {"name": "since", "type": "date"} - ] - } - ] - } -} -``` - -## 使用场景 - -1. **关系型数据库**: - - 首次连接:不传 `database_id`,获取实时表结构 - - 恢复映射:传入 `database_id`,返回已保存的 `mapped_name` 和 `ddl` - -2. **Neo4j 图数据库**: - - 连接 Neo4j 并获取图谱概览数据(标签、关系类型、属性定义) - - 用于前端图可视化展示 diff --git a/team-require/api/database-create.md b/team-require/api/database-create.md deleted file mode 100644 index d1dc72d..0000000 --- a/team-require/api/database-create.md +++ /dev/null @@ -1,104 +0,0 @@ -# 创建数据库配置 - -## 接口地址 - -``` -POST /database/add -``` - -## 请求参数 - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| name | string | 是 | 数据库名称 | -| description | string | 否 | 描述 | -| db_type | string | 是 | 数据库类型 | -| host | string | 是 | 主机 | -| port | int | 是 | 端口 | -| username | string | 是 | 用户名 | -| password | string | 否 | 密码 | -| database | string | 是 | 数据库名 | -| charset | string | 否 | 字符集 | -| ssl_mode | string | 否 | SSL 模式 | -| sub_tables | array | 否 | 子表配置列表 | - -### sub_tables[] 详情 - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| parent_table | string | 是 | 原始表名 | -| sub_table_name | string | 是 | 子表别名 | -| sub_table_comment | string | 否 | 子表注释 | -| mapping_type | string | 否 | 映射类型 | -| relation_field | string | 否 | 关联字段 | -| relation_type | string | 否 | 关联类型 | -| fields | array | 否 | 字段映射列表 | - -### fields[] 详情 - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| column_name | string | 是 | 列名 | -| mapped_name | string | 是 | 中文映射名 | - -## 请求示例 - -```json -{ - "name": "学生数据库", - "description": "用于存储学生信息", - "db_type": "mysql", - "host": "localhost", - "port": 3306, - "username": "root", - "password": "root", - "database": "students", - "charset": "utf8mb4", - "sub_tables": [ - { - "parent_table": "users", - "sub_table_name": "用户表", - "sub_table_comment": "用户信息", - "fields": [ - {"column_name": "id", "mapped_name": "用户ID"}, - {"column_name": "name", "mapped_name": "用户名"} - ] - } - ] -} -``` - -## 返回参数 - -| 参数 | 类型 | 说明 | -|------|------|------| -| id | string | 数据库记录ID | -| name | string | 数据库名称 | -| db_type | string | 数据库类型 | -| host | string | 主机 | -| port | int | 端口 | -| ... | ... | 其他字段 | - -## 返回示例 - -```json -{ - "id": "xxx-xxx-xxx", - "name": "学生数据库", - "description": "用于存储学生信息", - "db_type": "mysql", - "host": "localhost", - "port": 3306, - "username": "root", - "password": "root", - "database": "students", - "table_count": 1, - "charset": "utf8mb4", - "created_at": "2026-03-06T15:00:00Z" -} -``` - -## 说明 - -- 创建时会自动连接数据库获取表结构 DDL -- 如果传入了 `fields`(字段映射),会自动生成带 COMMENT 的新 DDL 并存储 diff --git a/team-require/api/database-list.md b/team-require/api/database-list.md deleted file mode 100644 index 87b93b6..0000000 --- a/team-require/api/database-list.md +++ /dev/null @@ -1,51 +0,0 @@ -# 获取数据库列表 - -## 接口地址 - -``` -GET /database/list -``` - -## 请求参数 - -无 - -## 返回参数 - -| 参数 | 类型 | 说明 | -|------|------|------| -| list | array | 数据库列表 | - -### list[] 详情 - -| 参数 | 类型 | 说明 | -|------|------|------| -| id | string | 数据库ID | -| name | string | 数据库名称 | -| description | string | 描述 | -| db_type | string | 数据库类型 | -| host | string | 主机 | -| port | int | 端口 | -| database | string | 数据库名 | -| table_count | int | 子表数量 | -| created_at | string | 创建时间 | - -## 返回示例 - -```json -{ - "list": [ - { - "id": "xxx-xxx", - "name": "学生数据库", - "description": "用于存储学生信息", - "db_type": "mysql", - "host": "localhost", - "port": 3306, - "database": "students", - "table_count": 5, - "created_at": "2026-03-06T15:00:00Z" - } - ] -} -``` diff --git a/team-require/api/knowledge-api.md b/team-require/api/knowledge-api.md deleted file mode 100644 index 593351f..0000000 --- a/team-require/api/knowledge-api.md +++ /dev/null @@ -1,268 +0,0 @@ -# 知识库 API - -## 基础信息 - -| 项目 | 说明 | -|------|------| -| 基础URL | `http://localhost:8082` | - -## 接口列表 - -### 1. 创建知识库 - -**请求** - -``` -POST /api/knowledge/create -Content-Type: application/json -``` - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| name | String | 是 | 知识库名称 | -| description | String | 否 | 知识库描述 | -| llm_model_id | String | 是 | LLM 模型 ID | -| embedding_model_id | String | 是 | Embedding 模型 ID | -| parsing_config | Object | 是 | 解析配置 | -| - engine | String | 是 | 解析引擎:markitdown / docling | -| - docling_url | String | 条件 | Docling URL(engine=docling 时必填) | -| - enable_pdf | Boolean | 否 | 是否启用 PDF 解析 | -| - pandoc | Boolean | 否 | 是否启用 Pandoc | -| storage_config | Object | 否 | 存储配置,不传则使用全局配置 | -| - type | String | 否 | 存储模式:local / minio | -| - endpoint | String | 否 | MinIO endpoint | -| - bucket | String | 否 | MinIO bucket | -| - access_key | String | 否 | MinIO access key | -| - secret_key | String | 否 | MinIO secret key | -| - use_ssl | Boolean | 否 | MinIO 是否使用 SSL | - -**响应** - -```json -{ - "success": true, - "id": "kb_xxx", - "message": "Knowledge base created successfully" -} -``` - ---- - -### 2. 获取知识库列表 - -**请求** - -``` -GET /api/knowledge/list -``` - -**响应** - -```json -{ - "success": true, - "data": [ - { - "id": "kb_001", - "name": "产品文档知识库", - "description": "用于存储产品手册", - "llm_model_id": "model_001", - "embedding_model_id": "model_002", - "status": "active", - "document_count": 15, - "chunk_count": 156, - "created_at": "2024-01-15T10:30:00Z", - "updated_at": "2024-01-15T10:30:00Z" - } - ] -} -``` - ---- - -### 3. 获取知识库详情 - -**请求** - -``` -GET /api/knowledge/:id -``` - -**响应** - -```json -{ - "success": true, - "data": { - "id": "kb_001", - "name": "产品文档知识库", - "description": "用于存储产品手册", - "llm_model_id": "model_001", - "embedding_model_id": "model_002", - "parsing_config": { - "engine": "markitdown", - "enable_pdf": true, - "pandoc": true - }, - "status": "active", - "document_count": 15, - "chunk_count": 156, - "created_at": "2024-01-15T10:30:00Z", - "updated_at": "2024-01-15T10:30:00Z" - } -} -``` - ---- - -### 4. 删除知识库 - -**请求** - -``` -DELETE /api/knowledge/:id -``` - -**响应** - -```json -{ - "success": true, - "message": "Knowledge base deleted" -} -``` - ---- - -### 5. 获取知识库下的文档列表 - -**请求** - -``` -GET /api/knowledge/:id/documents -``` - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| status | String | 否 | 过滤状态:all / parsed / parsing / failed | - -**响应** - -```json -{ - "success": true, - "data": [ - { - "id": "doc_001", - "knowledge_base_id": "kb_001", - "name": "产品手册_v2.0.pdf", - "file_key": "abc123.pdf", - "file_url": "http://localhost:8082/files/abc123.pdf", - "file_size": 2516582, - "status": "parsed", - "chunk_count": 156, - "uploaded_at": "2024-01-15T10:30:00Z" - } - ] -} -``` - ---- - -### 6. 上传文档到知识库 - -**请求** - -``` -POST /api/knowledge/:id/documents -Content-Type: multipart/form-data -``` - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| file | File | 是 | 要上传的文件 | - -**响应** - -```json -{ - "success": true, - "id": "doc_001", - "url": "http://localhost:8082/files/abc123.pdf", - "document": { - "id": "doc_001", - "knowledge_base_id": "kb_001", - "name": "产品手册_v2.0.pdf", - "file_size": 2516582, - "status": "parsing", - "chunk_count": 0, - "uploaded_at": "2024-01-15T10:30:00Z" - }, - "message": "Document uploaded" -} -``` - ---- - -### 7. 删除知识库文档 - -**请求** - -``` -DELETE /api/knowledge/:id/documents/:doc_id -``` - -**响应** - -```json -{ - "success": true, - "message": "Document deleted" -} -``` - ---- - -### 8. 重新解析文档 - -**请求** - -``` -POST /api/knowledge/:id/documents/:doc_id/reparse -``` - -**响应** - -```json -{ - "success": true, - "message": "Document reparse started" -} -``` - ---- - -### 9. 获取文档预览内容 - -**请求** - -``` -GET /api/knowledge/:id/documents/:doc_id/preview -``` - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| page | Number | 否 | 页码(默认 1) | - -**响应** - -```json -{ - "success": true, - "data": { - "total_pages": 3, - "current_page": 1, - "content": "第一章 产品介绍..." - } -} -``` diff --git a/team-require/api/model-api.md b/team-require/api/model-api.md deleted file mode 100644 index 3a35d8b..0000000 --- a/team-require/api/model-api.md +++ /dev/null @@ -1,208 +0,0 @@ -# Model Settings 接口文档 - -## 接口列表 - -### 1. 获取模型列表 - -**接口地址:** `GET /model/list` - -**返回参数:** -```json -{ - "list": [ - { - "id": "xxx-xxx-xxx", - "name": "OpenAI", - "model_type": "chat", - "provider": "OpenAI", - "model": "gpt-4o", - "api_key": "sk-xxx", - "base_url": "https://api.openai.com", - "api_endpoint": "/v1/chat/completions", - "status": "active", - "created_at": "2024-01-01T00:00:00Z", - "updated_at": "2024-01-01T00:00:00Z" - } - ] -} -``` - ---- - -### 2. 获取模型详情 - -**接口地址:** `GET /model/:id` - -**返回参数:** -```json -{ - "id": "xxx-xxx-xxx", - "name": "OpenAI", - "model_type": "chat", - "provider": "OpenAI", - "model": "gpt-4o", - "api_key": "sk-xxx", - "base_url": "https://api.openai.com", - "api_endpoint": "/v1/chat/completions", - "status": "active", - "created_at": "2024-01-01T00:00:00Z", - "updated_at": "2024-01-01T00:00:00Z" -} -``` - ---- - -### 3. 创建模型 - -**接口地址:** `POST /model/add` - -**请求参数:** - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| name | string | 是 | 模型名称 | -| model_type | string | 是 | 模型类型:chat/embedding/rerank/vlm | -| provider | string | 是 | 提供商:OpenAI/Ollama | -| model | string | 是 | 模型标识,如 gpt-4o | -| api_key | string | 是 | API 密钥 | -| base_url | string | 是 | 基础 URL | -| api_endpoint | string | 否 | API 端点路径 | - -**请求示例:** -```json -{ - "name": "OpenAI", - "model_type": "chat", - "provider": "OpenAI", - "model": "gpt-4o", - "api_key": "sk-xxx", - "base_url": "https://api.openai.com", - "api_endpoint": "/v1/chat/completions" -} -``` - -**返回参数:** -```json -{ - "id": "xxx-xxx-xxx", - "name": "OpenAI", - "model_type": "chat", - "provider": "OpenAI", - "model": "gpt-4o", - "api_key": "sk-xxx", - "base_url": "https://api.openai.com", - "api_endpoint": "/v1/chat/completions", - "status": "active", - "created_at": "2024-01-01T00:00:00Z", - "updated_at": "2024-01-01T00:00:00Z" -} -``` - ---- - -### 4. 更新模型 - -**接口地址:** `PUT /model/:id` - -**请求参数:** - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| name | string | 否 | 模型名称 | -| model_type | string | 否 | 模型类型:chat/embedding/rerank/vlm | -| provider | string | 否 | 提供商:OpenAI/Ollama | -| model | string | 否 | 模型标识 | -| api_key | string | 否 | API 密钥 | -| base_url | string | 否 | 基础 URL | -| api_endpoint | string | 否 | API 端点路径 | -| status | string | 否 | 状态:active/inactive | - -**请求示例:** -```json -{ - "name": "OpenAI Updated", - "model_type": "chat", - "provider": "OpenAI", - "model": "gpt-4o", - "api_key": "sk-xxx", - "base_url": "https://api.openai.com", - "api_endpoint": "/v1/chat/completions", - "status": "active" -} -``` - ---- - -### 5. 删除模型 - -**接口地址:** `DELETE /model/:id` - -**返回参数:** -```json -{ - "success": true -} -``` - ---- - -### 6. 测试连接 - -**接口地址:** `POST /model/test` - -**请求参数:** - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| provider | string | 是 | 提供商:OpenAI/Ollama | -| model | string | 是 | 模型标识 | -| api_key | string | 是 | API 密钥 | -| base_url | string | 是 | 基础 URL | -| api_endpoint | string | 否 | API 端点路径 | - -**请求示例:** -```json -{ - "provider": "OpenAI", - "model": "gpt-4o", - "api_key": "sk-xxx", - "base_url": "https://api.openai.com", - "api_endpoint": "/v1/chat/completions" -} -``` - -**返回参数:** -```json -{ - "success": true, - "message": "Connection successful" -} -``` - -或失败时: -```json -{ - "success": false, - "message": "HTTP 401: Unauthorized" -} -``` - ---- - -## 数据结构 - -### ModelInfo 模型信息 - -| 字段 | 类型 | 说明 | -|------|------|------| -| id | string | 主键 UUID | -| name | string | 模型名称 | -| model_type | string | 模型类型:chat/embedding/rerank/vlm | -| provider | string | 提供商:OpenAI/Ollama | -| model | string | 模型标识 | -| api_key | string | API 密钥 | -| base_url | string | 基础 URL | -| api_endpoint | string | API 端点路径 | -| status | string | 状态:active/inactive | -| created_at | datetime | 创建时间 | -| updated_at | datetime | 更新时间 | diff --git a/team-require/api/neo4j-check.md b/team-require/api/neo4j-check.md deleted file mode 100644 index a75f4c5..0000000 --- a/team-require/api/neo4j-check.md +++ /dev/null @@ -1,265 +0,0 @@ -# Neo4j 连接测试 - -## 接口地址 - -``` -POST /neo4j/check -``` - -## 请求参数 - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| host | string | 是 | Neo4j 主机 | -| port | int | 是 | Neo4j 端口(默认 7687) | -| username | string | 是 | 用户名(默认 neo4j) | -| password | string | 是 | 密码 | -| database | string | 否 | 数据库名(默认 neo4j) | -| name | string | 否 | 数据库名称,用于保存记录 | -| uri | string | 否 | Neo4j 连接地址(bolt://host:port) | -| description | string | 否 | 数据库描述 | - -## 请求示例 - -```json -{ - "host": "localhost", - "port": 7687, - "username": "neo4j", - "password": "password", - "database": "neo4j", - "name": "My Neo4j Database" -} -``` - -## 返回参数 - -| 参数 | 类型 | 说明 | -|------|------|------| -| success | bool | 是否连接成功 | -| message | string | 消息 | -| version | string | Neo4j 版本 | -| databases | array | 数据库列表 | -| databaseId | string | 数据库记录 ID(新增) | -| name | string | 数据库名称(新增) | -| description | string | 数据库描述(新增) | - -## 返回示例 - -```json -{ - "success": true, - "message": "connection successful", - "version": "5.14.0", - "databases": ["neo4j", "system"], - "databaseId": "abc-123-def", - "name": "Neo4j-neo4j", - "description": "Neo4j neo4j@localhost:7687" -} -``` - -> **说明**:连接成功时,后端会自动检查数据库记录是否存在,不存在则创建并返回 `databaseId`、`name` 和 `description`。前端可使用这些信息进行后续保存图谱操作。 - ---- - -# Neo4j 获取图谱概览数据(核心接口) - -获取所有标签(Labels)和关系类型(Relationship Types)的统计信息,用于前端图谱可视化。 - -## 接口地址 - -``` -POST /neo4j/graphs -``` - -## 请求参数 - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| uri | string | 是 | Neo4j 连接地址,如 bolt://localhost:7687 | -| username | string | 是 | 用户名 | -| password | string | 是 | 密码 | -| database | string | 否 | 数据库名(默认 neo4j) | - -## 请求示例 - -```json -{ - "uri": "bolt://localhost:7687", - "username": "neo4j", - "password": "password", - "database": "neo4j" -} -``` - -## 返回参数 - -| 参数 | 类型 | 说明 | -|------|------|------| -| success | bool | 是否成功 | -| graphs | object | 图谱数据 | - -### graphs 对象 - -| 参数 | 类型 | 说明 | -|------| -| labels------|------| | array | 标签列表 | -| relationshipTypes | array | 关系类型列表 | - -### labels 数组项 - -| 参数 | 类型 | 说明 | -|------|------|------| -| name | string | 标签名称 | -| count | int | 该标签的节点数量 | - -### relationshipTypes 数组项 - -| 参数 | 类型 | 说明 | -|------|------|------| -| name | string | 关系类型名称 | -| count | int | 该关系的数量 | - -## 返回示例 - -```json -{ - "success": true, - "graphs": { - "labels": [ - {"name": "User", "count": 1523}, - {"name": "Order", "count": 856}, - {"name": "Product", "count": 2341}, - {"name": "Category", "count": 45}, - {"name": "Review", "count": 5678} - ], - "relationshipTypes": [ - {"name": "KNOWS", "count": 2341}, - {"name": "BOUGHT", "count": 5678}, - {"name": "BELONGS_TO", "count": 2341}, - {"name": "HAS_REVIEW", "count": 5678}, - {"name": "LOCATED_IN", "count": 1523} - ] - } -} -``` - -## 前端使用说明 - -前端使用 ECharts 力导向图谱展示: -- `labels` 生成图谱节点,count 决定节点大小 -- `relationshipTypes` 生成图谱边 -- 建议返回至少 5-10 个关系类型以便生成丰富图谱 - ---- - -# Neo4j 获取节点详情 - -## 接口地址 - -``` -POST /neo4j/nodes -``` - -## 请求参数 - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| uri | string | 是 | Neo4j 连接地址,如 bolt://localhost:7687 | -| username | string | 是 | 用户名 | -| password | string | 是 | 密码 | -| database | string | 否 | 数据库名 | -| label | string | 是 | 节点标签名 | -| limit | int | 否 | 返回数量限制,默认 10 | - -## 请求示例 - -```json -{ - "uri": "bolt://localhost:7687", - "username": "neo4j", - "password": "password", - "label": "User", - "limit": 10 -} -``` - -## 返回参数 - -| 参数 | 类型 | 说明 | -|------|------|------| -| success | bool | 是否成功 | -| message | string | 消息 | -| nodes | array | 节点数据列表 | - -## 返回示例 - -```json -{ - "success": true, - "message": "success", - "nodes": [ - {"id": "1", "name": "张三", "email": "zhangsan@example.com"}, - {"id": "2", "name": "李四", "email": "lisi@example.com"} - ] -} -``` - ---- - -# Neo4j 获取关系详情 - -## 接口地址 - -``` -POST /neo4j/relationships -``` - -## 请求参数 - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| uri | string | 是 | Neo4j 连接地址 | -| username | string | 是 | 用户名 | -| password | string | 是 | 密码 | -| database | string | 否 | 数据库名 | -| relationship_type | string | 是 | 关系类型名 | -| limit | int | 否 | 返回数量限制,默认 10 | - -## 请求示例 - -```json -{ - "uri": "bolt://localhost:7687", - "username": "neo4j", - "password": "password", - "relationship_type": "KNOWS", - "limit": 10 -} -``` - -## 返回参数 - -| 参数 | 类型 | 说明 | -|------|------|------| -| success | bool | 是否成功 | -| message | string | 消息 | -| relationships | array | 关系数据列表 | - -## 返回示例 - -```json -{ - "success": true, - "message": "success", - "relationships": [ - { - "startId": "1", - "endId": "2", - "startLabels": ["User"], - "endLabels": ["User"], - "since": "2020-01-01" - } - ] -} -``` diff --git a/team-require/api/neo4j-graph-save.md b/team-require/api/neo4j-graph-save.md deleted file mode 100644 index 89d69e8..0000000 --- a/team-require/api/neo4j-graph-save.md +++ /dev/null @@ -1,75 +0,0 @@ -# Neo4j 图谱保存接口需求 - -## 需求说明 - -前端需要保存 Neo4j 图谱的连接信息,以便后续快速加载和查看。 - ---- - -## 接口地址 - -``` -POST /database/graph/save -``` - -## 请求参数 - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| databaseId | string | 是 | 数据库 ID | -| databaseName | string | 是 | 数据库名称 | -| uri | string | 是 | Neo4j 连接地址,如 bolt://localhost:7687 | -| username | string | 是 | 用户名 | -| labels | array | 是 | 标签列表 | -| relationshipTypes | array | 是 | 关系类型列表 | -| selectedLabel | string | 否 | 当前选中的标签 | - -## 请求示例 - -```json -{ - "databaseId": "123", - "databaseName": "neo4j", - "uri": "bolt://10.10.10.189:7687", - "username": "neo4j", - "labels": ["User", "Order", "Product"], - "relationshipTypes": ["KNOWS", "BOUGHT", "BELONGS_TO"], - "selectedLabel": "User" -} -``` - -## 返回参数 - -| 参数 | 类型 | 说明 | -|------|------|------| -| success | bool | 是否成功 | -| message | string | 消息 | - -## 返回示例 - -```json -{ - "success": true, - "message": "保存成功" -} -``` - ---- - -## 前端调用示例 - -```javascript -fetch('/database/graph/save', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - databaseId: '123', - databaseName: 'neo4j', - uri: 'bolt://10.10.10.189:7687', - username: 'neo4j', - labels: ['User', 'Order', 'Product'], - relationshipTypes: ['KNOWS', 'BOUGHT', 'BELONGS_TO'], - selectedLabel: 'User', - }), -}) -``` diff --git a/team-require/api/subtable-list.md b/team-require/api/subtable-list.md deleted file mode 100644 index c916bcb..0000000 --- a/team-require/api/subtable-list.md +++ /dev/null @@ -1,75 +0,0 @@ -# 获取子表列表 - -## 接口地址 - -``` -GET /sub-table/database/:database_id -``` - -## 路径参数 - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| database_id | string | 是 | 数据库ID | - -## 返回参数 - -| 参数 | 类型 | 说明 | -|------|------|------| -| list | array | 子表列表 | - -### list[] 详情 - -| 参数 | 类型 | 说明 | -|------|------|------| -| id | string | 子表ID | -| database_id | string | 关联的数据库ID | -| parent_table | string | 原始表名 | -| sub_table_name | string | 子表别名 | -| sub_table_comment | string | 子表注释 | -| mapping_type | string | 映射类型 | -| relation_field | string | 关联字段 | -| relation_type | string | 关联类型 | -| fields | array | 字段映射列表 | -| ddl | string | 建表 DDL(带 COMMENT) | -| created_at | string | 创建时间 | - -### fields[] 详情 - -| 参数 | 类型 | 说明 | -|------|------|------| -| column_name | string | 列名 | -| mapped_name | string | 中文映射名 | - -## 返回示例 - -```json -{ - "list": [ - { - "id": "xxx-xxx", - "database_id": "database-xxx", - "parent_table": "users", - "sub_table_name": "用户表", - "sub_table_comment": "用户信息", - "mapping_type": "horizontal", - "relation_field": "id", - "relation_type": "one_to_many", - "fields": [ - {"column_name": "id", "mapped_name": "用户ID"}, - {"column_name": "name", "mapped_name": "用户名"} - ], - "ddl": "CREATE TABLE `users` (\n `id` int(10) unsigned NOT NULL COMMENT '用户ID'\n ...\n)", - "created_at": "2026-03-06T15:00:00Z" - } - ] -} -``` - -## 使用场景 - -用于恢复映射状态: -1. 用户点击已存在的数据库的 "Map Tables" 按钮 -2. 调用此接口获取已保存的子表信息 -3. 根据 `parent_table` 勾选已选择的表 -4. 根据 `fields` 恢复字段映射 diff --git a/team-require/api/upload-api.md b/team-require/api/upload-api.md deleted file mode 100644 index a01d0fc..0000000 --- a/team-require/api/upload-api.md +++ /dev/null @@ -1,96 +0,0 @@ -# 文件上传 API - -## 基础信息 - -| 项目 | 说明 | -|------|------| -| 基础URL | `http://localhost:8082` | -| 上传模式 | local / minio(配置决定) | - -## 配置说明 - -```yaml -# config.yaml -upload_mode: "local" # 上传模式:local 或 minio -upload_local_path: "resource/files" # 本地存储路径 -server_base_url: "http://localhost:8082" # 服务器基础URL - -# MinIO 配置(upload_mode 为 minio 时需要) -minio_endpoint: "localhost:9000" -minio_access_key: "your-access-key" -minio_secret_key: "your-secret-key" -minio_bucket: "x-agents" -minio_use_ssl: false -``` - -## 接口列表 - -### 1. 上传文件 - -**请求** - -``` -POST /api/file_upload -Content-Type: multipart/form-data -``` - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| file | File | 是 | 要上传的文件 | - -**响应** - -```json -{ - "success": true, - "url": "http://localhost:8082/files/abc123.pdf", - "fileKey": "abc123", - "message": "Upload successful" -} -``` - -**错误响应** - -```json -{ - "success": false, - "message": "File too large (max 100MB)" -} -``` - ---- - -### 2. 删除文件 - -**请求** - -``` -DELETE /api/file_upload/:filename -``` - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| filename | String | 是 | 文件名(不含路径) | - -**响应** - -```json -{ - "success": true, - "message": "File deleted" -} -``` - ---- - -### 3. 访问文件(仅本地模式) - -文件上传后,本地模式下可通过以下 URL 直接访问: - -``` -GET /files/{filename} -``` - -例如:`http://localhost:8082/files/abc123.pdf` - -> 注意:MinIO 模式返回的是预签名 URL,有效期 24 小时。 diff --git a/team-require/web/columns-api.md b/team-require/web/columns-api.md deleted file mode 100644 index a893fb8..0000000 --- a/team-require/web/columns-api.md +++ /dev/null @@ -1,92 +0,0 @@ -# 后端需求 - 表结构返回 columns 数据 - -## 问题描述 - -前端在 Edit Mapping 页面需要展示表的列信息(字段名、类型、COMMENT等),但前端自行解析 DDL 存在困难。 - -## 需求 - -后端在获取表结构列表时,需要同时返回: - -1. **DDL 语句**(已有的需求,继续保留) -2. **结构化的 columns 数据**(新增) - -### 返回数据结构 - -```json -{ - "success": true, - "tables": [ - { - "table_name": "exam_scores", - "table_comment": "考试成绩表", - "ddl": "CREATE TABLE `exam_scores` (...)", - "columns": [ - { - "column_name": "id", - "data_type": "int", - "column_type": "int(10) unsigned", - "is_nullable": "NO", - "default_value": null, - "column_key": "PRI", - "extra": "auto_increment", - "column_comment": "" - }, - { - "column_name": "student_id", - "data_type": "int", - "column_type": "int(10) unsigned", - "is_nullable": "NO", - "default_value": null, - "column_key": "", - "extra": "", - "column_comment": "" - }, - { - "column_name": "subject", - "data_type": "varchar", - "column_type": "varchar(50)", - "is_nullable": "NO", - "default_value": null, - "column_key": "", - "extra": "", - "column_comment": "科目" - }, - { - "column_name": "score", - "data_type": "double", - "column_type": "double", - "is_nullable": "YES", - "default_value": null, - "column_key": "", - "extra": "", - "column_comment": "分数" - } - ] - } - ] -} -``` - -### 字段说明 - -| 字段 | 类型 | 说明 | -|------|------|------| -| column_name | string | 列名 | -| data_type | string | 数据类型(如 int, varchar, double) | -| column_type | string | 完整列类型(如 int(10) unsigned) | -| is_nullable | string | 是否可空(YES/NO) | -| default_value | string | 默认值 | -| column_key | string | 主键标识(PRI/MUL/UNI) | -| extra | string | 额外信息(如 auto_increment) | -| column_comment | string | 列注释 | - -## 影响范围 - -- 文件:`server/internal/service/database_service.go` -- 函数:`getMySQLTables`, `getPostgresTables` -- 数据模型:`server/internal/model/sub_table_info.go` 的 `ColumnInfo` 结构体 - -## 优先级 - -高 - 前端 Edit Mapping 页面字段映射功能依赖此数据 diff --git a/team-require/web/ddl-edit.md b/team-require/web/ddl-edit.md deleted file mode 100644 index 204b862..0000000 --- a/team-require/web/ddl-edit.md +++ /dev/null @@ -1,66 +0,0 @@ -# 后端需求 - DDL 编辑功能 - -## 问题描述 - -前端 Database 页面的 Table Mapping 功能已从"字段映射"改为"DDL 编辑"模式。后端需要支持保存和读取 DDL 数据。 - -## 需求 - -### 1. 保存 DDL - -前端保存时发送 `ddl` 字段而非 `fields` 字段。 - -请求结构: -```json -{ - "name": "数据库名", - "sub_tables": [ - { - "parent_table": "users", - "sub_table_name": "用户表", - "sub_table_comment": "用户表", - "ddl": "CREATE TABLE users (...)" - } - ] -} -``` - -### 2. 后端处理 - -- `CreateSubTableRequest` 已有 `DDL string` 字段(已添加) -- `UpdateSubTableRequest` 已有 `DDL string` 字段(已添加) -- `UpdateDatabaseRequest` 已有 `SubTables []CreateSubTableRequest` 字段(已添加) - -### 3. Service 层修改 - -**sub_table_service.go**: - -1. `Create` 函数 - 添加 DDL 字段赋值: -```go -info := &model.SubTableInfo{ - // ... 现有字段 - DDL: req.DDL, -} -``` - -2. `Update` 函数 - 添加 DDL 更新逻辑: -```go -// 更新 DDL -info.DDL = req.DDL -``` - -**database_service.go 或 handler**: - -在 `Update` 方法中处理 `SubTables` 字段: -- 当前端传入 `sub_tables` 时,需要创建或更新对应的子表记录(包括 DDL) -- 遍历 `sub_tables`,调用 `SubTableService.Create` 或 `SubTableService.Update` - -## 影响范围 - -- `server/internal/service/sub_table_service.go` - Create/Update 方法 -- `server/internal/service/database_service.go` 或 handler - Update 方法处理 SubTables - -## 状态 - -- [x] 前端修改完成 -- [x] 后端修改已完成 diff --git a/team-require/web/field-mapping.md b/team-require/web/field-mapping.md deleted file mode 100644 index 02afa5e..0000000 --- a/team-require/web/field-mapping.md +++ /dev/null @@ -1,89 +0,0 @@ -# 后端需求 - 字段映射保存与读取 - -## 问题描述 - -前端 Edit Mapping 页面中,用户输入的字段中文映射名(mapped_name)在保存后,第二次打开时丢失了。 - -## 原因分析 - -1. **保存时**:前端只保存了表级别信息,没有保存字段的中文映射 -2. **加载时**:前端每次都从 `/database/check` 重新获取表结构,没有读取已保存的映射数据 - -## 需求 - -### 1. 保存字段映射 - -前端保存时需要传递每个字段的中文映射名,后端需要存储这些数据。 - -请求结构: -```json -{ - "name": "数据库名", - "sub_tables": [ - { - "parent_table": "users", - "sub_table_name": "用户表", - "sub_table_comment": "用户表", - "fields": [ - { - "column_name": "id", - "mapped_name": "编号" - }, - { - "column_name": "username", - "mapped_name": "用户名" - } - ] - } - ] -} -``` - -### 2. 返回字段映射 - -后端在返回表结构时,需要同时返回已保存的字段映射信息。 - -返回结构: -```json -{ - "success": true, - "tables": [ - { - "table_name": "users", - "table_comment": "用户表", - "ddl": "...", - "columns": [ - { - "column_name": "id", - "data_type": "int", - "column_type": "int(10)", - "column_comment": "", - "mapped_name": "编号" - }, - { - "column_name": "username", - "data_type": "varchar", - "column_type": "varchar(50)", - "column_comment": "用户名", - "mapped_name": "用户名" - } - ] - } - ] -} -``` - -### 3. 数据存储 - -- 可以在 `sub_table_info` 表中增加 `fields` JSON 字段存储字段映射 -- 或者创建新的关联表 `sub_table_fields` - -## 影响范围 - -- `server/internal/service/database_service.go` - Create/Update 方法 -- `server/internal/model/` - 数据模型修改 -- 子表映射的数据存储结构 - -## 优先级 - -高 - 用户输入的映射数据丢失影响使用体验 diff --git a/team-require/web/knowledge-base-api.md b/team-require/web/knowledge-base-api.md deleted file mode 100644 index e3306e7..0000000 --- a/team-require/web/knowledge-base-api.md +++ /dev/null @@ -1,375 +0,0 @@ -# 知识库创建 API - -## 基础信息 - -| 项目 | 说明 | -|------|------| -| 基础URL | `http://localhost:8082` | -| 前端页面 | Knowledge Base 创建弹窗 | - -## 接口列表 - -### 1. 创建知识库 - -**请求** - -``` -POST /api/knowledge/create -Content-Type: application/json -``` - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| name | String | 是 | 知识库名称 | -| description | String | 否 | 知识库描述 | -| llm_model_id | String | 是 | LLM 模型 ID(来自 model 表) | -| embedding_model_id | String | 是 | Embedding 模型 ID(来自 model 表) | -| parsing_config | Object | 是 | 解析配置 | -| - engine | String | 是 | 解析引擎:markitdown / docling | -| - docling_url | String | 条件必填 | Docling 服务 URL(engine=docling 时必填) | -| - enable_pdf | Boolean | 否 | 是否启用 PDF 解析(默认 true) | -| - pandoc | Boolean | 否 | 是否启用 Pandoc(默认 true) | -| storage_config | Object | 否 | 存储配置(默认 local) | -| - type | String | 是 | 存储类型:local / minio / s3 | -| - endpoint | String | 否 | MinIO Endpoint(如 minio:9000) | -| - access_key_id | String | 否 | MinIO Access Key ID | -| - secret_access_key | String | 否 | MinIO Secret Access Key | -| - bucket | String | 否 | MinIO Bucket 名称 | - -**请求示例** - -本地存储: -```json -{ - "name": "产品文档知识库", - "description": "用于存储产品手册和文档", - "llm_model_id": "model_001", - "embedding_model_id": "model_002", - "parsing_config": { - "engine": "markitdown", - "enable_pdf": true, - "pandoc": true - }, - "storage_config": { - "type": "local" - } -} -``` - -使用 Docling + MinIO: -```json -{ - "name": "产品文档知识库", - "description": "用于存储产品手册和文档", - "llm_model_id": "model_001", - "embedding_model_id": "model_002", - "parsing_config": { - "engine": "docling", - "docling_url": "http://localhost:8501", - "enable_pdf": true, - "pandoc": true - }, - "storage_config": { - "type": "minio", - "endpoint": "localhost:9000", - "access_key_id": "minioadmin", - "secret_access_key": "minioadmin", - "bucket": "x-agents" - } -} -``` - -**成功响应** - -```json -{ - "success": true, - "id": "kb_abc123", - "message": "Knowledge base created successfully" -} -``` - -**错误响应** - -```json -{ - "success": false, - "message": "LLM model not found" -} -``` - ---- - -### 2. 获取知识库列表 - -**请求** - -``` -GET /api/knowledge/list -``` - -**响应** - -```json -{ - "success": true, - "data": [ - { - "id": "kb_001", - "name": "产品文档知识库", - "description": "用于存储产品手册", - "llm_model_id": "model_001", - "embedding_model_id": "model_002", - "status": "active", - "document_count": 15, - "chunk_count": 156, - "created_at": "2024-01-15T10:30:00Z", - "updated_at": "2024-01-15T10:30:00Z" - } - ] -} -``` - ---- - -### 3. 获取知识库详情 - -**请求** - -``` -GET /api/knowledge/:id -``` - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| id | String | 是 | 知识库 ID | - -**响应** - -```json -{ - "success": true, - "data": { - "id": "kb_001", - "name": "产品文档知识库", - "description": "用于存储产品手册", - "llm_model_id": "model_001", - "embedding_model_id": "model_002", - "parsing_config": { - "engine": "markitdown", - "enable_pdf": true, - "pandoc": true - }, - "status": "active", - "document_count": 15, - "chunk_count": 156, - "created_at": "2024-01-15T10:30:00Z", - "updated_at": "2024-01-15T10:30:00Z" - } -} -``` - ---- - -### 4. 删除知识库 - -**请求** - -``` -DELETE /api/knowledge/:id -``` - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| id | String | 是 | 知识库 ID | - -**响应** - -```json -{ - "success": true, - "message": "Knowledge base deleted" -} -``` - ---- - -### 5. 获取知识库下的文档列表 - -**请求** - -``` -GET /api/knowledge/:id/documents -``` - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| id | String | 是 | 知识库 ID | - -**查询参数** - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| status | String | 否 | 过滤状态:all / parsed / parsing / failed | - -**响应** - -```json -{ - "success": true, - "data": [ - { - "id": "doc_001", - "knowledge_base_id": "kb_001", - "name": "产品手册_v2.0.pdf", - "file_key": "abc123.pdf", - "file_url": "http://localhost:8082/files/abc123.pdf", - "file_size": 2516582, - "status": "parsed", - "chunk_count": 156, - "uploaded_at": "2024-01-15T10:30:00Z" - } - ] -} -``` - ---- - -### 6. 上传文档到知识库 - -**请求** - -``` -POST /api/knowledge/:id/documents -Content-Type: multipart/form-data -``` - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| id | String | 是 | 知识库 ID | -| file | File | 是 | 要上传的文件 | - -**响应** - -```json -{ - "success": true, - "dataid": "doc_001", - ": { - " "name": "产品手册_v2.0.pdf", - "status": "parsing" - } -} -``` - ---- - -### 7. 删除知识库文档 - -**请求** - -``` -DELETE /api/knowledge/:id/documents/:doc_id -``` - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| id | String | 是 | 知识库 ID | -| doc_id | String | 是 | 文档 ID | - -**响应** - -```json -{ - "success": true, - "message": "Document deleted" -} -``` - ---- - -### 8. 重新解析文档 - -**请求** - -``` -POST /api/knowledge/:id/documents/:doc_id/reparse -``` - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| id | String | 是 | 知识库 ID | -| doc_id | String | 是 | 文档 ID | - -**响应** - -```json -{ - "success": true, - "message": "Document reparse started" -} -``` - ---- - -### 9. 获取文档预览内容 - -**请求** - -``` -GET /api/knowledge/:id/documents/:doc_id/preview -``` - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| id | String | 是 | 知识库 ID | -| doc_id | String | 是 | 文档 ID | -| page | Number | 否 | 页码(默认 1) | - -**响应** - -```json -{ - "success": true, - "data": { - "total_pages": 3, - "current_page": 1, - "content": "第一章 产品介绍\n\n欢迎使用我们的产品手册..." - } -} -``` - ---- - -## 数据库表设计(参考) - -### knowledge_base 表 - -| 字段 | 类型 | 说明 | -|------|------|------| -| id | String | 主键 | -| name | String | 知识库名称 | -| description | Text | 描述 | -| llm_model_id | String | LLM 模型 ID | -| embedding_model_id | String | Embedding 模型 ID | -| parsing_config | JSON | 解析配置 | -| storage_config | JSON | 存储配置(包含 type, endpoint, access_key_id, secret_access_key, bucket) | -| status | String | 状态:active / inactive | -| document_count | Integer | 文档数量 | -| chunk_count | Integer | 切片数量 | -| created_at | Timestamp | 创建时间 | -| updated_at | Timestamp | 更新时间 | - -### knowledge_document 表 - -| 字段 | 类型 | 说明 | -|------|------|------| -| id | String | 主键 | -| knowledge_base_id | String | 知识库 ID | -| name | String | 文档名称 | -| file_key | String | 文件存储 key | -| file_url | String | 文件访问 URL(本地路径或 MinIO 预签名 URL) | -| file_size | BigInteger | 文件大小 | -| status | String | 状态:parsing / parsed / failed | -| chunk_count | Integer | 切片数量 | -| uploaded_at | Timestamp | 上传时间 | diff --git a/team-require/web/mapping-state.md b/team-require/web/mapping-state.md deleted file mode 100644 index 6142913..0000000 --- a/team-require/web/mapping-state.md +++ /dev/null @@ -1,43 +0,0 @@ -# 后端需求 - 保存和恢复映射状态 - -## 问题描述 - -用户第一次选择表并设置字段映射后,第二次点击 "Map Tables" 按钮进入界面时,之前选择的表和设置的字段映射都丢失了。 - -## 需求 - -前端打开已存在的数据库映射时,需要恢复以下状态: - -### 1. 已选择的表列表 - -后端需要在数据库记录中保存用户选择了哪些表(不仅仅是子表信息),或者在查询时返回该数据库关联的所有子表。 - -### 2. 字段映射 - -每个子表保存的字段映射(mapped_name)需要在前端重新加载时显示。 - -## 期望的行为 - -1. 用户点击已存在的数据库的 "Map Tables" 按钮 -2. 前端获取实时表结构 -3. 同时加载该数据库已保存的子表信息(包括选择的表和字段映射) -4. 前端合并数据,显示: - - 已选择的表(勾选状态) - - 每个字段之前设置的 mapped_name - -## 技术实现建议 - -在数据库表中增加或利用已有字段: - -- `sub_table_info` 表已包含 `Fields` JSON 字段存储字段映射 -- 需要在创建/更新数据库时保存选择的表列表 -- 或者在查询时返回该数据库下所有已创建的子表 - -## 影响范围 - -- 数据库创建/更新接口 -- 子表映射查询接口 - -## 优先级 - -高 - 影响用户体验,第二次进入无法看到之前的工作成果 diff --git a/team-require/web/model-settings.md b/team-require/web/model-settings.md deleted file mode 100644 index 33ce937..0000000 --- a/team-require/web/model-settings.md +++ /dev/null @@ -1,193 +0,0 @@ -# Model Settings 需求文档 - -## 需求概述 - -Model Settings 页面用于管理 AI 模型配置,支持添加、编辑、删除和测试模型连接。 - -## 功能列表 - -### 1. 模型列表展示 - -展示已配置的模型列表,包含以下字段: -- Model Name(模型名称) -- Model Type(模型类型):Chat / Embedding / Rerank / VLM -- API Endpoint(API 端点) -- Status(状态):Active / Inactive - -### 2. 添加新模型 - -点击 "Add New Model" 按钮,弹出表单包含以下字段: -- Model Name(必填) -- Model Type(必选):Chat / Embedding / Rerank / VLM -- Provider(必选):OpenAI / Ollama -- Model(必填):模型名称,如 gpt-4o -- API Key(必填) -- Base URL(必填) -- API Endpoint(可选) - -### 3. 测试连接 - -在添加模型表单中提供 "Test Connection" 按钮,用于验证模型连接是否可用。 - -### 4. 编辑模型 - -点击编辑按钮,弹出编辑表单,可修改模型信息。 - -### 5. 删除模型 - -点击删除按钮,确认后删除模型记录。 - ---- - -## 后端接口需求 - -### 1. 获取模型列表 - -**接口地址:** `GET /api/models` 或 `GET /model/list` - -**返回参数:** -```json -{ - "list": [ - { - "id": "1", - "name": "OpenAI", - "model_type": "chat", - "provider": "OpenAI", - "model": "gpt-4o", - "api_key": "sk-xxx", - "base_url": "https://api.openai.com", - "api_endpoint": "/v1/chat/completions", - "status": "active", - "created_at": "2024-01-01T00:00:00Z", - "updated_at": "2024-01-01T00:00:00Z" - } - ] -} -``` - -### 2. 添加模型 - -**接口地址:** `POST /api/models` 或 `POST /model/add` - -**请求参数:** -```json -{ - "name": "OpenAI", - "model_type": "chat", - "provider": "OpenAI", - "model": "gpt-4o", - "api_key": "sk-xxx", - "base_url": "https://api.openai.com", - "api_endpoint": "/v1/chat/completions" -} -``` - -**返回参数:** -```json -{ - "id": "1", - "name": "OpenAI", - "model_type": "chat", - ... -} -``` - -### 3. 更新模型 - -**接口地址:** `PUT /api/models/{id}` 或 `PUT /model/{id}` - -**请求参数:** -```json -{ - "name": "OpenAI Updated", - "model_type": "chat", - "provider": "OpenAI", - "model": "gpt-4o", - "api_key": "sk-xxx", - "base_url": "https://api.openai.com", - "api_endpoint": "/v1/chat/completions", - "status": "active" -} -``` - -### 4. 删除模型 - -**接口地址:** `DELETE /api/models/{id}` 或 `DELETE /model/{id}` - -**返回参数:** -```json -{ - "success": true -} -``` - -### 5. 测试连接 - -**接口地址:** `POST /api/models/test` 或 `POST /model/test` - -**请求参数:** -```json -{ - "provider": "OpenAI", - "model": "gpt-4o", - "api_key": "sk-xxx", - "base_url": "https://api.openai.com", - "api_endpoint": "/v1/chat/completions" -} -``` - -**返回参数:** -```json -{ - "success": true, - "message": "Connection successful" -} -``` - ---- - -## 数据结构 - -### Model 表结构(参考) - -| 字段 | 类型 | 说明 | -|------|------|------| -| id | string | 主键 UUID | -| name | string | 模型名称 | -| model_type | string | 模型类型:chat/embedding/rerank/vlm | -| provider | string | 提供商:OpenAI/Ollama | -| model | string | 模型标识 | -| api_key | string | API 密钥(加密存储) | -| base_url | string | 基础 URL | -| api_endpoint | string | API 端点路径 | -| status | string | 状态:active/inactive | -| created_at | datetime | 创建时间 | -| updated_at | datetime | 更新时间 | - ---- - -## 前端组件状态 - -### 表单数据 (newModelForm) -```typescript -{ - name: string, - apiKey: string, - apiEndpoint: string, - baseUrl: string, - provider: string, - model: string, - modelType: string -} -``` - -### 模型类型选项 (modelTypeOptions) -- Chat -- Embedding -- Rerank -- VLM - -### 提供商选项 (providerOptions) -- OpenAI -- Ollama diff --git a/team-require/web/neo4j-api-requirement.md b/team-require/web/neo4j-api-requirement.md deleted file mode 100644 index 44325a5..0000000 --- a/team-require/web/neo4j-api-requirement.md +++ /dev/null @@ -1,110 +0,0 @@ -# Neo4j 接口后端需求 - -## 需求说明 - -前端 Neo4j 图谱功能已完成,后端接口需要匹配前端调用。 - ---- - -## 1. 新增 `/neo4j/graphs` 接口 - -### 接口地址 -``` -POST /neo4j/graphs -``` - -### 请求参数 -```json -{ - "uri": "bolt://localhost:7687", - "username": "neo4j", - "password": "password", - "database": "neo4j" -} -``` - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| uri | string | 是 | Neo4j 连接地址,如 bolt://localhost:7687 | -| username | string | 是 | 用户名 | -| password | string | 是 | 密码 | -| database | string | 否 | 数据库名(默认 neo4j) | - -### 返回参数 -```json -{ - "success": true, - "graphs": { - "labels": [ - {"name": "User", "count": 1523}, - {"name": "Order", "count": 856} - ], - "relationshipTypes": [ - {"name": "KNOWS", "count": 2341}, - {"name": "BOUGHT", "count": 5678} - ] - } -} -``` - ---- - -## 2. 修改路由路径 - -### 当前状态 -- `/database/neo4j/nodes` → 需要改为 → `/neo4j/nodes` -- `/database/neo4j/relationships` → 需要改为 → `/neo4j/relationships` - ---- - -## 总结 - -后端需要修改以下内容: - -1. **新增** `/neo4j/graphs` 接口 -2. **修改** `/database/neo4j/nodes` → `/neo4j/nodes` -3. **修改** `/database/neo4j/relationships` → `/neo4j/relationships` - ---- - -## 附:前端 API 调用示例 - -```javascript -// 获取图谱概览 -fetch('/neo4j/graphs', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - uri: 'bolt://10.10.10.189:7687', - username: 'neo4j', - password: 'neo4j', - database: 'neo4j' - }) -}) - -// 获取节点详情 -fetch('/neo4j/nodes', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - uri: 'bolt://10.10.10.189:7687', - username: 'neo4j', - password: 'neo4j', - label: 'User', - limit: 10 - }) -}) - -// 获取关系详情 -fetch('/neo4j/relationships', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - uri: 'bolt://10.10.10.189:7687', - username: 'neo4j', - password: 'neo4j', - relationship_type: 'KNOWS', - limit: 10 - }) -}) -``` diff --git a/team-require/web/neo4j-check-return-id.md b/team-require/web/neo4j-check-return-id.md deleted file mode 100644 index fab67a6..0000000 --- a/team-require/web/neo4j-check-return-id.md +++ /dev/null @@ -1,99 +0,0 @@ -# Neo4j 连接成功后返回数据库 ID - -## 需求说明 - -当前端 Connect 测试 Neo4j 连接成功后,后端需要返回数据库的 ID,以便前端保存图谱配置。 - ---- - -## 问题 - -当前 `/neo4j/check` 接口返回: -```json -{ - "success": true, - "message": "connection successful", - "version": "5.14.0", - "databases": ["neo4j", "system"] -} -``` - -**没有返回 `databaseId`**,导致后续保存图谱时缺少 `databaseId`。 - ---- - -## 需求内容 - -修改 `/neo4j/check` 接口,在连接成功时: - -1. **检查数据库是否已存在** - 根据 URI(bolt://host:port)、username、database 查询 -2. **如果存在** - 返回已有的 `databaseId` -3. **如果不存在** - 自动创建一条数据库记录,并返回新的 `databaseId` - -### 返回格式 - -```json -{ - "success": true, - "message": "connection successful", - "version": "5.14.0", - "databases": ["neo4j", "system"], - "databaseId": "xxx-xxx-xxx", - "name": "Neo4j-neo4j", - "description": "Neo4j neo4j@10.10.10.189:7687" -} -``` - -| 字段 | 类型 | 说明 | -|------|------|------| -| success | bool | 是否成功 | -| message | string | 消息 | -| version | string | Neo4j 版本 | -| databases | array | 数据库列表 | -| databaseId | string | 数据库记录 ID | -| name | string | 数据库名称 | -| description | string | 数据库描述 | - -### 请求参数 - -当前 `/neo4j/check` 请求: -```json -{ - "db_type": "Neo4j", - "host": "10.10.10.189", - "port": 7687, - "username": "neo4j", - "password": "neo4j", - "database": "neo4j" -} -``` - -后端需要增加 `name` 字段用于数据库名称(可选): -```json -{ - "name": "My Neo4j Database" -} -``` - ---- - -## 涉及文件 - -- `server/internal/service/neo4j_service.go` - - 函数:`Check()` - 第 81-128 行 - - 函数:`ensureNeo4jDatabase()` - 第 131-175 行(已有代码但可能有问题) - -- `server/internal/model/neo4j_info.go` - - 结构体:`Neo4jCheckResponse` - 需要确保 `databaseId` 字段正确返回 - ---- - -## 前端使用 - -前端代码已实现兼容处理: -```javascript -const dbId = result.databaseId || result.id || result.database_id || '' -``` - -所以后端返回 `databaseId`、`id` 或 `database_id` 都可以被正确识别。 - diff --git a/team-require/web/neo4j-graphs.md b/team-require/web/neo4j-graphs.md deleted file mode 100644 index 17427e8..0000000 --- a/team-require/web/neo4j-graphs.md +++ /dev/null @@ -1,196 +0,0 @@ -# 后端需求 - Neo4j 图谱数据获取(完善版) - -## 需求描述 - -Neo4j 连接成功后,需要获取图谱数据供前端可视化展示。前端使用 ECharts 力导向图谱展示科幻风格效果。 - -## Neo4j 图谱核心概念 - -Neo4j 是图数据库,与关系型数据库概念不同: -- **Node(节点)** - 类似于表,但不需要固定结构 -- **Label(标签)** - 类似于表的类型名(如 User, Order) -- **Relationship(关系)** - 节点之间的边 -- **Relationship Type(关系类型)** - 关系的类型(如 KNOWS, OWNS) - -## 后端需要提供的接口 - -### 1. 获取图谱概览数据(核心接口) - -返回所有 Label(标签)和 Relationship Type(关系类型)的统计信息。这是前端图谱可视化的核心数据来源。 - -**接口地址:** `POST /database/check` (复用现有接口,在 db_type 为 Neo4j 时返回图谱数据) - -**请求参数:** -```json -{ - "db_type": "Neo4j", - "uri": "bolt://localhost:7687", - "username": "neo4j", - "password": "password", - "database": "neo4j" -} -``` - -**返回参数:** -```json -{ - "success": true, - "graphs": { - "labels": [ - {"name": "User", "count": 1523}, - {"name": "Order", "count": 856}, - {"name": "Product", "count": 2341}, - {"name": "Category", "count": 45}, - {"name": "Review", "count": 5678} - ], - "relationshipTypes": [ - {"name": "KNOWS", "count": 2341}, - {"name": "BOUGHT", "count": 5678}, - {"name": "BELONGS_TO", "count": 2341}, - {"name": "HAS_REVIEW", "count": 5678}, - {"name": "LOCATED_IN", "count": 1523} - ] - } -} -``` - -### 2. 获取节点详情(可选,用于点击显示) - -点击某个 Label 节点时,获取该类型节点的样本数据用于详情展示。 - -**接口地址:** `POST /database/neo4j/nodes` - -**请求参数:** -```json -{ - "uri": "bolt://localhost:7687", - "username": "neo4j", - "password": "password", - "database": "neo4j", - "label": "User", - "limit": 5 -} -``` - -**返回参数:** -```json -{ - "success": true, - "nodes": [ - {"id": "1", "name": "张三", "email": "zhangsan@example.com", "created_at": "2024-01-01"}, - {"id": "2", "name": "李四", "email": "lisi@example.com", "created_at": "2024-01-02"} - ], - "properties": [ - {"name": "id", "type": "string"}, - {"name": "name", "type": "string"}, - {"name": "email", "type": "string"}, - {"name": "created_at", "type": "datetime"} - ] -} -``` - -### 3. 获取关系详情(可选) - -获取两个节点之间的关系数据。 - -**接口地址:** `POST /database/neo4j/relationships` - -**请求参数:** -```json -{ - "uri": "bolt://localhost:7687", - "username": "neo4j", - "password": "password", - "database": "neo4j", - "relationshipType": "KNOWS", - "limit": 10 -} -``` - -**返回参数:** -```json -{ - "success": true, - "relationships": [ - { - "id": "rel-1", - "source": "1", - "target": "2", - "properties": {"since": "2020-01-01"} - } - ] -} -``` - -## 数据结构说明 - -### graphs.labels[] - 标签列表(前端图谱节点) -| 字段 | 类型 | 说明 | 用途 | -|------|------|------|------| -| name | string | 标签名称(如 User, Order) | 作为图谱节点显示 | -| count | int | 该标签的节点数量 | 计算节点大小 symbolSize | - -### graphs.relationshipTypes[] - 关系类型列表(前端图谱边) -| 字段 | 类型 | 说明 | 用途 | -|------|------|------|------| -| name | string | 关系类型(如 KNOWS, OWNS) | 作为图谱边的标签 | -| count | int | 该关系的数量 | 可能影响边的粗细 | - -### nodes[] - 节点详情 -| 字段 | 类型 | 说明 | -|------|------|------| -| id | string | 节点唯一标识 | -| (其他) | any | 节点的其他属性 | - -### relationships[] - 关系详情 -| 字段 | 类型 | 说明 | -|------|------|------| -| id | string | 关系唯一标识 | -| source | string | 起始节点ID | -| target | string | 目标节点ID | -| properties | object | 关系属性 | - -## 前端图谱展示逻辑 - -前端使用 ECharts 力导向图谱(force-directed graph),展示方式如下: - -1. **节点生成**: - - 根据 `graphs.labels` 数组生成节点 - - `name` 作为节点显示名称 - - `count` 决定节点大小(symbolSize = log2(count+1) * 12) - - 节点颜色按索引分配科幻配色(紫、蓝、绿、橙、粉、青) - - 节点带发光效果(shadowBlur: 20) - -2. **边生成**: - - 根据 `graphs.relationshipTypes` 生成边 - - 边 label 显示关系类型名称 - - 曲线连接(curveness: 0.2) - - 带箭头 - -3. **交互效果**: - - 弹簧物理效果(force layout) - - 节点可拖拽 - - 滚轮缩放 - - hover 相邻节点高亮 - -## 优先级 - -高 - Neo4j 可视化的核心数据 - -## 注意事项 - -1. Neo4j 连接使用官方 Go 驱动:`github.com/neo4j/neo4j-go-driver` -2. 注意处理连接超时和认证失败的情况 -3. 大数据量时需要限制返回数量(limit 参数) -4. **建议返回足够多的关系类型**(建议至少 5-10 个),以便前端生成丰富的图谱连接 -5. 如果关系类型少于节点数,可以创建额外连接让图谱更美观 - -## 前端缓存策略 - -### 方案设计 -- **首次加载**:获取数据并缓存 -- **第二次展示**:直接使用缓存,秒开 -- **刷新按钮**:用户手动点击刷新获取最新数据 - -### 实现说明 -前端会缓存图谱数据,第二次进入时直接展示缓存数据,提升用户体验。同时提供"刷新"按钮供用户手动刷新。 diff --git a/team-require/web/neo4j-support.md b/team-require/web/neo4j-support.md deleted file mode 100644 index ddec242..0000000 --- a/team-require/web/neo4j-support.md +++ /dev/null @@ -1,42 +0,0 @@ -# 后端需求 - 支持 Neo4j 图数据库 - -## 需求描述 - -添加 Neo4j 图数据库类型支持。 - -## Neo4j 连接参数 - -Neo4j 连接需要以下参数: - -| 参数 | 类型 | 必填 | 说明 | 默认值 | -|------|------|------|------|--------| -| uri | string | 是 | 连接地址 | bolt://localhost:7687 | -| username | string | 是 | 用户名 | neo4j | -| password | string | 是 | 密码 | - | -| database | string | 否 | 数据库名 | neo4j(默认数据库) | - -### 连接示例 -- `bolt://localhost:7687` -- `neo4j://localhost:7687` -- `bolt://192.168.1.100:7687` - -## 需要修改的地方 - -### 1. 数据库类型列表 -在前端和后端添加 "Neo4j" 选项 - -### 2. 连接表单 -Neo4j 只需要 3-4 个字段: -- URI(连接地址) -- Username(用户名) -- Password(密码) -- Database(数据库名,可选) - -### 3. 数据库服务 -- `server/internal/service/database_service.go` -- 新增 `connectNeo4j` 方法 -- 新增 `getNeo4jTables` 方法 - -## 优先级 - -中 - 扩展数据库类型支持 diff --git a/team-require/web/sub-tables-edit.md b/team-require/web/sub-tables-edit.md deleted file mode 100644 index 21fad67..0000000 --- a/team-require/web/sub-tables-edit.md +++ /dev/null @@ -1,35 +0,0 @@ -# 后端需求 - 编辑数据库时正确处理 sub_tables - -## 问题描述 - -用户点击 Action 修改数据库,进入 Map Tables 页面后: -1. 初始显示 2 个已选中的表 -2. 用户取消选中 1 个表,只保留 1 个 -3. 点击 Save Mapping 保存 -4. 再次点击 Map Tables 查看时,仍然显示 2 个表,而不是修改后的 1 个 - -## 原因 - -可能的问题: -1. 编辑时没有正确从数据库加载已保存的 sub_tables 数据 -2. Save Mapping 时没有正确更新 sub_tables(可能只是创建新的,没有删除已取消的) - -## 需求 - -### 1. 加载数据库时返回 sub_tables 数据 - -在获取数据库详情时,需要返回该数据库已保存的子表映射信息(包括 parent_table 等),以便前端正确显示已选中的表。 - -### 2. 保存时正确处理子表 - -- 新增的子表:创建新记录 -- 保留的子表:更新记录 -- 取消的子表:删除对应记录 - -或者使用更简单的方案: -- 保存时删除该数据库所有的旧 sub_tables -- 重新创建新的 sub_tables 记录 - -## 状态 - -- [ ] 后端修改待实现 diff --git a/team-require/web/table-count-update-edit.md b/team-require/web/table-count-update-edit.md deleted file mode 100644 index c99edc6..0000000 --- a/team-require/web/table-count-update-edit.md +++ /dev/null @@ -1,22 +0,0 @@ -# 后端需求 - 编辑数据库时更新 table_count - -## 问题描述 - -用户点击 Action 修改数据库,从 2 个子表修改为 1 个子表并保存后,数据库列表中的 Tables 列没有更新为新的数量。 - -## 原因 - -编辑数据库并保存 sub_tables 时,后端没有更新 `table_count` 字段。 - -## 需求 - -在 UpdateDatabaseRequest 处理 `SubTables` 字段时,需要同步更新数据库记录的 `table_count` 字段为当前 sub_tables 的数量。 - -### 修改位置 - -- `server/internal/service/database_service.go` 或 handler -- 在 Update 方法中处理 SubTables 时更新 table_count - -## 状态 - -- [x] 后端修改已完成 diff --git a/team-require/web/table-count-update.md b/team-require/web/table-count-update.md deleted file mode 100644 index b40370f..0000000 --- a/team-require/web/table-count-update.md +++ /dev/null @@ -1,30 +0,0 @@ -# 后端需求 - 保存映射时更新 table_count - -## 问题描述 - -用户在 Database 列表页面看到 Table Mapping 选中 2 个表并保存后,表格的 Tables 列仍然显示 1,没有更新为实际选中的表数量。 - -## 原因 - -保存 Table Mapping 时,后端没有更新数据库的 `table_count` 字段。 - -## 需求 - -在保存子表映射时,需要同时更新数据库的 `table_count` 字段为实际保存的子表数量。 - -### 修改位置 - -- `server/internal/service/database_service.go` 或 handler -- 在处理 `SubTables` 保存逻辑后,更新 `database_info` 表的 `table_count` 字段 - -### 逻辑 - -```go -// 保存 sub_tables 后,更新 table_count -tableCount := len(subTables) -// 更新数据库记录的 table_count 字段 -``` - -## 状态 - -- [x] 后端修改已完成 diff --git a/team-require/web/todo-2026-3-6.md b/team-require/web/todo-2026-3-6.md deleted file mode 100644 index 428b3e3..0000000 --- a/team-require/web/todo-2026-3-6.md +++ /dev/null @@ -1,52 +0,0 @@ -# Web 前端需求 TODO - -## 2026年3月 - -### 2026-03-06 - -- [x] **DDL 获取功能** - 后端需在获取表结构时返回 DDL 语句 ✔ - - 相关文件:`server/internal/service/database_service.go` - - 函数:`getMySQLTables`, `getPostgresTables` - - 详细需求:[ddl-fetch.md](./ddl-fetch.md) - -- [x] **返回结构化 columns 数据** - 后端需返回完整的列信息(column_name, data_type, column_type, is_nullable, default_value, column_key, extra, column_comment)✔ - - 相关文件:`server/internal/service/database_service.go` - - 函数:`getMySQLTables`, `getPostgresTables` - - 详细需求:[columns-api.md](./columns-api.md) - -- [x] **保存和读取字段映射** - 后端需支持保存/读取字段的中文映射名(mapped_name) ✔ - - 相关文件:`server/internal/service/database_service.go`, `server/internal/model/` - - 详细需求:[field-mapping.md](./field-mapping.md) - -- [x] **保存和恢复映射状态** - 第二次进入 Map Tables 时需恢复之前选择的表和字段映射 ✔ - - 相关文件:`server/internal/service/database_service.go`, `server/internal/model/` - - 详细需求:[mapping-state.md](./mapping-state.md) - -- [x] **Neo4j 图谱数据获取** - 前端已完成 ECharts 科幻风格图谱,后端需提供图谱数据接口 ✔ - - 前端:使用 ECharts force-directed graph,力导向弹簧效果,可拖拽,hover 高亮 - - 详细需求:[neo4j-graphs.md](./neo4j-graphs.md), [neo4j-support.md](./neo4j-support.md) - ---- - -- [x] **Neo4j 接口路由修改** - 后端已完成 ✔ - - 新增 `/neo4j/graphs` 接口 - - 修改 `/database/neo4j/nodes` → `/neo4j/nodes` - - 修改 `/database/neo4j/relationships` → `/neo4j/relationships` - - 详细需求:[neo4j-api-requirement.md](./neo4j-api-requirement.md) - ---- - -### 2026-03-07 - -- [x] **Neo4j 图谱保存接口** - 后端已完成 ✔ - - 接口地址:`POST /database/graph/save` - - 详细需求:[neo4j-graph-save.md](./neo4j-graph-save.md) - -- [x] **Neo4j 连接成功后返回 databaseId** - 后端已完成 ✔ - - 问题:Connect 测试连接成功后没有保存数据库记录,导致后续保存图谱时缺少 databaseId - - 解决方案:/neo4j/check 成功时检查数据库是否已存在,不存在则自动创建并返回 databaseId - - 详细需求:[neo4j-check-return-id.md](./neo4j-check-return-id.md) - ---- - -> 需求完成后请完成者打 ✔ \ No newline at end of file diff --git a/team-require/web/todo-2026-3-8.md b/team-require/web/todo-2026-3-8.md deleted file mode 100644 index 7555832..0000000 --- a/team-require/web/todo-2026-3-8.md +++ /dev/null @@ -1,45 +0,0 @@ -# Web 前端需求 TODO - -## 2026年3月 - -### 2026-03-08 - -- [x] **知识库(Knowledge Base)API** - 后端已完成 ✔ - - 创建知识库、获取列表、获取详情、删除 - - 上传文档、删除文档、重新解析 - - 获取文档预览内容 - - 详细需求:[knowledge-base-api.md](./knowledge-base-api.md) - -- [x] **编辑时正确处理 sub_tables** - 后端已完成 ✔ - - 问题:取消选中 1 个表后保存,再次进入仍显示 2 个表 - - 详细需求:[sub-tables-edit.md](./sub-tables-edit.md) - -- [x] **知识库存储配置 (MinIO/S3)** - 后端已完成 ✔ - - 前端已完成:添加 storage_config 参数传递 - - 后端已完成:KnowledgeBase 模型添加 storage_config 字段 - - 上传文件时使用知识库的 storage_config,而非全局配置 - - 详细需求:[knowledge-base-api.md](./knowledge-base-api.md) - -- [x] **文档列表返回 file_url** - 后端已完成 ✔ - - 问题:重新进入知识库后 PDF 无法预览 - - 已确认:API 返回的 file_url 字段有值 - ---- - -### 2026-03-07 - -- [x] **DDL 编辑功能** - 后端已完成 ✔ - - 前端只发送 ddl 字段,不再发送 fields 字段 - - 详细需求:[ddl-edit.md](./ddl-edit.md) - -- [x] **保存映射时更新 table_count** - 后端已完成 ✔ - - 问题:用户保存 2 个子表后,Tables 列仍显示 1 - - 详细需求:[table-count-update.md](./table-count-update.md) - -- [x] **编辑数据库时更新 table_count** - 后端已完成 ✔ - - 问题:用户从 2 个子表修改为 1 个后,Tables 列没有更新 - - 详细需求:[table-count-update-edit.md](./table-count-update-edit.md) - ---- - -> 需求完成后请完成者打 ✔