from fastapi import FastAPI from pydantic import BaseModel import requests import os app = FastAPI(title="Forex Sentiment API", version="2.0") # =============================== # Konfigurasi # =============================== HF_ROUTER_URL = "https://router.huggingface.co/hf-inference/models" HF_API_KEY = os.getenv("HF_API_KEY") FINBERT_MODEL = "ProsusAI/finbert" LONGFORMER_MODEL = "Miruzen/LongFormer_Skripsi" # =============================== # Input Schema # =============================== class InputData(BaseModel): title: str | None = None content: str | None = None # =============================== # Helper Functions # =============================== def call_hf_model(model_name: str, text: str): """Kirim teks ke model Hugging Face menggunakan router API baru""" headers = { "Authorization": f"Bearer {HF_API_KEY}", "Content-Type": "application/json", } payload = { "inputs": text, "options": {"wait_for_model": True} } url = f"{HF_ROUTER_URL}/{model_name}" response = requests.post(url, headers=headers, json=payload) if response.status_code != 200: raise Exception( f"HF API error ({response.status_code}): {response.text}" ) return response.json() def extract_scores(predictions): """Convert HF model output into {positive, neutral, negative} dict.""" scores = {"positive": 0.0, "neutral": 0.0, "negative": 0.0} # Router API sometimes returns either list of lists or single list data = predictions[0] if isinstance(predictions, list) else predictions if isinstance(data, list) and len(data) > 0 and isinstance(data[0], dict): for item in data: label = item.get("label", "").lower() if "pos" in label: scores["positive"] = item["score"] elif "neg" in label: scores["negative"] = item["score"] elif "neu" in label: scores["neutral"] = item["score"] dominant = max(scores, key=scores.get) return {"label": dominant, "scores": scores} # =============================== # Main Endpoint # =============================== @app.post("/analyze") def analyze(data: InputData): print("🚀 Incoming request:", data) print("📡 Using router endpoint:", HF_ROUTER_URL) print("🔑 Using key starts with:", HF_API_KEY[:10]) result = {} errors = [] if data.title: try: finbert_out = call_hf_model(FINBERT_MODEL, data.title) result["title"] = extract_scores(finbert_out) except Exception as e: errors.append(f"Title analysis error: {e}") if data.content: try: longformer_out = call_hf_model(LONGFORMER_MODEL, data.content) result["content"] = extract_scores(longformer_out) except Exception as e: errors.append(f"Content analysis error: {e}") mood_score = ( result.get("title", {}).get("scores", {}).get("positive", 0) + result.get("content", {}).get("scores", {}).get("positive", 0) - result.get("title", {}).get("scores", {}).get("negative", 0) - result.get("content", {}).get("scores", {}).get("negative", 0) ) return { "mood_score": mood_score, "details": result, "errors": errors, "status": "ok" if not errors else "partial" } @app.get("/") def root(): return {"message": "Forex Sentiment API active via router.huggingface.co!"}