Primera versión del backend

This commit is contained in:
Mireya Cueto Garrido
2026-05-13 13:43:32 +02:00
parent 7d893c98fa
commit ebc3631cfd
32 changed files with 1264 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
"""API package."""
+17
View File
@@ -0,0 +1,17 @@
from typing import Annotated
from fastapi import Depends
from sqlalchemy.orm import Session
from app.core.config import Settings, get_settings
from app.db.session import get_db
from app.services.exam_service import ExamService
from app.services.llm import LLMClient
def get_exam_service(db: Annotated[Session, Depends(get_db)]) -> ExamService:
return ExamService(db)
def get_llm_client(settings: Annotated[Settings, Depends(get_settings)]) -> LLMClient:
return LLMClient(settings)
+1
View File
@@ -0,0 +1 @@
"""API route package."""
+37
View File
@@ -0,0 +1,37 @@
import uuid
from typing import Annotated
from fastapi import APIRouter, Depends, Response
from app.api.dependencies import get_exam_service
from app.models.exam import ExportFormat
from app.services.exam_service import ExamService
router = APIRouter(prefix="/export", tags=["exports"])
@router.get("/xml/{template_id}")
def export_xml(
template_id: uuid.UUID,
service: Annotated[ExamService, Depends(get_exam_service)],
) -> Response:
export = service.export(template_id, ExportFormat.XML)
return Response(content=export.content, media_type="application/xml")
@router.get("/txt/{template_id}")
def export_txt(
template_id: uuid.UUID,
service: Annotated[ExamService, Depends(get_exam_service)],
) -> Response:
export = service.export(template_id, ExportFormat.TXT)
return Response(content=export.content, media_type="text/plain; charset=utf-8")
@router.get("/json/{template_id}")
def export_json(
template_id: uuid.UUID,
service: Annotated[ExamService, Depends(get_exam_service)],
) -> Response:
export = service.export(template_id, ExportFormat.JSON)
return Response(content=export.content, media_type="application/json")
+43
View File
@@ -0,0 +1,43 @@
import uuid
from typing import Annotated
from fastapi import APIRouter, Depends
from app.api.dependencies import get_exam_service, get_llm_client
from app.schemas.exam import (
BuildPromptRequest,
GenerateExamRequest,
ParsedQuestionsResponse,
ParseRequest,
PromptResponse,
)
from app.services.exam_service import ExamService
from app.services.llm import LLMClient
router = APIRouter(tags=["generation"])
@router.post("/prompts/{template_id}", response_model=PromptResponse)
def build_prompt(
template_id: uuid.UUID,
payload: BuildPromptRequest,
service: Annotated[ExamService, Depends(get_exam_service)],
) -> PromptResponse:
return service.build_prompt(template_id, payload.topic_prompt)
@router.post("/generate", response_model=ParsedQuestionsResponse)
async def generate_exam(
payload: GenerateExamRequest,
service: Annotated[ExamService, Depends(get_exam_service)],
llm_client: Annotated[LLMClient, Depends(get_llm_client)],
) -> ParsedQuestionsResponse:
return await service.generate_with_llm(payload.template_id, payload.topic_prompt, llm_client)
@router.post("/parse", response_model=ParsedQuestionsResponse)
def parse_ai_output(
payload: ParseRequest,
service: Annotated[ExamService, Depends(get_exam_service)],
) -> ParsedQuestionsResponse:
return service.parse_and_persist(payload)
+8
View File
@@ -0,0 +1,8 @@
from fastapi import APIRouter
router = APIRouter(tags=["health"])
@router.get("/health")
def health_check() -> dict[str, str]:
return {"status": "ok"}
+31
View File
@@ -0,0 +1,31 @@
import uuid
from typing import Annotated
from fastapi import APIRouter, Depends, status
from app.api.dependencies import get_exam_service
from app.schemas.exam import ExamTemplateCreate, ExamTemplateRead
from app.services.exam_service import ExamService
router = APIRouter(prefix="/templates", tags=["templates"])
@router.post("", response_model=ExamTemplateRead, status_code=status.HTTP_201_CREATED)
def create_template(
payload: ExamTemplateCreate,
service: Annotated[ExamService, Depends(get_exam_service)],
) -> ExamTemplateRead:
return service.create_template(payload)
@router.get("", response_model=list[ExamTemplateRead])
def list_templates(service: Annotated[ExamService, Depends(get_exam_service)]) -> list[ExamTemplateRead]:
return service.list_templates()
@router.get("/{template_id}", response_model=ExamTemplateRead)
def get_template(
template_id: uuid.UUID,
service: Annotated[ExamService, Depends(get_exam_service)],
) -> ExamTemplateRead:
return service.get_template(template_id)