import gradio as gr
from urllib.request import urlopen
import certifi
import json
import pandas as pd
import os
import warnings
import re
warnings.filterwarnings("ignore")
from langchain_community.document_loaders import CSVLoader
from langchain_community.vectorstores import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
from langchain_community.llms import HuggingFacePipeline
from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
# Hugging Face API Key
os.environ["HUGGINGFACEHUB_API_TOKEN"] = os.environ.get("HUGGINGFACEHUB_API_TOKEN")
# Load Falcon LLM
model_id = "tiiuae/Falcon3-3B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id)
pipe = pipeline(
"text-generation",
model=model,
tokenizer=tokenizer,
max_new_tokens=512,
do_sample=True,
temperature=0.1,
top_k=50,
top_p=0.95,
eos_token_id=tokenizer.eos_token_id,
)
llm = HuggingFacePipeline(pipeline=pipe)
# Enhanced Prompt Template
template = """
You are a Financial Market Expert. Analyze the provided market data and create a comprehensive financial report.
Market Data: {context}
Company: {question}
Please provide a detailed analysis including:
1. Current stock performance metrics
2. Price movements and trends
3. Market capitalization details
4. Trading volume analysis
5. Key financial indicators
Format the response as a clear, professional financial report with proper sections and bullet points.
"""
PROMPT = PromptTemplate(input_variables=["context", "question"], template=template)
def format_currency(value):
"""Format currency values"""
try:
if isinstance(value, (int, float)):
return f"${value:,.2f}"
return str(value)
except:
return str(value)
def format_percentage(value):
"""Format percentage values"""
try:
if isinstance(value, (int, float)):
return f"{value:.2f}%"
return str(value)
except:
return str(value)
def create_html_report(data, llm_analysis):
"""Create a formatted HTML report"""
if not data or len(data) == 0:
return "
No data available for this ticker.
"
# Get the first data point (assuming it's the most relevant)
stock_data = data[0] if isinstance(data, list) else data
# Extract key metrics
symbol = stock_data.get('symbol', 'N/A')
name = stock_data.get('name', 'N/A')
price = stock_data.get('price', 0)
change = stock_data.get('change', 0)
change_percent = stock_data.get('changesPercentage', 0)
market_cap = stock_data.get('marketCap', 0)
volume = stock_data.get('volume', 0)
avg_volume = stock_data.get('avgVolume', 0)
pe_ratio = stock_data.get('pe', 'N/A')
eps = stock_data.get('eps', 'N/A')
# Determine trend color
trend_color = "#22c55e" if change >= 0 else "#ef4444"
trend_icon = "📈" if change >= 0 else "📉"
html = f"""
{symbol} - Financial Report
{name}
📅 Generated on {pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S')}
Current Price
{format_currency(price)}
Price Change {trend_icon}
{format_currency(change)} ({format_percentage(change_percent)})
Market Cap
{format_currency(market_cap) if market_cap else 'N/A'}
Volume
{f"{volume:,}" if volume else 'N/A'}
📊 Detailed Metrics
| P/E Ratio |
{pe_ratio} |
| Earnings Per Share (EPS) |
{format_currency(eps) if eps != 'N/A' else 'N/A'} |
| Average Volume |
{f"{avg_volume:,}" if avg_volume else 'N/A'} |
| Exchange |
{stock_data.get('exchange', 'N/A')} |
⚠️ This report is for informational purposes only and should not be considered as investment advice.
"""
return html
def generate_report(ticker: str, exchange: str):
"""Generate enhanced financial report"""
api_key = "C1HRSweTniWdBuLmTTse9w8KpkoiouM5"
if not ticker.strip():
return "❌ Please enter a valid ticker symbol.
"
try:
# Show loading message
loading_html = """
🔄 Generating Report...
Fetching data and running AI analysis
"""
# Fetch Data
ticker = ticker.upper().strip()
if exchange == "NSE":
url = f"https://financialmodelingprep.com/api/v3/search?query={ticker}&exchange=NSE&apikey={api_key}"
else:
url = f"https://financialmodelingprep.com/api/v3/quote/{ticker}?apikey={api_key}"
response = urlopen(url, cafile=certifi.where())
data = json.loads(response.read().decode("utf-8"))
if not data:
return "❌ No data found for ticker: " + ticker + "
"
# Save to CSV for RAG processing
df = pd.DataFrame(data)
if 'timestamp' in df.columns:
df['timestamp'] = pd.to_datetime(df['timestamp'], errors='coerce')
if 'earningsAnnouncement' in df.columns:
df['earningsAnnouncement'] = pd.to_datetime(df['earningsAnnouncement'], errors='coerce')
df.to_csv("eco_ind.csv", index=False)
# Create vector store and run LLM analysis
loader = CSVLoader("eco_ind.csv")
documents = loader.load()
splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=20)
texts = splitter.split_documents(documents)
embeddings = HuggingFaceEmbeddings()
chroma = Chroma.from_documents(
documents=texts,
collection_name="economic_data",
embedding=embeddings,
persist_directory="docs/chroma_rag"
)
retriever = chroma.as_retriever(search_kwargs={"k": 3})
qa = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
chain_type_kwargs={"prompt": PROMPT},
retriever=retriever,
return_source_documents=False
)
# Get LLM analysis
query = f"Provide a comprehensive financial analysis for {ticker}"
result = qa({"query": query})
llm_analysis = result["result"]
# Create and return formatted HTML report
return create_html_report(data, llm_analysis)
except Exception as e:
error_html = f"""
❌ Error Occurred
Details: {str(e)}
Please check your ticker symbol and try again. Make sure you have a stable internet connection.
"""
return error_html
# Custom CSS for better styling
custom_css = """
#component-0 {
max-width: 1200px !important;
margin: 0 auto !important;
}
.gradio-container {
background-color: black !important;
min-height: 100vh !important;
}
#title {
text-align: center !important;
color: white !important;
font-size: 2.5rem !important;
font-weight: 700 !important;
margin-bottom: 1rem !important;
text-shadow: 0 2px 4px rgba(0,0,0,0.1) !important;
}
#description {
text-align: center !important;
color: white !important;
font-size: 1.1rem !important;
margin-bottom: 2rem !important;
}
.input-container {
background: white !important;
border-radius: 5px !important;
padding: 3px !important;
box-shadow: 0 10px 30px rgba(0,0,0,0.1) !important;
margin-bottom: 20px !important;
}
.output-container {
background: transparent !important;
border-radius: 15px !important;
padding: 10px;
border: 2px white solid ;
overflow: hidden !important;
box-shadow: 0 10px 30px rgba(0,0,0,0.2) !important;
}
"""
# Create the Gradio interface with sidebar for inputs
with gr.Blocks(css=custom_css, title="📊 Financial Report Generator") as iface:
gr.HTML('📊 AI-Powered Financial Report Generator
')
gr.HTML('Enter a stock ticker and exchange to get a comprehensive AI-generated financial analysis
')
# Sidebar for inputs
with gr.Sidebar():
gr.Markdown("## 📥 Input Parameters")
ticker_input = gr.Textbox(
label="🎯 Stock Ticker Symbol",
placeholder="e.g., MSFT, AAPL, GOOGL",
info="Enter the stock symbol you want to analyze"
)
exchange_input = gr.Radio(
choices=["US", "NSE"],
label="🏢 Exchange",
value="US",
info="Select the stock exchange"
)
generate_btn = gr.Button(
"🚀 Generate Report",
variant="primary"
)
clear_btn = gr.Button(
"🔄 Clear",
variant="secondary"
)
# Output section
with gr.Row(elem_classes=["output-container"]):
output = gr.HTML(label="📊 Financial Report")
# Event handlers
generate_btn.click(
fn=generate_report,
inputs=[ticker_input, exchange_input],
outputs=output
)
clear_btn.click(
lambda: ["", "US", ""],
outputs=[ticker_input, exchange_input, output]
)
ticker_input.submit(
fn=generate_report,
inputs=[ticker_input, exchange_input],
outputs=output
)
if __name__ == "__main__":
iface.launch(
share=True,
show_error=True
)