sushilideaclan01's picture
refactored the files
d4a4da7
"""Angle × Concept matrix endpoints."""
from fastapi import APIRouter, HTTPException, Depends
from api.schemas import (
MatrixGenerateRequest,
MatrixGenerateResponse,
MatrixBatchRequest,
TestingMatrixResponse,
RefineCustomRequest,
RefineCustomResponse,
)
from services.generator import ad_generator
from services.matrix import matrix_service
from services.auth_dependency import get_current_user
router = APIRouter(tags=["matrix"])
@router.post("/matrix/generate", response_model=MatrixGenerateResponse)
async def generate_with_matrix(
request: MatrixGenerateRequest,
username: str = Depends(get_current_user),
):
"""
Generate ad using the Angle × Concept matrix approach.
Requires authentication. Supports custom angle/concept when key is 'custom'.
"""
try:
return await ad_generator.generate_ad_with_matrix(
niche=request.niche,
angle_key=request.angle_key,
concept_key=request.concept_key,
custom_angle=request.custom_angle,
custom_concept=request.custom_concept,
num_images=request.num_images,
image_model=request.image_model,
username=username,
core_motivator=request.core_motivator,
target_audience=request.target_audience,
offer=request.offer,
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/matrix/testing", response_model=TestingMatrixResponse)
async def generate_testing_matrix(request: MatrixBatchRequest):
"""
Generate a testing matrix (combinations without images).
Strategies: balanced, top_performers, diverse.
"""
try:
combinations = matrix_service.generate_testing_matrix(
niche=request.niche,
angle_count=request.angle_count,
concept_count=request.concept_count,
strategy=request.strategy,
)
summary = matrix_service.get_matrix_summary(combinations)
return {
"niche": request.niche,
"strategy": request.strategy,
"summary": summary,
"combinations": combinations,
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/matrix/angles")
async def list_angles():
"""List all available angles (100 total, 10 categories)."""
from data.angles import ANGLES, get_all_angles
categories = {}
for cat_key, cat_data in ANGLES.items():
categories[cat_key.value] = {
"name": cat_data["name"],
"angle_count": len(cat_data["angles"]),
"angles": [
{"key": a["key"], "name": a["name"], "trigger": a["trigger"], "example": a["example"]}
for a in cat_data["angles"]
],
}
return {"total_angles": len(get_all_angles()), "categories": categories}
@router.get("/matrix/concepts")
async def list_concepts():
"""List all available concepts (100 total, 10 categories)."""
from data.concepts import CONCEPTS, get_all_concepts
categories = {}
for cat_key, cat_data in CONCEPTS.items():
categories[cat_key.value] = {
"name": cat_data["name"],
"concept_count": len(cat_data["concepts"]),
"concepts": [
{"key": c["key"], "name": c["name"], "structure": c["structure"], "visual": c["visual"]}
for c in cat_data["concepts"]
],
}
return {"total_concepts": len(get_all_concepts()), "categories": categories}
@router.get("/matrix/angle/{angle_key}")
async def get_angle(angle_key: str):
"""Get details for a specific angle by key."""
from data.angles import get_angle_by_key
angle = get_angle_by_key(angle_key)
if not angle:
raise HTTPException(status_code=404, detail=f"Angle '{angle_key}' not found")
return angle
@router.get("/matrix/concept/{concept_key}")
async def get_concept(concept_key: str):
"""Get details for a specific concept by key."""
from data.concepts import get_concept_by_key
concept = get_concept_by_key(concept_key)
if not concept:
raise HTTPException(status_code=404, detail=f"Concept '{concept_key}' not found")
return concept
@router.get("/matrix/compatible/{angle_key}")
async def get_compatible_concepts(angle_key: str):
"""Get concepts compatible with a specific angle."""
from data.angles import get_angle_by_key
from data.concepts import get_compatible_concepts as get_compatible
angle = get_angle_by_key(angle_key)
if not angle:
raise HTTPException(status_code=404, detail=f"Angle '{angle_key}' not found")
compatible = get_compatible(angle.get("trigger", ""))
return {
"angle": {"key": angle["key"], "name": angle["name"], "trigger": angle["trigger"]},
"compatible_concepts": [
{"key": c["key"], "name": c["name"], "structure": c["structure"]}
for c in compatible
],
}
@router.post("/matrix/refine-custom", response_model=RefineCustomResponse)
async def refine_custom_angle_or_concept(request: RefineCustomRequest):
"""Refine a custom angle or concept text using AI."""
try:
result = await ad_generator.refine_custom_angle_or_concept(
text=request.text,
type=request.type,
niche=request.niche,
goal=request.goal,
)
return {"status": "success", "type": request.type, "refined": result}
except Exception as e:
return {"status": "error", "type": request.type, "refined": None, "error": str(e)}