474 lines
14 KiB
Python
474 lines
14 KiB
Python
"""
|
||
Cognitive Conflict Detection & Resolution Service - 认知冲突检测与解决服务
|
||
|
||
核心功能:
|
||
1. 自动检测团队隐性认知差异
|
||
2. 识别定义不一致(如"留存"vs"DAU")
|
||
3. 检测目标冲突(产品说X,开发实现Y)
|
||
4. 主动推送对齐提醒
|
||
5. 异步 1v1 认知对齐
|
||
"""
|
||
import asyncio
|
||
import json
|
||
from datetime import datetime, timedelta, timezone
|
||
from typing import Any, Dict, List, Optional
|
||
from sqlalchemy.ext.asyncio import AsyncSession
|
||
from sqlalchemy.future import select
|
||
from sqlalchemy import text
|
||
|
||
from ..models import (
|
||
User, Project, TruthNode, Task,
|
||
CognitiveConflict, ProjectDomain
|
||
)
|
||
from .llm import LLMService
|
||
|
||
|
||
class CognitiveConflictService:
|
||
"""认知冲突检测与解决服务"""
|
||
|
||
def __init__(self, db: AsyncSession):
|
||
self.db = db
|
||
self.llm = LLMService()
|
||
|
||
async def detect_charter_conflicts(
|
||
self,
|
||
project_id: int,
|
||
tenant_id: int = 1
|
||
) -> List[Dict[str, Any]]:
|
||
"""
|
||
检测项目宪章中的潜在冲突
|
||
|
||
扫描:
|
||
1. 宪章中的成功指标定义是否清晰
|
||
2. 是否有模糊的目标描述
|
||
3. 是否有相互冲突的约束
|
||
"""
|
||
# 获取项目宪章
|
||
result = await self.db.execute(
|
||
select(TruthNode).where(
|
||
TruthNode.project_id == project_id,
|
||
TruthNode.node_type == 'charter',
|
||
TruthNode.tenant_id == tenant_id
|
||
)
|
||
)
|
||
charter = result.scalar_one_or_none()
|
||
|
||
if not charter:
|
||
return []
|
||
|
||
# AI 分析宪章内容
|
||
conflicts = await self._analyze_charter_for_conflicts(
|
||
charter.content,
|
||
tenant_id=tenant_id,
|
||
)
|
||
|
||
# 保存检测到的冲突
|
||
for conflict_data in conflicts:
|
||
await self._create_conflict_record(
|
||
truth_node_id=charter.id,
|
||
conflict_type=conflict_data['type'],
|
||
description=conflict_data['description'],
|
||
severity=conflict_data['severity'],
|
||
suggested_resolution=conflict_data['suggested_resolution'],
|
||
tenant_id=tenant_id
|
||
)
|
||
|
||
return conflicts
|
||
|
||
async def detect_task_charter_mismatch(
|
||
self,
|
||
task: Task,
|
||
charter_content: str,
|
||
tenant_id: int = 1
|
||
) -> Optional[Dict[str, Any]]:
|
||
"""
|
||
检测任务与宪章的一致性
|
||
|
||
检查:
|
||
1. 任务描述是否与宪章目标一致
|
||
2. 技术选型是否符合约束
|
||
3. 是否偏离项目方向
|
||
"""
|
||
prompt = f"""检查以下任务是否符合项目宪章:
|
||
|
||
宪章内容:
|
||
{charter_content}
|
||
|
||
任务信息:
|
||
标题:{task.title}
|
||
描述:{task.description}
|
||
优先级:{task.priority}
|
||
预计工时:{task.estimated_hours} 小时
|
||
|
||
请判断:
|
||
1. 任务是否与宪章目标一致?
|
||
2. 是否有潜在的偏离?
|
||
3. 是否存在隐性冲突?
|
||
|
||
以 JSON 格式返回:
|
||
{{
|
||
"is_aligned": boolean,
|
||
"conflict_type": "目标不一致/技术约束冲突/优先级错配",
|
||
"description": "冲突描述",
|
||
"severity": "high/medium/low",
|
||
"suggestion": "建议调整"
|
||
}}
|
||
|
||
如果任务与宪章一致,is_aligned 设为 true,conflict_type 为 null。"""
|
||
|
||
try:
|
||
response = await self.llm.generate(
|
||
prompt,
|
||
db=self.db,
|
||
tenant_id=tenant_id,
|
||
project_id=task.project_id if getattr(task, "project_id", None) is not None else None,
|
||
)
|
||
response = response.strip()
|
||
if response.startswith('```'):
|
||
response = response.split('```')[1]
|
||
if response.startswith('json'):
|
||
response = response[4:]
|
||
result = json.loads(response.strip())
|
||
|
||
if not result.get('is_aligned', True):
|
||
# 创建冲突记录
|
||
await self._create_conflict_record(
|
||
truth_node_id=task.truth_node_id,
|
||
conflict_type=result.get('conflict_type', 'unknown'),
|
||
description=result.get('description', ''),
|
||
severity=result.get('severity', 'medium'),
|
||
suggested_resolution=result.get('suggestion', ''),
|
||
related_task_id=task.id,
|
||
tenant_id=tenant_id
|
||
)
|
||
return result
|
||
|
||
return None
|
||
|
||
except Exception as e:
|
||
print(f"[CognitiveConflict] Task mismatch detection failed: {e}")
|
||
return None
|
||
|
||
async def detect_user_definition_conflicts(
|
||
self,
|
||
project_id: int,
|
||
tenant_id: int = 1
|
||
) -> List[Dict[str, Any]]:
|
||
"""
|
||
检测用户定义冲突
|
||
|
||
例如:
|
||
- 产品在宪章中写"用户留存提升10%"
|
||
- 开发在实现"DAU提升10%"
|
||
- 双方都没有争论,但目标不一致
|
||
"""
|
||
# 获取项目的所有宪章和任务
|
||
charters_result = await self.db.execute(
|
||
select(TruthNode).where(
|
||
TruthNode.project_id == project_id,
|
||
TruthNode.node_type == 'charter',
|
||
TruthNode.tenant_id == tenant_id
|
||
)
|
||
)
|
||
charters = charters_result.scalars().all()
|
||
|
||
tasks_result = await self.db.execute(
|
||
select(Task).where(
|
||
Task.project_id == project_id,
|
||
Task.tenant_id == tenant_id
|
||
)
|
||
)
|
||
tasks = tasks_result.scalars().all()
|
||
|
||
# 构建所有定义的上下文
|
||
definitions = []
|
||
|
||
for charter in charters:
|
||
definitions.append({
|
||
'source_type': 'charter',
|
||
'source_id': charter.id,
|
||
'content': charter.content
|
||
})
|
||
|
||
for task in tasks:
|
||
definitions.append({
|
||
'source_type': 'task',
|
||
'source_id': task.id,
|
||
'content': f"{task.title}: {task.description}"
|
||
})
|
||
|
||
if not definitions:
|
||
return []
|
||
|
||
# AI 检测定义冲突
|
||
prompt = f"""分析以下项目定义中是否存在隐性认知冲突:
|
||
|
||
{json.dumps(definitions, ensure_ascii=False, indent=2)}
|
||
|
||
请查找:
|
||
1. 相同概念的不同表述(如"留存"vs"DAU")
|
||
2. 相矛盾的目标(如"降低成本"vs"增加功能")
|
||
3. 不一致的指标定义
|
||
|
||
以 JSON 格式返回:
|
||
[
|
||
{{
|
||
"conflict_type": "定义不一致",
|
||
"description": "具体描述冲突",
|
||
"involved_sources": ["charter:1", "task:2"],
|
||
"severity": "high/medium/low",
|
||
"suggested_alignment": "建议的对齐方案"
|
||
}}
|
||
]
|
||
|
||
如果没有发现冲突,返回空数组。"""
|
||
|
||
try:
|
||
response = await self.llm.generate(
|
||
prompt,
|
||
db=self.db,
|
||
tenant_id=tenant_id,
|
||
project_id=project_id,
|
||
)
|
||
response = response.strip()
|
||
if response.startswith('```'):
|
||
response = response.split('```')[1]
|
||
if response.startswith('json'):
|
||
response = response[4:]
|
||
conflicts = json.loads(response.strip())
|
||
|
||
# 保存检测到的冲突
|
||
for conflict in conflicts:
|
||
await self._create_conflict_record(
|
||
truth_node_id=int(conflict['involved_sources'][0].split(':')[1]),
|
||
conflict_type=conflict['conflict_type'],
|
||
description=conflict['description'],
|
||
severity=conflict['severity'],
|
||
suggested_resolution=conflict.get('suggested_alignment', ''),
|
||
tenant_id=tenant_id
|
||
)
|
||
|
||
return conflicts
|
||
|
||
except Exception as e:
|
||
print(f"[CognitiveConflict] Definition conflict detection failed: {e}")
|
||
return []
|
||
|
||
async def propose_alignment_resolution(
|
||
self,
|
||
conflict_id: int,
|
||
tenant_id: int = 1
|
||
) -> Dict[str, Any]:
|
||
"""
|
||
提议认知冲突解决方案
|
||
|
||
为冲突双方生成对齐方案:
|
||
1. 分析冲突根因
|
||
2. 提出妥协方案
|
||
3. 生成可执行的对齐计划
|
||
"""
|
||
# 获取冲突记录
|
||
result = await self.db.execute(
|
||
select(CognitiveConflict).where(
|
||
CognitiveConflict.id == conflict_id,
|
||
CognitiveConflict.tenant_id == tenant_id
|
||
)
|
||
)
|
||
conflict = result.scalar_one_or_none()
|
||
|
||
if not conflict:
|
||
raise ValueError(f"Conflict {conflict_id} not found")
|
||
|
||
# AI 生成解决方案
|
||
prompt = f"""为以下认知冲突提供解决方案:
|
||
|
||
冲突类型:{conflict.conflict_type}
|
||
描述:{conflict.description}
|
||
|
||
请提供:
|
||
1. 冲突根因分析
|
||
2. 双方都能接受的妥协方案
|
||
3. 具体的对齐步骤
|
||
|
||
以 JSON 格式返回:
|
||
{{
|
||
"root_cause": "根本原因",
|
||
"resolution_plan": ["步骤1", "步骤2"],
|
||
"compromise": "妥协方案",
|
||
"expected_outcome": "预期结果"
|
||
}}"""
|
||
|
||
try:
|
||
response = await self.llm.generate(
|
||
prompt,
|
||
db=self.db,
|
||
tenant_id=tenant_id,
|
||
)
|
||
response = response.strip()
|
||
if response.startswith('```'):
|
||
response = response.split('```')[1]
|
||
if response.startswith('json'):
|
||
response = response[4:]
|
||
resolution = json.loads(response.strip())
|
||
|
||
# 更新冲突状态
|
||
conflict.status = 'resolution_proposed'
|
||
conflict.description += f"\n\nAI 建议方案:{resolution.get('compromise', '')}"
|
||
|
||
await self.db.commit()
|
||
|
||
return resolution
|
||
|
||
except Exception as e:
|
||
print(f"[CognitiveConflict] Resolution proposal failed: {e}")
|
||
return {}
|
||
|
||
async def trigger_async_alignment(
|
||
self,
|
||
conflict_id: int,
|
||
user1_id: int,
|
||
user2_id: int,
|
||
tenant_id: int = 1
|
||
) -> Dict[str, Any]:
|
||
"""
|
||
触发异步 1v1 认知对齐
|
||
|
||
为冲突双方创建独立的对齐任务:
|
||
1. 发送对齐邀请
|
||
2. 提供背景信息
|
||
3. 收集双方观点
|
||
4. AI 生成共识方案
|
||
"""
|
||
# 获取用户信息
|
||
result1 = await self.db.execute(
|
||
select(User).where(User.id == user1_id)
|
||
)
|
||
user1 = result1.scalar_one_or_none()
|
||
|
||
result2 = await self.db.execute(
|
||
select(User).where(User.id == user2_id)
|
||
)
|
||
user2 = result2.scalar_one_or_none()
|
||
|
||
if not user1 or not user2:
|
||
raise ValueError("Users not found")
|
||
|
||
# 获取冲突详情
|
||
result = await self.db.execute(
|
||
select(CognitiveConflict).where(
|
||
CognitiveConflict.id == conflict_id,
|
||
CognitiveConflict.tenant_id == tenant_id
|
||
)
|
||
)
|
||
conflict = result.scalar_one_or_none()
|
||
|
||
# TODO: 实际实现需要:
|
||
# 1. 发送飞书消息/邮件通知双方
|
||
# 2. 创建对齐任务
|
||
# 3. 记录对齐过程
|
||
|
||
return {
|
||
'alignment_session_id': f"align_{conflict_id}",
|
||
'user1': user1.username,
|
||
'user2': user2.username,
|
||
'conflict': conflict.conflict_type,
|
||
'status': 'initiated'
|
||
}
|
||
|
||
async def _create_conflict_record(
|
||
self,
|
||
truth_node_id: int,
|
||
conflict_type: str,
|
||
description: str,
|
||
severity: str,
|
||
suggested_resolution: str = "",
|
||
related_task_id: Optional[int] = None,
|
||
tenant_id: int = 1
|
||
):
|
||
"""创建认知冲突记录"""
|
||
from sqlalchemy import text
|
||
next_conflict_id = (await self.db.execute(text("SELECT COALESCE(MAX(id),0)+1 FROM cognitive_conflicts"))).scalar() or 1
|
||
|
||
conflict = CognitiveConflict(
|
||
id=next_conflict_id,
|
||
truth_node_id=truth_node_id,
|
||
conflict_type=conflict_type,
|
||
description=description,
|
||
involved_user_ids=json.dumps([]),
|
||
status='detected',
|
||
tenant_id=tenant_id
|
||
)
|
||
self.db.add(conflict)
|
||
await self.db.commit()
|
||
|
||
async def _analyze_charter_for_conflicts(
|
||
self,
|
||
charter_content: str,
|
||
tenant_id: int,
|
||
) -> List[Dict[str, Any]]:
|
||
"""AI 分析宪章内容中的冲突"""
|
||
prompt = f"""分析以下项目宪章中是否存在潜在冲突或问题:
|
||
|
||
{charter_content}
|
||
|
||
请检查:
|
||
1. 目标是否模糊或相互矛盾?
|
||
2. 约束条件是否现实?
|
||
3. 成功指标是否可衡量?
|
||
4. 是否遗漏重要方面?
|
||
|
||
以 JSON 格式返回:
|
||
[
|
||
{{
|
||
"type": "目标模糊/约束冲突/指标不可测量",
|
||
"description": "具体问题描述",
|
||
"severity": "high/medium/low",
|
||
"suggested_resolution": "建议的改进方案"
|
||
}}
|
||
"""
|
||
|
||
try:
|
||
response = await self.llm.generate(
|
||
prompt,
|
||
db=self.db,
|
||
tenant_id=tenant_id,
|
||
)
|
||
response = response.strip()
|
||
if response.startswith('```'):
|
||
response = response.split('```')[1]
|
||
if response.startswith('json'):
|
||
response = response[4:]
|
||
return json.loads(response.strip())
|
||
except:
|
||
return []
|
||
|
||
async def get_detected_conflicts(
|
||
self,
|
||
tenant_id: int = 1
|
||
) -> List[Dict[str, Any]]:
|
||
"""获取所有检测到的冲突"""
|
||
result = await self.db.execute(
|
||
select(CognitiveConflict).where(
|
||
CognitiveConflict.tenant_id == tenant_id,
|
||
CognitiveConflict.status == 'detected'
|
||
)
|
||
)
|
||
conflicts = result.scalars().all()
|
||
|
||
return [
|
||
{
|
||
'id': str(c.id),
|
||
'type': c.conflict_type,
|
||
'description': c.description,
|
||
'severity': 'medium' if 'high' not in c.description.lower() else 'high',
|
||
'truth_node_id': str(c.truth_node_id)
|
||
}
|
||
for c in conflicts
|
||
]
|
||
|
||
|
||
# 全局服务实例
|
||
def get_cognitive_conflict_service(db: AsyncSession) -> CognitiveConflictService:
|
||
"""获取认知冲突服务实例"""
|
||
return CognitiveConflictService(db)
|