""" 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" } }