PragmaLens-AI / main.py
jamalinu's picture
Update main.py
70934e3 verified
Raw
History Blame Contribute Delete
3.66 kB
import os
import json
import logging
import io
from typing import Dict, Any
from fastapi import FastAPI, UploadFile, File, HTTPException, Depends
from fastapi.responses import FileResponse, JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field, field_validator
from groq import Groq
import pdfplumber
# ==================== CONFIGURACIÓN ====================
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
app = FastAPI(title="PragmaLens API", version="1.1.0")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
# ==================== DEPENDENCIAS ====================
def get_groq_client():
api_key = os.getenv("GROQ_API_KEY")
if not api_key:
raise HTTPException(status_code=500, detail="GROQ_API_KEY no configurada")
return Groq(api_key=api_key)
# ==================== MODELOS ====================
class TextInput(BaseModel):
text: str = Field(..., min_length=1)
@field_validator('text')
@classmethod
def text_not_empty(cls, v: str) -> str:
if not v.strip():
raise ValueError('El texto no puede estar vacío')
return v.strip()
# ==================== LÓGICA DE ANÁLISIS ====================
def run_audit(text: str, client: Groq) -> Dict[str, str]:
# El prompt instruye a la IA para detectar el idioma automáticamente y responder en el mismo
system_prompt = (
"You are an expert polyglot discourse analyst. "
"1. Automatically detect the language of the input text. "
"2. Analyze for: Grice's Maxims, Pragmatic markers, Ambiguity, and Logical fallacies. "
"3. Respond in the same language as the input text. "
"Return ONLY a raw JSON object with these exact keys: "
"'grice_maxims', 'pragmatics', 'ambiguity', 'fallacies'. "
"Each value must be a single continuous string."
)
try:
response = client.chat.completions.create(
model="llama-3.3-70b-versatile",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": text[:4000]}
],
response_format={"type": "json_object"},
temperature=0.1
)
return json.loads(response.choices[0].message.content)
except Exception as e:
logger.error(f"Error en auditoría: {e}")
return {
"grice_maxims": "Error processing",
"pragmatics": "Error processing",
"ambiguity": "Error processing",
"fallacies": "Error processing"
}
# ==================== ENDPOINTS ====================
@app.get("/")
async def root():
return FileResponse("index.html")
@app.post("/analyze")
async def analyze(payload: TextInput, client: Groq = Depends(get_groq_client)):
return run_audit(payload.text, client)
@app.post("/analyze_pdf")
async def analyze_pdf(file: UploadFile = File(...), client: Groq = Depends(get_groq_client)):
if not file.filename.lower().endswith('.pdf'):
raise HTTPException(status_code=400, detail="Solo se aceptan archivos PDF")
content = await file.read()
with pdfplumber.open(io.BytesIO(content)) as pdf:
# Extraemos hasta 10 páginas para optimizar tokens
text = "\n".join([p.extract_text() or "" for p in pdf.pages[:10]])
if not text.strip():
raise HTTPException(status_code=400, detail="No se pudo extraer texto del PDF")
return run_audit(text, client)