feat: AI聊天室多Agent协作讨论平台

- 实现Agent管理,支持AI辅助生成系统提示词
- 支持多个AI提供商(OpenRouter、智谱、MiniMax等)
- 实现聊天室和讨论引擎
- WebSocket实时消息推送
- 前端使用React + Ant Design
- 后端使用FastAPI + MongoDB

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Claude Code
2026-02-03 19:20:02 +08:00
commit edbddf855d
76 changed files with 14681 additions and 0 deletions

314
backend/routers/agents.py Normal file
View File

@@ -0,0 +1,314 @@
"""
Agent管理路由
"""
from typing import List, Optional, Dict, Any
from fastapi import APIRouter, HTTPException, status
from pydantic import BaseModel, Field
from loguru import logger
from services.agent_service import AgentService, AGENT_TEMPLATES
router = APIRouter()
# ============ 请求/响应模型 ============
class CapabilitiesModel(BaseModel):
"""能力配置模型"""
memory_enabled: bool = False
mcp_tools: List[str] = []
skills: List[str] = []
multimodal: bool = False
class BehaviorModel(BaseModel):
"""行为配置模型"""
speak_threshold: float = 0.5
max_speak_per_round: int = 2
speak_style: str = "balanced"
class AgentCreateRequest(BaseModel):
"""创建Agent请求"""
name: str = Field(..., description="Agent名称")
role: str = Field(..., description="角色定义")
system_prompt: str = Field(..., description="系统提示词")
provider_id: str = Field(..., description="使用的AI接口ID")
temperature: float = Field(default=0.7, ge=0, le=2, description="温度参数")
max_tokens: int = Field(default=2000, gt=0, description="最大token数")
capabilities: Optional[CapabilitiesModel] = None
behavior: Optional[BehaviorModel] = None
avatar: Optional[str] = None
color: str = "#1890ff"
class Config:
json_schema_extra = {
"example": {
"name": "产品经理",
"role": "产品规划和需求分析专家",
"system_prompt": "你是一位经验丰富的产品经理...",
"provider_id": "openrouter-abc123",
"temperature": 0.7,
"max_tokens": 2000
}
}
class AgentUpdateRequest(BaseModel):
"""更新Agent请求"""
name: Optional[str] = None
role: Optional[str] = None
system_prompt: Optional[str] = None
provider_id: Optional[str] = None
temperature: Optional[float] = Field(default=None, ge=0, le=2)
max_tokens: Optional[int] = Field(default=None, gt=0)
capabilities: Optional[CapabilitiesModel] = None
behavior: Optional[BehaviorModel] = None
avatar: Optional[str] = None
color: Optional[str] = None
enabled: Optional[bool] = None
class AgentResponse(BaseModel):
"""Agent响应"""
agent_id: str
name: str
role: str
system_prompt: str
provider_id: str
temperature: float
max_tokens: int
capabilities: Dict[str, Any]
behavior: Dict[str, Any]
avatar: Optional[str]
color: str
enabled: bool
created_at: str
updated_at: str
class AgentTestRequest(BaseModel):
"""Agent测试请求"""
message: str = "你好,请简单介绍一下你自己。"
class AgentTestResponse(BaseModel):
"""Agent测试响应"""
success: bool
message: str
response: Optional[str] = None
model: Optional[str] = None
tokens: Optional[int] = None
latency_ms: Optional[float] = None
class TemplateResponse(BaseModel):
"""模板响应"""
template_id: str
name: str
role: str
system_prompt: str
color: str
class GeneratePromptRequest(BaseModel):
"""生成提示词请求"""
provider_id: str = Field(..., description="使用的AI接口ID")
name: str = Field(..., description="Agent名称")
role: str = Field(..., description="角色定位")
description: Optional[str] = Field(None, description="额外描述(可选)")
class GeneratePromptResponse(BaseModel):
"""生成提示词响应"""
success: bool
message: Optional[str] = None
prompt: Optional[str] = None
model: Optional[str] = None
tokens: Optional[int] = None
# ============ 路由处理 ============
@router.post("", response_model=AgentResponse, status_code=status.HTTP_201_CREATED)
async def create_agent(request: AgentCreateRequest):
"""
创建新的Agent
"""
try:
agent = await AgentService.create_agent(
name=request.name,
role=request.role,
system_prompt=request.system_prompt,
provider_id=request.provider_id,
temperature=request.temperature,
max_tokens=request.max_tokens,
capabilities=request.capabilities.dict() if request.capabilities else None,
behavior=request.behavior.dict() if request.behavior else None,
avatar=request.avatar,
color=request.color
)
return _to_response(agent)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
logger.error(f"创建Agent失败: {e}")
raise HTTPException(status_code=500, detail="创建失败")
@router.get("", response_model=List[AgentResponse])
async def list_agents(enabled_only: bool = False):
"""
获取所有Agent
"""
agents = await AgentService.get_all_agents(enabled_only)
return [_to_response(a) for a in agents]
@router.get("/templates", response_model=List[TemplateResponse])
async def list_templates():
"""
获取Agent预设模板
"""
return [
TemplateResponse(
template_id=tid,
name=t["name"],
role=t["role"],
system_prompt=t["system_prompt"],
color=t["color"]
)
for tid, t in AGENT_TEMPLATES.items()
]
@router.post("/generate-prompt", response_model=GeneratePromptResponse)
async def generate_prompt(request: GeneratePromptRequest):
"""
使用AI生成Agent系统提示词
"""
result = await AgentService.generate_system_prompt(
provider_id=request.provider_id,
name=request.name,
role=request.role,
description=request.description
)
return GeneratePromptResponse(**result)
@router.get("/{agent_id}", response_model=AgentResponse)
async def get_agent(agent_id: str):
"""
获取指定Agent
"""
agent = await AgentService.get_agent(agent_id)
if not agent:
raise HTTPException(status_code=404, detail="Agent不存在")
return _to_response(agent)
@router.put("/{agent_id}", response_model=AgentResponse)
async def update_agent(agent_id: str, request: AgentUpdateRequest):
"""
更新Agent配置
"""
update_data = request.dict(exclude_unset=True)
# 转换嵌套模型
if "capabilities" in update_data and update_data["capabilities"]:
if hasattr(update_data["capabilities"], "dict"):
update_data["capabilities"] = update_data["capabilities"].dict()
if "behavior" in update_data and update_data["behavior"]:
if hasattr(update_data["behavior"], "dict"):
update_data["behavior"] = update_data["behavior"].dict()
try:
agent = await AgentService.update_agent(agent_id, **update_data)
if not agent:
raise HTTPException(status_code=404, detail="Agent不存在")
return _to_response(agent)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
@router.delete("/{agent_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_agent(agent_id: str):
"""
删除Agent
"""
success = await AgentService.delete_agent(agent_id)
if not success:
raise HTTPException(status_code=404, detail="Agent不存在")
@router.post("/{agent_id}/test", response_model=AgentTestResponse)
async def test_agent(agent_id: str, request: AgentTestRequest = None):
"""
测试Agent对话
"""
message = request.message if request else "你好,请简单介绍一下你自己。"
result = await AgentService.test_agent(agent_id, message)
return AgentTestResponse(**result)
@router.post("/{agent_id}/duplicate", response_model=AgentResponse)
async def duplicate_agent(agent_id: str, new_name: Optional[str] = None):
"""
复制Agent
"""
agent = await AgentService.duplicate_agent(agent_id, new_name)
if not agent:
raise HTTPException(status_code=404, detail="源Agent不存在")
return _to_response(agent)
@router.post("/from-template/{template_id}", response_model=AgentResponse)
async def create_from_template(template_id: str, provider_id: str):
"""
从模板创建Agent
"""
if template_id not in AGENT_TEMPLATES:
raise HTTPException(status_code=404, detail="模板不存在")
template = AGENT_TEMPLATES[template_id]
try:
agent = await AgentService.create_agent(
name=template["name"],
role=template["role"],
system_prompt=template["system_prompt"],
provider_id=provider_id,
color=template["color"]
)
return _to_response(agent)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
# ============ 辅助函数 ============
def _to_response(agent) -> AgentResponse:
"""
转换为响应模型
"""
return AgentResponse(
agent_id=agent.agent_id,
name=agent.name,
role=agent.role,
system_prompt=agent.system_prompt,
provider_id=agent.provider_id,
temperature=agent.temperature,
max_tokens=agent.max_tokens,
capabilities=agent.capabilities,
behavior=agent.behavior,
avatar=agent.avatar,
color=agent.color,
enabled=agent.enabled,
created_at=agent.created_at.isoformat(),
updated_at=agent.updated_at.isoformat()
)