Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -129,14 +129,26 @@ You have access to:
|
|
| 129 |
3. A powerful index calculator for custom analysis
|
| 130 |
When users ask about stocks or indices, fetch live data. Provide clear explanations with numbers."""
|
| 131 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
# ========== Core conversational function ==========
|
| 133 |
-
def process_query(query: str, history: List[
|
| 134 |
"""
|
| 135 |
Process user query with real-time data awareness.
|
| 136 |
-
history is a list of
|
| 137 |
Returns:
|
| 138 |
- response_text: str (the assistant's reply)
|
| 139 |
-
- updated_history: list of
|
| 140 |
- data_preview: pd.DataFrame
|
| 141 |
- status: str (unused)
|
| 142 |
"""
|
|
@@ -148,12 +160,13 @@ def process_query(query: str, history: List[List], exchange: str) -> Tuple[str,
|
|
| 148 |
indian_stocks = ['RELIANCE', 'TCS', 'INFY', 'HDFCBANK', 'ICICIBANK', 'SBIN',
|
| 149 |
'ITC', 'BHARTIARTL', 'KOTAKBANK', 'LT', 'WIPRO', 'AXISBANK']
|
| 150 |
|
|
|
|
| 151 |
query_lower = query.lower()
|
| 152 |
|
| 153 |
# Real-time data handling
|
| 154 |
-
if any(stock
|
| 155 |
for stock in indian_stocks:
|
| 156 |
-
if stock
|
| 157 |
try:
|
| 158 |
# Build symbol with correct suffix for Indian exchange
|
| 159 |
if exchange == "NSE":
|
|
@@ -178,7 +191,7 @@ def process_query(query: str, history: List[List], exchange: str) -> Tuple[str,
|
|
| 178 |
response_text = f"Error fetching data: {str(e)}"
|
| 179 |
break
|
| 180 |
|
| 181 |
-
if '
|
| 182 |
try:
|
| 183 |
nifty_data = global_api.get_stock_info('^NSEI')
|
| 184 |
if nifty_data:
|
|
@@ -187,22 +200,36 @@ def process_query(query: str, history: List[List], exchange: str) -> Tuple[str,
|
|
| 187 |
except Exception as e:
|
| 188 |
response_text = f"Error fetching Nifty: {str(e)}"
|
| 189 |
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
response_text += f"π Change: ${data['change']:+.2f} ({data['percent_change']:+.2f}%)\n"
|
| 200 |
-
response_text += f"π Day Range: ${data['day_low']} - ${data['day_high']}\n"
|
| 201 |
-
response_text += f"πΉ Market Cap: ${data['market_cap']/1e9:,.2f}B\n"
|
| 202 |
-
data_preview = pd.DataFrame([data])
|
| 203 |
-
except Exception as e:
|
| 204 |
-
response_text = f"Error fetching data: {str(e)}"
|
| 205 |
break
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 206 |
|
| 207 |
# If no real-time match, use LLM
|
| 208 |
if not response_text:
|
|
@@ -210,11 +237,10 @@ def process_query(query: str, history: List[List], exchange: str) -> Tuple[str,
|
|
| 210 |
llm = get_llm()
|
| 211 |
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
|
| 212 |
|
| 213 |
-
# Convert Gradio history (list of
|
| 214 |
flat_history = []
|
| 215 |
-
for
|
| 216 |
-
flat_history.append(
|
| 217 |
-
flat_history.append(assistant_msg)
|
| 218 |
|
| 219 |
messages = [SystemMessage(content=SYSTEM_PROMPT)]
|
| 220 |
for i, msg in enumerate(flat_history):
|
|
@@ -229,11 +255,14 @@ def process_query(query: str, history: List[List], exchange: str) -> Tuple[str,
|
|
| 229 |
except Exception as e:
|
| 230 |
response_text = f"LLM error: {str(e)}"
|
| 231 |
|
| 232 |
-
# Update history in Gradio's
|
| 233 |
-
updated_history = history + [
|
|
|
|
|
|
|
|
|
|
| 234 |
# Keep only last 10 exchanges (20 messages)
|
| 235 |
-
if len(updated_history) >
|
| 236 |
-
updated_history = updated_history[-
|
| 237 |
|
| 238 |
return response_text, updated_history, data_preview, ""
|
| 239 |
|
|
@@ -257,17 +286,20 @@ def fetch_live_stock(symbol: str, exchange: str):
|
|
| 257 |
fig.update_layout(height=300)
|
| 258 |
return formatted, formatted['last_price'], formatted['change'], formatted['percent_change'], fig
|
| 259 |
else:
|
| 260 |
-
|
| 261 |
-
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
|
| 269 |
-
|
| 270 |
-
|
|
|
|
|
|
|
|
|
|
| 271 |
return {}, 0, 0, 0, go.Figure()
|
| 272 |
|
| 273 |
def build_custom_index(symbols_df: pd.DataFrame, index_type: str, exchange: str):
|
|
@@ -288,6 +320,7 @@ def build_custom_index(symbols_df: pd.DataFrame, index_type: str, exchange: str)
|
|
| 288 |
else:
|
| 289 |
price = 0
|
| 290 |
else:
|
|
|
|
| 291 |
data = global_api.get_stock_info(symbol)
|
| 292 |
price = data.get('last_price', 0) if data else 0
|
| 293 |
weights.append(weight)
|
|
|
|
| 129 |
3. A powerful index calculator for custom analysis
|
| 130 |
When users ask about stocks or indices, fetch live data. Provide clear explanations with numbers."""
|
| 131 |
|
| 132 |
+
# Mapping for common company names to tickers (for global stocks)
|
| 133 |
+
GLOBAL_TICKER_MAP = {
|
| 134 |
+
'APPLE': 'AAPL',
|
| 135 |
+
'GOOGLE': 'GOOGL',
|
| 136 |
+
'MICROSOFT': 'MSFT',
|
| 137 |
+
'AMAZON': 'AMZN',
|
| 138 |
+
'TESLA': 'TSLA',
|
| 139 |
+
'META': 'META',
|
| 140 |
+
'FACEBOOK': 'META',
|
| 141 |
+
'NETFLIX': 'NFLX',
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
# ========== Core conversational function ==========
|
| 145 |
+
def process_query(query: str, history: List[Dict], exchange: str) -> Tuple[str, List[Dict], pd.DataFrame, str]:
|
| 146 |
"""
|
| 147 |
Process user query with real-time data awareness.
|
| 148 |
+
history is a list of dicts: [{"role": "user", "content": "..."}, {"role": "assistant", "content": "..."}, ...]
|
| 149 |
Returns:
|
| 150 |
- response_text: str (the assistant's reply)
|
| 151 |
+
- updated_history: list of dicts (new chat history)
|
| 152 |
- data_preview: pd.DataFrame
|
| 153 |
- status: str (unused)
|
| 154 |
"""
|
|
|
|
| 160 |
indian_stocks = ['RELIANCE', 'TCS', 'INFY', 'HDFCBANK', 'ICICIBANK', 'SBIN',
|
| 161 |
'ITC', 'BHARTIARTL', 'KOTAKBANK', 'LT', 'WIPRO', 'AXISBANK']
|
| 162 |
|
| 163 |
+
query_upper = query.upper()
|
| 164 |
query_lower = query.lower()
|
| 165 |
|
| 166 |
# Real-time data handling
|
| 167 |
+
if any(stock in query_upper for stock in indian_stocks) or 'NIFTY' in query_upper or 'SENSEX' in query_upper:
|
| 168 |
for stock in indian_stocks:
|
| 169 |
+
if stock in query_upper:
|
| 170 |
try:
|
| 171 |
# Build symbol with correct suffix for Indian exchange
|
| 172 |
if exchange == "NSE":
|
|
|
|
| 191 |
response_text = f"Error fetching data: {str(e)}"
|
| 192 |
break
|
| 193 |
|
| 194 |
+
if 'NIFTY' in query_upper and not response_text:
|
| 195 |
try:
|
| 196 |
nifty_data = global_api.get_stock_info('^NSEI')
|
| 197 |
if nifty_data:
|
|
|
|
| 200 |
except Exception as e:
|
| 201 |
response_text = f"Error fetching Nifty: {str(e)}"
|
| 202 |
|
| 203 |
+
# Check for global stock tickers or company names
|
| 204 |
+
else:
|
| 205 |
+
# Try to find a ticker in the query
|
| 206 |
+
ticker = None
|
| 207 |
+
# First check if any known ticker appears directly
|
| 208 |
+
known_tickers = ['AAPL', 'GOOGL', 'MSFT', 'AMZN', 'TSLA', 'META', 'NFLX']
|
| 209 |
+
for t in known_tickers:
|
| 210 |
+
if t in query_upper:
|
| 211 |
+
ticker = t
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 212 |
break
|
| 213 |
+
|
| 214 |
+
# If not found, check for company names
|
| 215 |
+
if not ticker:
|
| 216 |
+
for company, t in GLOBAL_TICKER_MAP.items():
|
| 217 |
+
if company in query_upper:
|
| 218 |
+
ticker = t
|
| 219 |
+
break
|
| 220 |
+
|
| 221 |
+
if ticker:
|
| 222 |
+
try:
|
| 223 |
+
data = global_api.get_stock_info(ticker)
|
| 224 |
+
if data:
|
| 225 |
+
response_text = f"**{data['company_name']} ({ticker})**\n\n"
|
| 226 |
+
response_text += f"π° Current Price: ${data['last_price']:,.2f}\n"
|
| 227 |
+
response_text += f"π Change: ${data['change']:+.2f} ({data['percent_change']:+.2f}%)\n"
|
| 228 |
+
response_text += f"π Day Range: ${data['day_low']} - ${data['day_high']}\n"
|
| 229 |
+
response_text += f"πΉ Market Cap: ${data['market_cap']/1e9:,.2f}B\n"
|
| 230 |
+
data_preview = pd.DataFrame([data])
|
| 231 |
+
except Exception as e:
|
| 232 |
+
response_text = f"Error fetching data: {str(e)}"
|
| 233 |
|
| 234 |
# If no real-time match, use LLM
|
| 235 |
if not response_text:
|
|
|
|
| 237 |
llm = get_llm()
|
| 238 |
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
|
| 239 |
|
| 240 |
+
# Convert Gradio history (list of dicts) to flat list for LangChain
|
| 241 |
flat_history = []
|
| 242 |
+
for turn in history:
|
| 243 |
+
flat_history.append(turn["content"])
|
|
|
|
| 244 |
|
| 245 |
messages = [SystemMessage(content=SYSTEM_PROMPT)]
|
| 246 |
for i, msg in enumerate(flat_history):
|
|
|
|
| 255 |
except Exception as e:
|
| 256 |
response_text = f"LLM error: {str(e)}"
|
| 257 |
|
| 258 |
+
# Update history in Gradio's dictionary format (list of dicts)
|
| 259 |
+
updated_history = history + [
|
| 260 |
+
{"role": "user", "content": query},
|
| 261 |
+
{"role": "assistant", "content": response_text}
|
| 262 |
+
]
|
| 263 |
# Keep only last 10 exchanges (20 messages)
|
| 264 |
+
if len(updated_history) > 20:
|
| 265 |
+
updated_history = updated_history[-20:]
|
| 266 |
|
| 267 |
return response_text, updated_history, data_preview, ""
|
| 268 |
|
|
|
|
| 286 |
fig.update_layout(height=300)
|
| 287 |
return formatted, formatted['last_price'], formatted['change'], formatted['percent_change'], fig
|
| 288 |
else:
|
| 289 |
+
# For global, try to map common names
|
| 290 |
+
ticker = symbol.upper()
|
| 291 |
+
if ticker in GLOBAL_TICKER_MAP.values() or ticker in ['AAPL', 'GOOGL', 'MSFT', 'AMZN', 'TSLA', 'META', 'NFLX']:
|
| 292 |
+
data = global_api.get_stock_info(ticker)
|
| 293 |
+
if data:
|
| 294 |
+
fig = go.Figure()
|
| 295 |
+
fig.add_trace(go.Indicator(
|
| 296 |
+
mode="number+delta",
|
| 297 |
+
value=data['last_price'],
|
| 298 |
+
number={'prefix': '$'},
|
| 299 |
+
delta={'reference': data['last_price'] - data['change']}
|
| 300 |
+
))
|
| 301 |
+
fig.update_layout(height=300)
|
| 302 |
+
return data, data['last_price'], data['change'], data['percent_change'], fig
|
| 303 |
return {}, 0, 0, 0, go.Figure()
|
| 304 |
|
| 305 |
def build_custom_index(symbols_df: pd.DataFrame, index_type: str, exchange: str):
|
|
|
|
| 320 |
else:
|
| 321 |
price = 0
|
| 322 |
else:
|
| 323 |
+
# For global, try direct ticker
|
| 324 |
data = global_api.get_stock_info(symbol)
|
| 325 |
price = data.get('last_price', 0) if data else 0
|
| 326 |
weights.append(weight)
|