import os import time import logging from fastapi import FastAPI, HTTPException from pydantic import BaseModel from pipeline import NLPPipeline logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) app = FastAPI( title="ReqGen NLP Service", description="NLP inference service for requirements extraction", version="1.0.0", ) # ── Load pipeline once at startup ────────────────────────────────────────── MODEL_NAME = os.getenv("HF_MODEL_NAME", "deepset/deberta-v3-base-squad2") logger.info(f"Loading NLP pipeline with model: {MODEL_NAME}") nlp_pipeline = NLPPipeline(model_name=MODEL_NAME) logger.info("NLP pipeline ready") # ── Schemas ──────────────────────────────────────────────────────────────── class NLPRequest(BaseModel): text: str domain_context: str | None = None class NLPResponse(BaseModel): text: str model_used: str tokens: list[str] named_entities: list[dict] dependency_parse: list[dict] actors: list[str] goals: list[str] constraints: list[str] requirement_type: str requirement_type_confidence: float extracted_requirements: list[dict] processing_time_ms: int # ── Routes ───────────────────────────────────────────────────────────────── @app.get("/") def root(): return { "service": "ReqGen NLP", "model": MODEL_NAME, "status": "running" } @app.get("/health") def health(): return {"status": "ok", "model": MODEL_NAME} @app.post("/process", response_model=NLPResponse) def process_text(payload: NLPRequest): if not payload.text.strip(): raise HTTPException(status_code=400, detail="Text cannot be empty") start = time.time() try: result = nlp_pipeline.process(payload.text, payload.domain_context) except Exception as e: logger.error(f"Pipeline error: {e}") raise HTTPException(status_code=500, detail=f"NLP processing failed: {str(e)}") result["processing_time_ms"] = int((time.time() - start) * 1000) return result