173 lines
5.2 KiB
Python
173 lines
5.2 KiB
Python
"""Helpers for seed project creation and SSTC recovery."""
|
||
|
||
from __future__ import annotations
|
||
|
||
import json
|
||
from typing import Optional
|
||
|
||
from sqlalchemy import select
|
||
from sqlalchemy.ext.asyncio import AsyncSession
|
||
|
||
from app.models import Signal, Task, TruthNode, User
|
||
from app.services.auth import AuthService
|
||
|
||
PIXELLE_SIGNAL_CONTENTS = [
|
||
(
|
||
"HackerNews",
|
||
"Pixelle-Video: An AI-powered automated short video generation platform with script-to-video automation",
|
||
9.2,
|
||
"critical",
|
||
),
|
||
(
|
||
"ProductHunt",
|
||
"Pixelle-Video launches API for programmatic video content generation",
|
||
8.5,
|
||
"high",
|
||
),
|
||
(
|
||
"TechCrunch",
|
||
"Pixelle-Video raises Series A funding to scale AI video infrastructure",
|
||
7.8,
|
||
"high",
|
||
),
|
||
]
|
||
|
||
PIXELLE_TASK_BLUEPRINT = [
|
||
{"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},
|
||
]
|
||
|
||
|
||
def _build_signal_payload(impact_score: float) -> tuple[str, str]:
|
||
strategic_analysis = json.dumps(
|
||
{
|
||
"decision_proposal": {
|
||
"is_strategic": True,
|
||
"threat_level": "HIGH",
|
||
"lead_time_days": 14,
|
||
"impact_score": 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,
|
||
}
|
||
)
|
||
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},
|
||
]
|
||
)
|
||
return strategic_analysis, tasks_generated
|
||
|
||
|
||
def build_pixelle_signals() -> list[Signal]:
|
||
signals: list[Signal] = []
|
||
for source, content, impact_score, priority in PIXELLE_SIGNAL_CONTENTS:
|
||
signal = Signal(
|
||
source=source,
|
||
content=content,
|
||
impact_score=impact_score,
|
||
priority=priority,
|
||
processed=True,
|
||
)
|
||
strategic_analysis, tasks_generated = _build_signal_payload(impact_score)
|
||
signal.strategic_analysis = strategic_analysis
|
||
signal.tasks_generated = tasks_generated
|
||
signals.append(signal)
|
||
return signals
|
||
|
||
|
||
async def ensure_seed_user(session: AsyncSession) -> User:
|
||
user_result = await session.execute(select(User).limit(1))
|
||
seed_user = user_result.scalar_one_or_none()
|
||
if seed_user:
|
||
return 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()
|
||
return seed_user
|
||
|
||
|
||
async def create_pixelle_charter_and_tasks(
|
||
session: AsyncSession,
|
||
*,
|
||
project_id: int,
|
||
created_by: int,
|
||
signal_ids: list[int],
|
||
) -> TruthNode:
|
||
charter = TruthNode(
|
||
node_type="charter",
|
||
parent_id=None,
|
||
project_id=project_id,
|
||
created_by=created_by,
|
||
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 task_item in PIXELLE_TASK_BLUEPRINT:
|
||
task = Task(
|
||
truth_node_id=charter.id,
|
||
project_id=project_id,
|
||
title=task_item["title"],
|
||
required_skill_tag_ids=[],
|
||
status="todo",
|
||
priority=task_item["priority"],
|
||
estimated_hours=task_item["hours"],
|
||
)
|
||
session.add(task)
|
||
|
||
return charter
|
||
|
||
|
||
def build_ai_signal() -> Signal:
|
||
signal = Signal(
|
||
source="ArXiv",
|
||
content="New paper: Multi-Agent LLM Voting System improves accuracy by 23%",
|
||
impact_score=7.5,
|
||
priority="medium",
|
||
processed=True,
|
||
)
|
||
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"],
|
||
}
|
||
)
|
||
return signal
|
||
|
||
|
||
def pick_signal_ids(signals: Optional[list[Signal]]) -> list[int]:
|
||
return [signal.id for signal in (signals or []) if signal.id is not None]
|