Spaces:
Sleeping
Sleeping
File size: 11,261 Bytes
ce180e5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 |
"""
CFA AI Agent - LangChain Agent Setup
This module sets up the LangChain agent with Finance-Llama-8B model and financial tools.
"""
import os
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
from langchain_community.llms import HuggingFacePipeline
from langchain.agents import initialize_agent, AgentType
from langchain.memory import ConversationBufferMemory
from langchain.schema import SystemMessage
from langchain.prompts import MessagesPlaceholder
from typing import List, Any, Optional
# Import our custom tools
from tools.finance_tools import (
calculate_dcf,
calculate_sharpe_ratio,
compare_pe_ratios,
calculate_beta,
calculate_wacc,
financial_ratios_analysis
)
from tools.data_fetcher import (
get_stock_price,
get_historical_data,
get_company_info,
get_financial_statements,
get_market_indices,
compare_stocks
)
class CFAAgent:
"""
CFA AI Agent that combines Finance-Llama-8B model with financial analysis tools.
"""
def __init__(self, model_name: str = "tarun7r/Finance-Llama-8B"):
"""
Initialize the CFA Agent with model and tools.
Args:
model_name: Hugging Face model name for financial analysis
"""
self.model_name = model_name
self.tokenizer = None
self.model = None
self.llm = None
self.agent = None
self.memory = None
self._setup_model()
self._setup_tools()
self._setup_agent()
def _setup_model(self):
"""Load and setup the Finance-Llama-8B model."""
try:
print(f"Loading model: {self.model_name}")
# Check if CUDA is available
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using device: {device}")
# Load tokenizer
self.tokenizer = AutoTokenizer.from_pretrained(
self.model_name,
trust_remote_code=True
)
# Add pad token if not present
if self.tokenizer.pad_token is None:
self.tokenizer.pad_token = self.tokenizer.eos_token
# Load model with appropriate settings and memory optimization
if device == "cuda":
self.model = AutoModelForCausalLM.from_pretrained(
self.model_name,
torch_dtype=torch.float16,
device_map="auto",
trust_remote_code=True,
low_cpu_mem_usage=True,
load_in_8bit=True, # Enable 8-bit quantization for memory efficiency
max_memory={0: "6GB"} # Limit GPU memory usage
)
else:
# For CPU, use aggressive memory optimization
self.model = AutoModelForCausalLM.from_pretrained(
self.model_name,
trust_remote_code=True,
low_cpu_mem_usage=True,
torch_dtype=torch.float32,
device_map="cpu",
max_memory={"cpu": "8GB"} # Limit CPU memory usage
)
# Create pipeline
pipe = pipeline(
"text-generation",
model=self.model,
tokenizer=self.tokenizer,
max_new_tokens=512,
temperature=0.1,
do_sample=True,
pad_token_id=self.tokenizer.eos_token_id,
repetition_penalty=1.1
)
# Wrap in LangChain
self.llm = HuggingFacePipeline(pipeline=pipe)
print("β
Model loaded successfully")
except Exception as e:
print(f"β Error loading model: {str(e)}")
# Fallback to a smaller model or OpenAI if Finance-Llama-8B fails
self._setup_fallback_model()
def _setup_fallback_model(self):
"""Setup a fallback model if Finance-Llama-8B fails to load."""
try:
print("Setting up fallback model...")
from langchain_community.llms import OpenAI
# Check for OpenAI API key
if os.getenv("OPENAI_API_KEY"):
self.llm = OpenAI(
temperature=0.1,
model_name="gpt-3.5-turbo-instruct",
max_tokens=512
)
print("β
Using OpenAI GPT-3.5 as fallback")
else:
raise ValueError("No OpenAI API key found")
except Exception as e:
print(f"β Fallback model failed: {str(e)}")
# Last resort: use a very small local model
try:
pipe = pipeline(
"text-generation",
model="distilgpt2",
max_new_tokens=256,
temperature=0.7
)
self.llm = HuggingFacePipeline(pipeline=pipe)
print("β
Using DistilGPT2 as emergency fallback")
except Exception as final_e:
raise RuntimeError(f"All model loading attempts failed: {final_e}")
def _setup_tools(self):
"""Setup all available financial analysis tools."""
self.tools = [
# Finance calculation tools
calculate_dcf,
calculate_sharpe_ratio,
compare_pe_ratios,
calculate_beta,
calculate_wacc,
financial_ratios_analysis,
# Data fetching tools
get_stock_price,
get_historical_data,
get_company_info,
get_financial_statements,
get_market_indices,
compare_stocks
]
print(f"β
Loaded {len(self.tools)} financial analysis tools")
def _setup_agent(self):
"""Setup the LangChain agent with memory and tools."""
try:
# Setup conversation memory
self.memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True,
output_key="output"
)
# Initialize agent
self.agent = initialize_agent(
tools=self.tools,
llm=self.llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
memory=self.memory,
verbose=True,
handle_parsing_errors=True,
max_iterations=3,
early_stopping_method="generate"
)
# Add system message for financial context
system_message = """You are a CFA (Chartered Financial Analyst) AI assistant specialized in financial analysis, investment valuation, and portfolio management.
Your expertise includes:
- Financial statement analysis and ratio calculations
- Valuation models (DCF, comparable company analysis, etc.)
- Risk assessment and portfolio theory
- Market analysis and economic indicators
- Investment recommendations based on fundamental analysis
When answering questions:
1. Use the available financial tools to fetch real data when needed
2. Provide clear, professional explanations suitable for CFA-level analysis
3. Show your calculations and reasoning
4. Consider both quantitative and qualitative factors
5. Acknowledge limitations and assumptions in your analysis
You have access to real-time financial data and calculation tools. Use them to provide accurate, data-driven insights."""
# Store system message for context
self.system_message = system_message
print("β
Agent initialized successfully")
except Exception as e:
print(f"β Error setting up agent: {str(e)}")
raise
def query(self, question: str) -> str:
"""
Process a financial query using the CFA agent.
Args:
question: User's financial question or request
Returns:
Agent's response with analysis and recommendations
"""
try:
# Enhance the question with context
enhanced_question = f"""As a CFA analyst, please help with the following:
{question}
Please provide a thorough analysis using available data and financial tools. Show your work and explain your reasoning."""
# Get response from agent
response = self.agent.run(enhanced_question)
return response
except Exception as e:
error_msg = f"Error processing query: {str(e)}"
print(error_msg)
return error_msg
def get_conversation_history(self) -> List[Any]:
"""Get the current conversation history."""
if self.memory:
return self.memory.chat_memory.messages
return []
def clear_memory(self):
"""Clear the conversation memory."""
if self.memory:
self.memory.clear()
print("β
Conversation memory cleared")
def get_available_tools(self) -> List[str]:
"""Get list of available tool names."""
return [tool.name for tool in self.tools]
def health_check(self) -> dict:
"""Perform a health check of the agent components."""
status = {
"model_loaded": self.model is not None,
"llm_ready": self.llm is not None,
"agent_ready": self.agent is not None,
"memory_ready": self.memory is not None,
"tools_count": len(self.tools),
"device": "cuda" if torch.cuda.is_available() else "cpu"
}
return status
def create_cfa_agent(model_name: str = "tarun7r/Finance-Llama-8B") -> CFAAgent:
"""
Factory function to create and return a CFA Agent instance.
Args:
model_name: Hugging Face model name for financial analysis
Returns:
Initialized CFAAgent instance
"""
try:
agent = CFAAgent(model_name=model_name)
print("π― CFA Agent created successfully")
return agent
except Exception as e:
print(f"β Failed to create CFA Agent: {str(e)}")
raise
# Example usage and testing
if __name__ == "__main__":
print("π Initializing CFA AI Agent...")
try:
# Create agent
cfa_agent = create_cfa_agent()
# Health check
health = cfa_agent.health_check()
print("π Health Check Results:")
for key, value in health.items():
status = "β
" if value else "β"
print(f" {status} {key}: {value}")
# Test queries
test_queries = [
"What is the current stock price of Apple (AAPL)?",
"Calculate the PE ratio comparison between Apple and Microsoft",
"Explain the CAPM model in simple terms"
]
print("\nπ§ͺ Running test queries...")
for i, query in enumerate(test_queries, 1):
print(f"\n--- Test Query {i} ---")
print(f"Q: {query}")
try:
response = cfa_agent.query(query)
print(f"A: {response}")
except Exception as e:
print(f"β Query failed: {str(e)}")
except Exception as e:
print(f"β CFA Agent initialization failed: {str(e)}") |