385 lines
14 KiB
Python
385 lines
14 KiB
Python
"""
|
||
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())
|