Spaces:
Runtime error
Runtime error
| from fastapi import FastAPI, HTTPException | |
| from fastapi.middleware.cors import CORSMiddleware | |
| import time | |
| import concurrent.futures | |
| from typing import List | |
| from schemas import IncomingNews, FinalReport, BatchArticleResult | |
| from openai_agent import extraction_agent | |
| from quant_agent import quant_agent | |
| from presenter_agent import presenter_agent | |
| app = FastAPI(title="Stock-IQ Agentic Backend") | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| LAST_REQUEST_TIME = 0.0 | |
| VALID_STOCKS = { | |
| "ABCAPITAL","ACC","ADANIENT","ADANIGREEN","ADANIPOWER","AMBUJACEM", | |
| "APOLLOHOSP","ASHOKLEY","ASIANPAINT","ATGL","AUBANK","AUROPHARMA", | |
| "AXISBANK","BAJAJ-AUTO","BAJAJFINSV","BAJFINANCE","BALKRISIND", | |
| "BANDHANBNK","BANKBARODA","BEL","BHARATFORG","BHARTIARTL","BHEL", | |
| "BIOCON","BOSCHLTD","BPCL","BRIGADE","BRITANNIA","BSE","CANBK", | |
| "CDSL","CHOLAFIN","CIPLA","COALINDIA","COFORGE","COLPAL","CONCOR", | |
| "CUMMINSIND","DABUR","DELHIVERY","DIVISLAB","DIXON","DLF","DMART", | |
| "DRREDDY","EICHERMOT","FEDERALBNK","GAIL","GLENMARK","GODREJCP", | |
| "GODREJPROP","HAL","HAVELLS","HCLTECH","HDFCBANK","HDFCLIFE", | |
| "HEROMOTOCO","HINDALCO","HINDPETRO","HINDUNILVR","HINDZINC", | |
| "HONASA","ICICIBANK","ICICIGI","IDEA","IDFCFIRSTB","IGL","INDIGO", | |
| "INDUSTOWER","INDUSINDBK","INFY","IOC","IRCTC","IREDA","IRFC","ITC", | |
| "JINDALSTEL","JIOFIN","JSWSTEEL","KOTAKBANK","LICI","LT","LTIM", | |
| "M&M","MANKIND","MARICO","MARUTI","MAZDOCK","MCX","MGL","MPHASIS", | |
| "MRF","MUTHOOTFIN","NATIONALUM","NBCC","NESTLEIND","NHPC","NMDC", | |
| "NYKAA","OBEROIRLTY","OIL","ONGC","PAYTM","PERSISTENT","PFC", | |
| "PHOENIXLTD","PIDILITIND","PNB","PRESTIGE","RECLTD","RELIANCE", | |
| "RVNL","SAIL","SBIN","SHREECEM","SJVN","SOBHA","SOLARINDS", | |
| "SUNPHARMA","SUZLON","SWIGGY","TATACONSUM","TATACHEM","TATAELXSI", | |
| "TATAPOWER","TATASTEEL","TECHM","TITAN","TORNTPHARM","TRENT", | |
| "TVSMOTOR","UPL","VBL","VEDL","VOLTAS","YESBANK","ZEEL","ZYDUSLIFE" | |
| } | |
| async def run_batch_workflow(payloads: List[IncomingNews]): | |
| global LAST_REQUEST_TIME | |
| # Rate limiting to protect your Hugging Face Space | |
| if (time.time() - LAST_REQUEST_TIME) < 1.0: | |
| raise HTTPException(status_code=429, detail="Cooldown active.") | |
| LAST_REQUEST_TIME = time.time() | |
| batch_results = [] | |
| print(f"\n[SYSTEM] Received {len(payloads)} articles from Frontend.") | |
| for idx, payload in enumerate(payloads, start=1): | |
| # Using the exact names from your new schema | |
| combined_news_text = f"{payload.title}. {payload.description}" | |
| empty_analysis = FinalReport( | |
| status="Success", | |
| analyzed_news=combined_news_text, | |
| impacted_domains=[] | |
| ) | |
| try: | |
| # 1. AI Extraction | |
| raw_tickers_dict = extraction_agent(combined_news_text) | |
| if not raw_tickers_dict: | |
| batch_results.append(BatchArticleResult(article_id=idx, source=payload.source, news_text=combined_news_text, ai_analysis=empty_analysis)) | |
| continue | |
| # 2. Strict Filter | |
| tickers_dict = {t.strip().upper(): w for t, w in raw_tickers_dict.items() if t.strip().upper() in VALID_STOCKS} | |
| if not tickers_dict: | |
| batch_results.append(BatchArticleResult(article_id=idx, source=payload.source, news_text=combined_news_text, ai_analysis=empty_analysis)) | |
| continue | |
| # 3. Quant Phase (Multi-threaded) | |
| analyzed_stocks = [] | |
| with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor: | |
| futures = {executor.submit(quant_agent, t, combined_news_text, w): t for t, w in tickers_dict.items()} | |
| for future in concurrent.futures.as_completed(futures): | |
| try: | |
| result = future.result() | |
| analyzed_stocks.append(result) | |
| except Exception: | |
| pass | |
| # 4. Presenter Phase | |
| if analyzed_stocks: | |
| report = presenter_agent(analyzed_stocks, combined_news_text) | |
| batch_results.append(BatchArticleResult(article_id=idx, source=payload.source, news_text=combined_news_text, ai_analysis=report)) | |
| else: | |
| batch_results.append(BatchArticleResult(article_id=idx, source=payload.source, news_text=combined_news_text, ai_analysis=empty_analysis)) | |
| except Exception as e: | |
| print(f"[ERROR] Critical failure on article {idx}: {e}") | |
| batch_results.append(BatchArticleResult(article_id=idx, source=payload.source, news_text=combined_news_text, ai_analysis=empty_analysis)) | |
| return batch_results | |
| if __name__ == "__main__": | |
| import uvicorn | |
| uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True) |