StoQ / main.py
manan77709's picture
Upload 9 files
80b5809 verified
Raw
History Blame Contribute Delete
5.04 kB
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"
}
@app.post("/api/workflow", response_model=List[BatchArticleResult])
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)