""" Seed Projects and Signals 初始化示例项目和信号数据(新模型:BigInteger id) 含 SSTC 宪章:Pixelle-Video 项目关联宪章与任务 """ import asyncio from datetime import datetime from typing import Optional from sqlalchemy import func, select, or_ from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import sessionmaker from app.models import Signal, Project, ProjectSignalLink, TruthNode, Task, User from app.services.auth import AuthService PIXELLE_NAME = "Pixelle-Video 集成" async def seed_pixelle_project(db: Optional[AsyncSession] = None): """ 创建或恢复 Pixelle-Video 示例项目:无项目则全量创建;有项目但无宪章/无信号链接则补全 SSTC 数据。 """ from app.database import engine if db is None: async_session_maker = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False) async with async_session_maker() as session: await _seed_projects(session) else: await _seed_projects(db) async def _ensure_pixelle_sstc_data(session: AsyncSession, pixelle_project: Project) -> bool: """ 若「Pixelle-Video 集成」已存在但无宪章或无项目-信号链接,则补全信号、链接、宪章与任务。返回是否做了变更。 """ import json pid = pixelle_project.id # 是否已有项目-信号链接 link_count = await session.execute( select(func.count()).select_from(ProjectSignalLink).where(ProjectSignalLink.project_id == pid) ) has_links = (link_count.scalar() or 0) > 0 # 是否已有宪章 charter_count = await session.execute( select(func.count()).select_from(TruthNode).where( TruthNode.project_id == pid, TruthNode.node_type == "charter" ) ) has_charters = (charter_count.scalar() or 0) > 0 if has_links and has_charters: return False changed = False pixelle_signals = [] if not has_links: pixelle_signals = [ Signal( source="HackerNews", content="Pixelle-Video: An AI-powered automated short video generation platform with script-to-video automation", impact_score=9.2, priority="critical", processed=True, ), Signal( source="ProductHunt", content="Pixelle-Video launches API for programmatic video content generation", impact_score=8.5, priority="high", processed=True, ), Signal( source="TechCrunch", content="Pixelle-Video raises Series A funding to scale AI video infrastructure", impact_score=7.8, priority="high", processed=True, ), ] for signal in pixelle_signals: signal.strategic_analysis = json.dumps({ "decision_proposal": { "is_strategic": True, "threat_level": "HIGH", "lead_time_days": 14, "impact_score": getattr(signal, "impact_score", 0), "recommendation": "立即集成 Pixelle-Video API 到主平台" }, "competitiveness_radar": { "innovation": 85, "market_potential": 90, "technical_complexity": 75, "resource_intensity": 70 }, "detected_tech_stacks": ["AI/ML", "Video Processing", "REST API"], "related_knowledge_nodes": [], "rag_context_used": 0 }) signal.tasks_generated = json.dumps([ {"task_name": "Integrate Pixelle-Video API", "type": "backend", "estimated_hours": 8.0}, {"task_name": "Design Video Workflow UI", "type": "frontend", "estimated_hours": 12.0}, {"task_name": "Optimize Video Pipeline", "type": "ai_engineer", "estimated_hours": 16.0}, ]) for signal in pixelle_signals: session.add(signal) await session.flush() for i, signal in enumerate(pixelle_signals): link = ProjectSignalLink( project_id=pid, signal_id=signal.id, link_type="related", relevance_score=1.0, ) session.add(link) pixelle_project.signal_count = len(pixelle_signals) changed = True await session.flush() if not has_charters: user_result = await session.execute(select(User).limit(1)) seed_user = user_result.scalar_one_or_none() if not seed_user: seed_user = User( username="boss", email="boss@pmflow.local", password_hash=AuthService.hash_password("boss123"), name="负责人", role="BOSS", status="active", ) session.add(seed_user) await session.flush() if pixelle_signals: signal_ids = [s.id for s in pixelle_signals] else: link_rows = await session.execute( select(ProjectSignalLink.signal_id).where(ProjectSignalLink.project_id == pid) ) signal_ids = [r[0] for r in link_rows.fetchall()] charter = TruthNode( node_type="charter", parent_id=None, project_id=pid, created_by=seed_user.id, title="Pixelle-Video 集成需求宪章", content={ "rationale": "基于 HackerNews/ProductHunt/TechCrunch 信号,决定集成 Pixelle-Video API 到主平台", "signal_ids": signal_ids, "decision": "立即集成 Pixelle-Video API,支持脚本到视频的自动化生成", }, version=1, status="aligned", ) session.add(charter) await session.flush() for idx, task_item in enumerate([ {"title": "Integrate Pixelle-Video API", "priority": "high", "hours": 8.0}, {"title": "Design Video Workflow UI", "priority": "medium", "hours": 12.0}, {"title": "Optimize Video Pipeline", "priority": "medium", "hours": 16.0}, ]): task = Task( truth_node_id=charter.id, project_id=pid, title=task_item["title"], required_skill_tag_ids=[], status="todo", priority=task_item["priority"], estimated_hours=task_item["hours"], ) session.add(task) changed = True print(f"[SSTC] 已为「{PIXELLE_NAME}」恢复宪章 1 个、任务 3 个") return changed async def _seed_projects(session: AsyncSession): import json result = await session.execute( select(Project).where( or_(Project.title == PIXELLE_NAME, Project.name == PIXELLE_NAME) ) ) existing = result.scalar_one_or_none() if existing: restored = await _ensure_pixelle_sstc_data(session, existing) if restored: await session.commit() else: print("示例项目已存在且 SSTC 数据完整,跳过") return pixelle_signals = [ Signal( source="HackerNews", content="Pixelle-Video: An AI-powered automated short video generation platform with script-to-video automation", impact_score=9.2, priority="critical", processed=True, ), Signal( source="ProductHunt", content="Pixelle-Video launches API for programmatic video content generation", impact_score=8.5, priority="high", processed=True, ), Signal( source="TechCrunch", content="Pixelle-Video raises Series A funding to scale AI video infrastructure", impact_score=7.8, priority="high", processed=True, ), ] for signal in pixelle_signals: signal.strategic_analysis = json.dumps({ "decision_proposal": { "is_strategic": True, "threat_level": "HIGH", "lead_time_days": 14, "impact_score": signal.impact_score, "recommendation": "立即集成 Pixelle-Video API 到主平台" }, "competitiveness_radar": { "innovation": 85, "market_potential": 90, "technical_complexity": 75, "resource_intensity": 70 }, "detected_tech_stacks": ["AI/ML", "Video Processing", "REST API"], "related_knowledge_nodes": [], "rag_context_used": 0 }) signal.tasks_generated = json.dumps([ {"task_name": "Integrate Pixelle-Video API", "type": "backend", "estimated_hours": 8.0}, {"task_name": "Design Video Workflow UI", "type": "frontend", "estimated_hours": 12.0}, {"task_name": "Optimize Video Pipeline", "type": "ai_engineer", "estimated_hours": 16.0}, ]) session.add(signal) await session.flush() pixelle_project = Project( name="Pixelle-Video 集成", title="Pixelle-Video 集成", description="集成 Pixelle-Video AI 视频生成平台到主系统", status="active", assigned_role="backend", signal_count=len(pixelle_signals), ) session.add(pixelle_project) await session.flush() for signal in pixelle_signals: link = ProjectSignalLink( project_id=pixelle_project.id, signal_id=signal.id, link_type="related", relevance_score=1.0, ) session.add(link) ai_analyst_project = Project( name="AI 分析引擎优化", title="AI 分析引擎优化", description="优化 LLM 服务性能,实现多模型投票机制和 RAG 检索增强", status="active", assigned_role="ai_engineer", signal_count=1, ) session.add(ai_analyst_project) await session.flush() ai_signal = Signal( source="ArXiv", content="New paper: Multi-Agent LLM Voting System improves accuracy by 23%", impact_score=7.5, priority="medium", processed=True, ) ai_signal.strategic_analysis = json.dumps({ "decision_proposal": { "is_strategic": True, "threat_level": "MEDIUM", "lead_time_days": 30, "impact_score": 7.5, "recommendation": "实现多模型投票机制提升 AI 分析准确性" }, "detected_tech_stacks": ["LLM", "Voting", "Multi-Agent"] }) session.add(ai_signal) await session.flush() ai_link = ProjectSignalLink( project_id=ai_analyst_project.id, signal_id=ai_signal.id, link_type="related", relevance_score=0.9, ) session.add(ai_link) await session.flush() # --- SSTC: 获取或创建默认用户,用于宪章 created_by --- user_result = await session.execute(select(User).limit(1)) seed_user = user_result.scalar_one_or_none() if not seed_user: seed_user = User( username="boss", email="boss@pmflow.local", password_hash=AuthService.hash_password("boss123"), name="负责人", role="BOSS", status="active", ) session.add(seed_user) await session.flush() # --- SSTC: 为 Pixelle-Video 创建宪章(关联信号)--- pixelle_signal_ids = [s.id for s in pixelle_signals] charter = TruthNode( node_type="charter", parent_id=None, project_id=pixelle_project.id, created_by=seed_user.id, title="Pixelle-Video 集成需求宪章", content={ "rationale": "基于 HackerNews/ProductHunt/TechCrunch 信号,决定集成 Pixelle-Video API 到主平台", "signal_ids": pixelle_signal_ids, "decision": "立即集成 Pixelle-Video API,支持脚本到视频的自动化生成", }, version=1, status="aligned", ) session.add(charter) await session.flush() # --- SSTC: 创建任务(绑定到宪章)--- for task_item in [ {"title": "Integrate Pixelle-Video API", "priority": "high", "hours": 8.0}, {"title": "Design Video Workflow UI", "priority": "medium", "hours": 12.0}, {"title": "Optimize Video Pipeline", "priority": "medium", "hours": 16.0}, ]: task = Task( truth_node_id=charter.id, project_id=pixelle_project.id, title=task_item["title"], required_skill_tag_ids=[], status="todo", priority=task_item["priority"], estimated_hours=task_item["hours"], ) session.add(task) await session.commit() print(f"创建示例项目:") print(f" - {pixelle_project.title} ({pixelle_project.assigned_role})") print(f" - {ai_analyst_project.title} ({ai_analyst_project.assigned_role})") print(f"\n关联信号: {len(pixelle_signals) + 1} 条") print(f"[SSTC] Pixelle-Video 宪章 1 个,任务 3 个") async def main(): print("开始初始化示例数据...") from app.database import engine from app.models import Base async with engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) await seed_pixelle_project() print("\n初始化完成!") if __name__ == "__main__": asyncio.run(main())