- 实现Agent管理,支持AI辅助生成系统提示词 - 支持多个AI提供商(OpenRouter、智谱、MiniMax等) - 实现聊天室和讨论引擎 - WebSocket实时消息推送 - 前端使用React + Ant Design - 后端使用FastAPI + MongoDB Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
228 lines
6.8 KiB
Python
228 lines
6.8 KiB
Python
"""
|
||
共识管理器
|
||
判断讨论是否达成共识
|
||
"""
|
||
import json
|
||
from typing import Dict, Any, Optional
|
||
from loguru import logger
|
||
|
||
from models.agent import Agent
|
||
from models.chatroom import ChatRoom
|
||
from services.ai_provider_service import AIProviderService
|
||
|
||
|
||
class ConsensusManager:
|
||
"""
|
||
共识管理器
|
||
使用主持人Agent判断讨论共识
|
||
"""
|
||
|
||
# 共识判断提示词模板
|
||
CONSENSUS_PROMPT = """你是讨论的主持人,负责判断讨论是否达成共识。
|
||
|
||
讨论目标:{objective}
|
||
|
||
对话历史:
|
||
{history}
|
||
|
||
请仔细分析对话内容,判断:
|
||
1. 参与者是否对核心问题达成一致意见?
|
||
2. 是否还有重要分歧未解决?
|
||
3. 讨论结果是否足够明确和可执行?
|
||
|
||
请以JSON格式回复(不要包含任何其他文字):
|
||
{{
|
||
"consensus_reached": true或false,
|
||
"confidence": 0到1之间的数字,
|
||
"summary": "讨论结果摘要,简洁概括达成的共识或当前状态",
|
||
"action_items": ["具体的行动项列表"],
|
||
"unresolved_issues": ["未解决的问题列表"],
|
||
"key_decisions": ["关键决策列表"]
|
||
}}
|
||
|
||
注意:
|
||
- consensus_reached为true表示核心问题已有明确结论
|
||
- confidence表示你对共识判断的信心程度
|
||
- 如果讨论仍有争议或不够深入,应该返回false
|
||
- action_items应该是具体可执行的任务
|
||
- 请确保返回有效的JSON格式"""
|
||
|
||
@classmethod
|
||
async def check_consensus(
|
||
cls,
|
||
moderator: Agent,
|
||
context: "DiscussionContext",
|
||
chatroom: ChatRoom
|
||
) -> Dict[str, Any]:
|
||
"""
|
||
检查是否达成共识
|
||
|
||
Args:
|
||
moderator: 主持人Agent
|
||
context: 讨论上下文
|
||
chatroom: 聊天室
|
||
|
||
Returns:
|
||
共识判断结果
|
||
"""
|
||
from services.discussion_engine import DiscussionContext
|
||
|
||
# 构建历史记录
|
||
history_text = ""
|
||
for msg in context.messages:
|
||
if msg.agent_id:
|
||
history_text += f"[{msg.agent_id}]: {msg.content}\n\n"
|
||
else:
|
||
history_text += f"[系统]: {msg.content}\n\n"
|
||
|
||
if not history_text:
|
||
return {
|
||
"consensus_reached": False,
|
||
"confidence": 0,
|
||
"summary": "讨论尚未开始",
|
||
"action_items": [],
|
||
"unresolved_issues": [],
|
||
"key_decisions": []
|
||
}
|
||
|
||
# 构建提示词
|
||
prompt = cls.CONSENSUS_PROMPT.format(
|
||
objective=context.objective,
|
||
history=history_text
|
||
)
|
||
|
||
try:
|
||
# 调用主持人Agent的AI接口
|
||
response = await AIProviderService.chat(
|
||
provider_id=moderator.provider_id,
|
||
messages=[{"role": "user", "content": prompt}],
|
||
temperature=0.3, # 使用较低温度以获得更一致的结果
|
||
max_tokens=1000
|
||
)
|
||
|
||
if not response.success:
|
||
logger.error(f"共识判断失败: {response.error}")
|
||
return cls._default_result("AI接口调用失败")
|
||
|
||
# 解析JSON响应
|
||
content = response.content.strip()
|
||
|
||
# 尝试提取JSON部分
|
||
try:
|
||
# 尝试直接解析
|
||
result = json.loads(content)
|
||
except json.JSONDecodeError:
|
||
# 尝试提取JSON块
|
||
import re
|
||
json_match = re.search(r'\{[\s\S]*\}', content)
|
||
if json_match:
|
||
try:
|
||
result = json.loads(json_match.group())
|
||
except json.JSONDecodeError:
|
||
logger.warning(f"无法解析共识判断结果: {content}")
|
||
return cls._default_result("无法解析AI响应")
|
||
else:
|
||
return cls._default_result("AI响应格式错误")
|
||
|
||
# 验证和规范化结果
|
||
return cls._normalize_result(result)
|
||
|
||
except Exception as e:
|
||
logger.error(f"共识判断异常: {e}")
|
||
return cls._default_result(str(e))
|
||
|
||
@classmethod
|
||
async def generate_summary(
|
||
cls,
|
||
moderator: Agent,
|
||
context: "DiscussionContext"
|
||
) -> str:
|
||
"""
|
||
生成讨论摘要
|
||
|
||
Args:
|
||
moderator: 主持人Agent
|
||
context: 讨论上下文
|
||
|
||
Returns:
|
||
讨论摘要
|
||
"""
|
||
from services.discussion_engine import DiscussionContext
|
||
|
||
# 构建历史记录
|
||
history_text = ""
|
||
for msg in context.messages:
|
||
if msg.agent_id:
|
||
history_text += f"[{msg.agent_id}]: {msg.content}\n\n"
|
||
|
||
prompt = f"""请为以下讨论生成一份简洁的摘要。
|
||
|
||
讨论目标:{context.objective}
|
||
|
||
对话记录:
|
||
{history_text}
|
||
|
||
请提供:
|
||
1. 讨论的主要观点和结论
|
||
2. 参与者的立场和建议
|
||
3. 最终的决策或共识(如果有)
|
||
|
||
摘要应该简洁明了,控制在300字以内。"""
|
||
|
||
try:
|
||
response = await AIProviderService.chat(
|
||
provider_id=moderator.provider_id,
|
||
messages=[{"role": "user", "content": prompt}],
|
||
temperature=0.5,
|
||
max_tokens=500
|
||
)
|
||
|
||
if response.success:
|
||
return response.content.strip()
|
||
else:
|
||
return "无法生成摘要"
|
||
|
||
except Exception as e:
|
||
logger.error(f"生成摘要异常: {e}")
|
||
return "生成摘要时发生错误"
|
||
|
||
@classmethod
|
||
def _default_result(cls, error: str = "") -> Dict[str, Any]:
|
||
"""
|
||
返回默认结果
|
||
|
||
Args:
|
||
error: 错误信息
|
||
|
||
Returns:
|
||
默认共识结果
|
||
"""
|
||
return {
|
||
"consensus_reached": False,
|
||
"confidence": 0,
|
||
"summary": error if error else "共识判断失败",
|
||
"action_items": [],
|
||
"unresolved_issues": [],
|
||
"key_decisions": []
|
||
}
|
||
|
||
@classmethod
|
||
def _normalize_result(cls, result: Dict[str, Any]) -> Dict[str, Any]:
|
||
"""
|
||
规范化共识结果
|
||
|
||
Args:
|
||
result: 原始结果
|
||
|
||
Returns:
|
||
规范化的结果
|
||
"""
|
||
return {
|
||
"consensus_reached": bool(result.get("consensus_reached", False)),
|
||
"confidence": max(0, min(1, float(result.get("confidence", 0)))),
|
||
"summary": str(result.get("summary", "")),
|
||
"action_items": list(result.get("action_items", [])),
|
||
"unresolved_issues": list(result.get("unresolved_issues", [])),
|
||
"key_decisions": list(result.get("key_decisions", []))
|
||
}
|