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

View File

@@ -0,0 +1,438 @@
"""
Agent服务
管理AI代理的配置
"""
import uuid
from datetime import datetime
from typing import List, Dict, Any, Optional
from loguru import logger
from models.agent import Agent
from services.ai_provider_service import AIProviderService
class AgentService:
"""
Agent服务类
负责Agent的CRUD操作
"""
@classmethod
async def create_agent(
cls,
name: str,
role: str,
system_prompt: str,
provider_id: str,
temperature: float = 0.7,
max_tokens: int = 2000,
capabilities: Optional[Dict[str, Any]] = None,
behavior: Optional[Dict[str, Any]] = None,
avatar: Optional[str] = None,
color: str = "#1890ff"
) -> Agent:
"""
创建新的Agent
Args:
name: Agent名称
role: 角色定义
system_prompt: 系统提示词
provider_id: 使用的AI接口ID
temperature: 温度参数
max_tokens: 最大token数
capabilities: 能力配置
behavior: 行为配置
avatar: 头像URL
color: 代表颜色
Returns:
创建的Agent文档
"""
# 验证AI接口存在
provider = await AIProviderService.get_provider(provider_id)
if not provider:
raise ValueError(f"AI接口不存在: {provider_id}")
# 生成唯一ID
agent_id = f"agent-{uuid.uuid4().hex[:8]}"
# 默认能力配置
default_capabilities = {
"memory_enabled": False,
"mcp_tools": [],
"skills": [],
"multimodal": False
}
if capabilities:
default_capabilities.update(capabilities)
# 默认行为配置
default_behavior = {
"speak_threshold": 0.5,
"max_speak_per_round": 2,
"speak_style": "balanced"
}
if behavior:
default_behavior.update(behavior)
# 创建文档
agent = Agent(
agent_id=agent_id,
name=name,
role=role,
system_prompt=system_prompt,
provider_id=provider_id,
temperature=temperature,
max_tokens=max_tokens,
capabilities=default_capabilities,
behavior=default_behavior,
avatar=avatar,
color=color,
enabled=True,
created_at=datetime.utcnow(),
updated_at=datetime.utcnow()
)
await agent.insert()
logger.info(f"创建Agent: {agent_id} ({name})")
return agent
@classmethod
async def get_agent(cls, agent_id: str) -> Optional[Agent]:
"""
获取指定Agent
Args:
agent_id: Agent ID
Returns:
Agent文档或None
"""
return await Agent.find_one(Agent.agent_id == agent_id)
@classmethod
async def get_all_agents(
cls,
enabled_only: bool = False
) -> List[Agent]:
"""
获取所有Agent
Args:
enabled_only: 是否只返回启用的Agent
Returns:
Agent列表
"""
if enabled_only:
return await Agent.find(Agent.enabled == True).to_list()
return await Agent.find_all().to_list()
@classmethod
async def get_agents_by_ids(
cls,
agent_ids: List[str]
) -> List[Agent]:
"""
根据ID列表获取多个Agent
Args:
agent_ids: Agent ID列表
Returns:
Agent列表
"""
return await Agent.find(
{"agent_id": {"$in": agent_ids}}
).to_list()
@classmethod
async def update_agent(
cls,
agent_id: str,
**kwargs
) -> Optional[Agent]:
"""
更新Agent配置
Args:
agent_id: Agent ID
**kwargs: 要更新的字段
Returns:
更新后的Agent或None
"""
agent = await cls.get_agent(agent_id)
if not agent:
return None
# 如果更新了provider_id验证其存在
if "provider_id" in kwargs:
provider = await AIProviderService.get_provider(kwargs["provider_id"])
if not provider:
raise ValueError(f"AI接口不存在: {kwargs['provider_id']}")
# 更新字段
kwargs["updated_at"] = datetime.utcnow()
for key, value in kwargs.items():
if hasattr(agent, key):
setattr(agent, key, value)
await agent.save()
logger.info(f"更新Agent: {agent_id}")
return agent
@classmethod
async def delete_agent(cls, agent_id: str) -> bool:
"""
删除Agent
Args:
agent_id: Agent ID
Returns:
是否删除成功
"""
agent = await cls.get_agent(agent_id)
if not agent:
return False
await agent.delete()
logger.info(f"删除Agent: {agent_id}")
return True
@classmethod
async def test_agent(
cls,
agent_id: str,
test_message: str = "你好,请简单介绍一下你自己。"
) -> Dict[str, Any]:
"""
测试Agent对话
Args:
agent_id: Agent ID
test_message: 测试消息
Returns:
测试结果
"""
agent = await cls.get_agent(agent_id)
if not agent:
return {
"success": False,
"message": f"Agent不存在: {agent_id}"
}
if not agent.enabled:
return {
"success": False,
"message": "Agent已禁用"
}
# 构建消息
messages = [
{"role": "system", "content": agent.system_prompt},
{"role": "user", "content": test_message}
]
# 调用AI接口
response = await AIProviderService.chat(
provider_id=agent.provider_id,
messages=messages,
temperature=agent.temperature,
max_tokens=agent.max_tokens
)
if response.success:
return {
"success": True,
"message": "测试成功",
"response": response.content,
"model": response.model,
"tokens": response.total_tokens,
"latency_ms": response.latency_ms
}
else:
return {
"success": False,
"message": response.error
}
@classmethod
async def duplicate_agent(
cls,
agent_id: str,
new_name: Optional[str] = None
) -> Optional[Agent]:
"""
复制Agent
Args:
agent_id: 源Agent ID
new_name: 新Agent名称
Returns:
新创建的Agent或None
"""
source_agent = await cls.get_agent(agent_id)
if not source_agent:
return None
return await cls.create_agent(
name=new_name or f"{source_agent.name} (副本)",
role=source_agent.role,
system_prompt=source_agent.system_prompt,
provider_id=source_agent.provider_id,
temperature=source_agent.temperature,
max_tokens=source_agent.max_tokens,
capabilities=source_agent.capabilities,
behavior=source_agent.behavior,
avatar=source_agent.avatar,
color=source_agent.color
)
@classmethod
async def generate_system_prompt(
cls,
provider_id: str,
name: str,
role: str,
description: Optional[str] = None
) -> Dict[str, Any]:
"""
使用AI生成Agent系统提示词
Args:
provider_id: AI接口ID
name: Agent名称
role: 角色定位
description: 额外描述(可选)
Returns:
生成结果包含success和生成的prompt
"""
# 验证AI接口存在
provider = await AIProviderService.get_provider(provider_id)
if not provider:
return {
"success": False,
"message": f"AI接口不存在: {provider_id}"
}
# 构建生成提示词的请求
generate_prompt = f"""请为一个AI Agent编写系统提示词system prompt
Agent名称{name}
角色定位:{role}
{f'补充说明:{description}' if description else ''}
要求:
1. 提示词应简洁专业控制在200字以内
2. 明确该Agent的核心职责和专业领域
3. 说明在多Agent讨论中应该关注什么
4. 使用中文编写
5. 不要包含任何问候语或开场白,直接给出提示词内容
请直接输出系统提示词,不要有任何额外的解释或包装。"""
try:
messages = [{"role": "user", "content": generate_prompt}]
response = await AIProviderService.chat(
provider_id=provider_id,
messages=messages,
temperature=0.7,
max_tokens=1000
)
if response.success:
# 清理可能的包装文本
content = response.content.strip()
# 移除可能的markdown代码块标记
if content.startswith("```"):
lines = content.split("\n")
content = "\n".join(lines[1:])
if content.endswith("```"):
content = content[:-3]
content = content.strip()
return {
"success": True,
"prompt": content,
"model": response.model,
"tokens": response.total_tokens
}
else:
return {
"success": False,
"message": response.error or "生成失败"
}
except Exception as e:
logger.error(f"生成系统提示词失败: {e}")
return {
"success": False,
"message": f"生成失败: {str(e)}"
}
# Agent预设模板
AGENT_TEMPLATES = {
"product_manager": {
"name": "产品经理",
"role": "产品规划和需求分析专家",
"system_prompt": """你是一位经验丰富的产品经理,擅长:
- 分析用户需求和痛点
- 制定产品策略和路线图
- 平衡业务目标和用户体验
- 与团队协作推进产品迭代
在讨论中,你需要从产品角度出发,关注用户价值、商业可行性和优先级排序。
请用专业但易懂的语言表达观点。""",
"color": "#1890ff"
},
"developer": {
"name": "开发工程师",
"role": "技术实现和架构设计专家",
"system_prompt": """你是一位资深的软件开发工程师,擅长:
- 系统架构设计
- 代码实现和优化
- 技术方案评估
- 性能和安全考量
在讨论中,你需要从技术角度出发,关注实现可行性、技术债务和最佳实践。
请提供具体的技术建议和潜在风险评估。""",
"color": "#52c41a"
},
"designer": {
"name": "设计师",
"role": "用户体验和界面设计专家",
"system_prompt": """你是一位专业的UI/UX设计师擅长:
- 用户体验设计
- 界面视觉设计
- 交互流程优化
- 设计系统构建
在讨论中,你需要从设计角度出发,关注用户体验、视觉美感和交互流畅性。
请提供设计建议并考虑可用性和一致性。""",
"color": "#eb2f96"
},
"moderator": {
"name": "主持人",
"role": "讨论主持和共识判断专家",
"system_prompt": """你是讨论的主持人,负责:
- 引导讨论方向
- 总结各方观点
- 判断是否达成共识
- 提炼行动要点
在讨论中,你需要保持中立,促进有效沟通,并在适当时机总结讨论成果。
当各方观点趋于一致时,请明确指出并总结共识内容。""",
"color": "#722ed1"
}
}