quantmacro-india / src /agents /analyst_node.py
kingbros919's picture
Upload folder using huggingface_hub
292b308 verified
Raw
History Blame Contribute Delete
2.58 kB
import os
import sys
import re
from langchain_google_genai import ChatGoogleGenerativeAI
from src.agents.state import AgentState
# Ensure project root is in path
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")))
def analyst_node(state: AgentState) -> AgentState:
"""
Synthesizes RAG contexts and ML/sentiment quantitative signals using Gemini.
"""
try:
# Build prompt using f-string exactly as specified
prompt = f"""SYSTEM: You are a senior BSE sector analyst at an institutional fund.
You synthesize quantitative signals and fundamental research into clear, actionable sector views.
Always cite your evidence. Never fabricate data.
USER:
Query: {state["query"]}
Sector: {state["sector"] or "Multi-sector"}
=== QUANTITATIVE SIGNALS ===
ML Model Direction: {state["ml_signal"].get("direction", "N/A")}
Model Confidence: {state["ml_signal"].get("probability", 0.5):.1%}
News Sentiment Score: {state["news_sentiment"]:.3f} (range -1 to +1)
Key Features Used: {", ".join(state["ml_signal"].get("features_used", [])[:5])}
=== EARNINGS & FILING CONTEXT (RAG) ===
{chr(10).join([f"[{i+1}] {c['source']} ({c['sector']}): {c['content'][:300]}" for i, c in enumerate(state["retrieved_chunks"][:4])])}
Provide:
1. SECTOR VIEW (1 sentence: Bullish / Neutral / Bearish + reason)
2. KEY EVIDENCE (2-3 bullet points from the context above)
3. RISK FACTORS (1-2 specific risks)
4. CONFIDENCE: HIGH / MEDIUM / LOW (based on context quality)"""
# Retrieve Google API key
api_key = os.getenv("GEMINI_API_KEY")
# Call ChatGoogleGenerativeAI
llm = ChatGoogleGenerativeAI(
model="gemini-2.5-flash",
temperature=0.1,
google_api_key=api_key
)
response = llm.invoke(prompt)
response_text = response.content
# Parse CONFIDENCE from response text
match = re.search(r"CONFIDENCE[:\*\s]*(HIGH|MEDIUM|LOW)", response_text, re.IGNORECASE)
confidence = match.group(1).upper() if match else "LOW"
# Extract sources (preserve duplicates for counting occurrences in UI)
sources = [c["source"] for c in state["retrieved_chunks"] if "source" in c]
state["answer"] = response_text
state["sources"] = sources
state["confidence"] = confidence
except Exception as e:
state["answer"] = f"Analysis unavailable — LLM error: {str(e)}"
state["confidence"] = "LOW"
state["sources"] = []
return state