from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel import requests import os # for reading environment variables app = FastAPI() # Enable CORS app.add_middleware( CORSMiddleware, allow_origins=["*"], # Allow all origins, or replace with your frontend URL allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Read OpenRouter API key from environment variable (HF Secret) OPENROUTER_API_KEY = os.environ.get("OPENROUTER_API_KEY") if not OPENROUTER_API_KEY: raise RuntimeError("OPENROUTER_API_KEY environment variable not set!") # Request schema class ExplainRequest(BaseModel): message: str label: str # "Phishing" or "Safe" @app.post("/explain") def explain(req: ExplainRequest): user_message = req.message.strip() label = req.label.strip() if not user_message or not label: raise HTTPException(status_code=400, detail="Missing message or label") # Updated system prompt with bullet-point format and language adaptation system_prompt = ( f"You are a robot that identifies phishing and safe messages. " f"The message was classified as '{label}'. " "Explain why this decision was made and point out any words or patterns that led to it. " "No greetings, introductions, or closing remarks. " "Don't restate the message or its classification. " "Output only the explanation as bullet points. " "Limit each bullet to 1–2 sentences. " "Limit the number of bullets to 3-4 " f"Message:\n\n{user_message}" "Respond using the same language as the message." ) url = "https://openrouter.ai/api/v1/chat/completions" headers = { "Authorization": f"Bearer {OPENROUTER_API_KEY}", "Content-Type": "application/json" } payload = { "model": "arcee-ai/trinity-large-preview:free", "messages": [ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_message} ] } try: response = requests.post(url, headers=headers, json=payload, timeout=20) response.raise_for_status() result = response.json() reply = result.get("choices", [{}])[0].get("message", {}).get("content", "").strip() if not reply: reply = "[No explanation returned]" return {"reply": reply} except requests.RequestException as e: raise HTTPException(status_code=500, detail=f"Error contacting OpenRouter: {e}")