Adedoyinjames commited on
Commit
3316b4a
Β·
verified Β·
1 Parent(s): f5215d5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +175 -126
app.py CHANGED
@@ -9,13 +9,17 @@ import json
9
  import asyncio
10
  import aiohttp
11
  from typing import Optional, List, Dict
12
- import nest_asyncio
13
 
14
  # Apply nest_asyncio for async operations in Streamlit
15
- nest_asyncio.apply()
 
 
 
 
16
 
17
- # Hugging Face token setup
18
- HUGGINGFACE_TOKEN = st.secrets.get("HUGGINGFACE_TOKEN", "")
19
 
20
  if HUGGINGFACE_TOKEN:
21
  try:
@@ -24,64 +28,90 @@ if HUGGINGFACE_TOKEN:
24
  except Exception as e:
25
  st.error(f"❌ Hugging Face login failed: {e}")
26
 
27
- # Custom CSS for silver/sky blue theme
28
  st.markdown("""
29
  <style>
30
  .main {
31
- background-color: #f8f9fa;
 
32
  }
 
33
  .stChatMessage {
34
- padding: 16px;
35
- border-radius: 12px;
36
- margin: 8px 0;
37
- }
38
- .stChatMessage[data-testid="stChatMessage"] {
39
- border: 1px solid #e1e5e9;
40
  }
 
41
  /* User message styling */
42
  .stChatMessage:has(div[data-testid="stChatMessageContent"] > div:first-child > div:first-child) {
43
- background-color: #e3f2fd;
44
- border-left: 4px solid #2196f3;
45
  }
 
46
  /* Assistant message styling */
47
  .stChatMessage:has(div[data-testid="stChatMessageContent"] > div:first-child > div:last-child) {
48
- background-color: #ffffff;
49
- border-left: 4px solid #78909c;
 
50
  }
 
51
  .stTextInput > div > div > input {
52
  border: 2px solid #90caf9;
53
- border-radius: 20px;
54
- padding: 12px 16px;
 
 
 
55
  }
 
56
  .stButton > button {
57
- background-color: #2196f3;
58
  color: white;
59
  border: none;
60
- border-radius: 20px;
61
- padding: 10px 24px;
62
- font-weight: 500;
 
 
 
63
  }
 
64
  .stButton > button:hover {
65
- background-color: #1976d2;
66
- color: white;
67
  }
 
68
  .sidebar .sidebar-content {
69
- background-color: #eceff1;
 
70
  }
 
71
  .api-status {
72
- padding: 8px;
73
- border-radius: 6px;
74
- margin: 5px 0;
75
- font-size: 0.8em;
 
76
  }
 
77
  .api-success {
78
- background-color: #e8f5e8;
79
  border-left: 4px solid #4caf50;
80
  }
 
81
  .api-error {
82
- background-color: #ffebee;
83
  border-left: 4px solid #f44336;
84
  }
 
 
 
 
 
 
 
85
  </style>
86
  """, unsafe_allow_html=True)
87
 
@@ -105,7 +135,7 @@ COMPANY_INFO = {
105
  "stage": "Growth and development, focused on building sustainable processes and systems"
106
  }
107
 
108
- # API Configuration
109
  API_CONFIG = {
110
  "news_api": {
111
  "url": "https://newsapi.org/v2/top-headlines",
@@ -113,14 +143,14 @@ API_CONFIG = {
113
  "country": "us",
114
  "category": "technology",
115
  "pageSize": 5,
116
- "apiKey": st.secrets.get("NEWS_API_KEY", "demo_key")
117
  }
118
  },
119
  "weather_api": {
120
  "url": "https://api.openweathermap.org/data/2.5/weather",
121
  "params": {
122
  "q": "Lagos,NG",
123
- "appid": st.secrets.get("WEATHER_API_KEY", "demo_key"),
124
  "units": "metric"
125
  }
126
  },
@@ -129,11 +159,8 @@ API_CONFIG = {
129
  "params": {
130
  "function": "GLOBAL_QUOTE",
131
  "symbol": "AAPL",
132
- "apikey": st.secrets.get("ALPHA_VANTAGE_KEY", "demo_key")
133
  }
134
- },
135
- "yah_tech_internal": {
136
- "url": "http://localhost:8000" # For internal FastAPI server
137
  }
138
  }
139
 
@@ -151,7 +178,7 @@ class APIClient:
151
  async def make_async_request(self, url: str, params: dict = None, headers: dict = None):
152
  """Make asynchronous API request"""
153
  try:
154
- async with self.session.get(url, params=params, headers=headers) as response:
155
  if response.status == 200:
156
  return await response.json()
157
  else:
@@ -181,9 +208,9 @@ class ExternalAPIService:
181
  if config["params"]["apiKey"] == "demo_key":
182
  return {
183
  "articles": [
184
- {"title": "AI Technology Advances in 2024", "description": "Latest breakthroughs in artificial intelligence..."},
185
- {"title": "Venture Studio Model Gains Popularity", "description": "More entrepreneurs adopting the venture studio approach..."},
186
- {"title": "Economic Impact of Tech Startups", "description": "How technology startups are reshaping economies..."}
187
  ]
188
  }
189
 
@@ -197,9 +224,10 @@ class ExternalAPIService:
197
 
198
  if config["params"]["appid"] == "demo_key":
199
  return {
200
- "weather": [{"description": "clear sky"}],
201
- "main": {"temp": 28, "humidity": 65},
202
- "name": city
 
203
  }
204
 
205
  result = await self.api_client.make_async_request(config["url"], config["params"])
@@ -213,6 +241,7 @@ class ExternalAPIService:
213
  if config["params"]["apikey"] == "demo_key":
214
  return {
215
  "Global Quote": {
 
216
  "05. price": "185.50",
217
  "09. change": "+1.25",
218
  "10. change percent": "+0.68%"
@@ -223,7 +252,8 @@ class ExternalAPIService:
223
  return result
224
 
225
  def get_crypto_data(self, coin: str = "bitcoin"):
226
- """Get cryptocurrency data (synchronous for simplicity)"""
 
227
  url = f"https://api.coingecko.com/api/v3/simple/price"
228
  params = {
229
  "ids": coin,
@@ -234,27 +264,27 @@ class ExternalAPIService:
234
  result = self.api_client.make_sync_request(url, params)
235
  return result
236
 
237
- # Knowledge base for the AI (updated with API capabilities)
238
  KNOWLEDGE_BASE = {
239
  "personal": {
240
- "who are you": f"I'm {PERSONAL_INFO['name']}, {PERSONAL_INFO['role']}.",
241
- "what are your goals": f"My goals include: {', '.join(PERSONAL_INFO['goals'])}.",
242
- "what do you do": f"I'm the CEO of YAH Tech, focused on {PERSONAL_INFO['goals'][2]}.",
243
- "tell me about yourself": f"I'm {PERSONAL_INFO['name']}, {PERSONAL_INFO['role']}. My mission is to {PERSONAL_INFO['goals'][0].lower()} and {PERSONAL_INFO['goals'][1].lower()}.",
244
  },
245
  "company": {
246
- "what is yah tech": f"{COMPANY_INFO['name']} is a {COMPANY_INFO['type']}. Our purpose is to {COMPANY_INFO['purpose'].lower()}.",
247
- "what does yah tech do": f"We specialize in {COMPANY_INFO['primary_activity'].lower()}. {COMPANY_INFO['purpose']}.",
248
- "company philosophy": f"Our philosophy is: '{COMPANY_INFO['philosophy']}'.",
249
- "company stage": f"We're currently in the {COMPANY_INFO['stage']} phase.",
250
- "venture studio": "As a venture studio, we don't just build apps - we build complete businesses with scalable systems and futuristic solutions.",
251
  },
252
  "api_capabilities": {
253
- "what can you do": "I can fetch real-time data like tech news, weather, stock prices, and cryptocurrency data. I also have knowledge about YAH Tech and Adedoyin James.",
254
- "get news": "I can fetch the latest technology news for you.",
255
- "weather": "I can check weather information for any city.",
256
- "stock": "I can get stock market data for companies.",
257
- "crypto": "I can fetch cryptocurrency prices and changes.",
258
  }
259
  }
260
 
@@ -269,7 +299,7 @@ class YAHBot:
269
  def _load_model(self):
270
  """Load the Hugging Face model"""
271
  try:
272
- with st.spinner("πŸ”„ Loading AI model..."):
273
  self.tokenizer = AutoTokenizer.from_pretrained(
274
  "Adedoyinjames/YAH-Tech-Chat-Bot",
275
  use_auth_token=HUGGINGFACE_TOKEN if HUGGINGFACE_TOKEN else True
@@ -279,16 +309,16 @@ class YAHBot:
279
  use_auth_token=HUGGINGFACE_TOKEN if HUGGINGFACE_TOKEN else True,
280
  torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32
281
  )
282
- st.success("βœ… AI model loaded successfully!")
283
  except Exception as e:
284
  st.error(f"❌ Failed to load custom model: {e}")
285
  st.info("πŸ”„ Falling back to standard FLAN-T5-small model...")
286
  try:
287
  self.tokenizer = AutoTokenizer.from_pretrained(self.model_name)
288
  self.model = AutoModelForSeq2SeqLM.from_pretrained(self.model_name)
289
- st.success("βœ… Standard model loaded successfully!")
290
  except Exception as e2:
291
- st.error(f"❌ Failed to load standard model: {e2}")
292
 
293
  def _get_knowledge_response(self, user_input):
294
  """Check if the input matches any knowledge base entries"""
@@ -316,29 +346,29 @@ class YAHBot:
316
  if any(word in user_input_lower for word in ["news", "headlines", "tech news"]):
317
  news_data = await self.api_service.get_tech_news()
318
  if "articles" in news_data:
319
- articles = news_data["articles"][:3] # Show top 3
320
- response = "πŸ“° **Latest Tech News:**\n\n"
321
  for i, article in enumerate(articles, 1):
322
- response += f"{i}. **{article.get('title', 'No title')}**\n"
323
  response += f" {article.get('description', 'No description available')}\n\n"
324
  return response
325
  else:
326
  return "❌ Could not fetch news at the moment. Please try again later."
327
 
328
  elif any(word in user_input_lower for word in ["weather", "temperature"]):
329
- # Extract city name if mentioned
330
  city = "Lagos"
331
  for word in user_input_lower.split():
332
- if word not in ["weather", "temperature", "what's", "the"] and len(word) > 2:
333
  city = word.capitalize()
334
  break
335
 
336
  weather_data = await self.api_service.get_weather(city)
337
  if "weather" in weather_data:
338
  temp = weather_data["main"]["temp"]
339
- desc = weather_data["weather"][0]["description"]
340
  humidity = weather_data["main"]["humidity"]
341
- return f"🌀️ **Weather in {weather_data.get('name', city)}:**\n\nTemperature: {temp}°C\nConditions: {desc}\nHumidity: {humidity}%"
 
342
  else:
343
  return "❌ Could not fetch weather data. Please try again later."
344
 
@@ -349,7 +379,7 @@ class YAHBot:
349
  price = quote.get("05. price", "N/A")
350
  change = quote.get("09. change", "N/A")
351
  change_percent = quote.get("10. change percent", "N/A")
352
- return f"πŸ“ˆ **Apple Stock (AAPL):**\n\nPrice: ${price}\nChange: {change} ({change_percent})"
353
  else:
354
  return "❌ Could not fetch stock data. Please try again later."
355
 
@@ -359,7 +389,17 @@ class YAHBot:
359
  btc_data = crypto_data["bitcoin"]
360
  price = btc_data.get("usd", "N/A")
361
  change = btc_data.get("usd_24h_change", "N/A")
362
- return f"β‚Ώ **Bitcoin Price:**\n\nCurrent: ${price:,.2f}\n24h Change: {change:.2f}%"
 
 
 
 
 
 
 
 
 
 
363
  else:
364
  return "❌ Could not fetch cryptocurrency data. Please try again later."
365
 
@@ -381,7 +421,7 @@ class YAHBot:
381
  if self.model and self.tokenizer:
382
  try:
383
  # Prepare input with context
384
- context = "You are YAH Bot, an AI assistant for YAH Tech. Be helpful, professional and focus on technology, entrepreneurship, and business development."
385
  full_input = f"{context}\n\nConversation:\n" + "\n".join([f"Human: {msg['content']}\nAI: {msg['content']}"
386
  for msg in conversation_history[-3:]]) + f"\nHuman: {user_input}\nAI:"
387
 
@@ -390,7 +430,7 @@ class YAHBot:
390
  with torch.no_grad():
391
  outputs = self.model.generate(
392
  inputs,
393
- max_length=150,
394
  num_return_sequences=1,
395
  temperature=0.7,
396
  do_sample=True,
@@ -401,14 +441,14 @@ class YAHBot:
401
  return response
402
 
403
  except Exception as e:
404
- return f"I encountered an error: {str(e)}. However, I can tell you that at YAH Tech, we're focused on building scalable systems that drive economic growth."
405
 
406
- # Fallback responses
407
  fallback_responses = [
408
- "That's an interesting question! At YAH Tech, we believe in learning, understanding, and creating solutions that matter.",
409
- "I'd be happy to discuss that. As a venture studio, we focus on building technology-driven ventures that create both profit and societal value.",
410
- "Great question! Our approach at YAH Tech is to develop futuristic solutions through careful evaluation and systematic creation.",
411
- f"From my perspective as {PERSONAL_INFO['name']}, I focus on building systems that reshape the economic landscape through technology."
412
  ]
413
  return random.choice(fallback_responses)
414
 
@@ -420,89 +460,93 @@ def initialize_session_state():
420
  st.session_state.bot = YAHBot()
421
  if "conversation_started" not in st.session_state:
422
  st.session_state.conversation_started = False
423
- if "api_status" not in st.session_state:
424
- st.session_state.api_status = {}
425
 
426
  def display_api_status():
427
  """Display API status in sidebar"""
428
- st.sidebar.subheader("API Status")
429
 
430
- # Mock API status for demo
431
  statuses = {
432
- "News API": "βœ… Connected" if API_CONFIG["news_api"]["params"]["apiKey"] != "demo_key" else "⚠️ Demo Mode",
433
- "Weather API": "βœ… Connected" if API_CONFIG["weather_api"]["params"]["appid"] != "demo_key" else "⚠️ Demo Mode",
434
- "Financial API": "βœ… Connected" if API_CONFIG["financial_api"]["params"]["apikey"] != "demo_key" else "⚠️ Demo Mode",
435
- "Crypto API": "βœ… Connected",
436
- "Internal API": "πŸ”Œ Not Connected" # FastAPI server would be separate
437
  }
438
 
439
  for api, status in statuses.items():
440
- color = "🟒" if "βœ…" in status else "🟑" if "⚠️" in status else "πŸ”΄"
441
- st.sidebar.write(f"{color} {api}: {status}")
442
 
443
  def main():
444
  # Page configuration
445
  st.set_page_config(
446
- page_title="YAH Tech Chatbot",
447
- page_icon="πŸ€–",
448
- layout="centered"
 
449
  )
450
 
451
  # Initialize session state
452
  initialize_session_state()
453
 
454
- # Header
455
  col1, col2 = st.columns([1, 4])
456
  with col1:
457
- st.image("https://via.placeholder.com/80/2196f3/ffffff?text=YT", width=80)
458
  with col2:
459
- st.title("YAH Tech Assistant")
460
- st.caption("Powered by AI β€’ Built for Innovation β€’ API-Enabled")
461
 
462
  st.markdown("---")
463
 
464
  # Sidebar
465
  with st.sidebar:
466
- st.header("About YAH Tech")
467
  st.markdown(f"""
468
- **Founder**: {PERSONAL_INFO['name']}
469
- **Role**: {PERSONAL_INFO['role']}
470
 
471
- **Company**: {COMPANY_INFO['name']}
472
- **Focus**: {COMPANY_INFO['type']}
473
- **Stage**: {COMPANY_INFO['stage']}
474
 
475
- **Philosophy**: *{COMPANY_INFO['philosophy']}*
476
  """)
477
 
478
  # API Status
479
  display_api_status()
480
 
481
  st.markdown("---")
482
- st.subheader("API Capabilities")
483
  st.markdown("""
484
- Ask me to:
485
- - **Get tech news** πŸ“°
486
- - **Check weather** 🌀️
487
- - **Stock prices** πŸ“ˆ
488
- - **Crypto data** β‚Ώ
489
- - **YAH Tech info** 🏒
490
- - **Business advice** πŸ’Ό
491
  """)
492
 
493
- st.markdown("---")
494
- st.subheader("Quick Actions")
495
- if st.button("πŸ”„ Test APIs"):
496
- st.info("API testing feature would be implemented here")
497
-
498
- if st.button("πŸ—‘οΈ Clear Chat"):
499
  st.session_state.messages = []
500
  st.session_state.conversation_started = False
501
  st.rerun()
502
 
503
  # Chat interface
504
  if not st.session_state.conversation_started:
505
- st.info(f"πŸ‘‹ Hello! I'm YAH Bot, your AI assistant for everything related to {PERSONAL_INFO['name']} and {COMPANY_INFO['name']}. I can also fetch real-time data through APIs! How can I help you today?")
 
 
 
 
 
 
 
 
 
 
 
506
  st.session_state.conversation_started = True
507
 
508
  # Display chat messages
@@ -511,7 +555,7 @@ def main():
511
  st.markdown(message["content"])
512
 
513
  # Chat input
514
- if prompt := st.chat_input("Ask me about YAH Tech, get news, check weather, or anything else..."):
515
  # Add user message to chat history
516
  st.session_state.messages.append({"role": "user", "content": prompt})
517
  with st.chat_message("user"):
@@ -519,10 +563,15 @@ def main():
519
 
520
  # Generate and display assistant response
521
  with st.chat_message("assistant"):
522
- with st.spinner("πŸ€” Thinking..."):
523
  # Use asyncio to handle async API calls
524
- response = asyncio.run(st.session_state.bot.generate_response(prompt, st.session_state.messages))
525
- st.markdown(response)
 
 
 
 
 
526
 
527
  st.session_state.messages.append({"role": "assistant", "content": response})
528
 
 
9
  import asyncio
10
  import aiohttp
11
  from typing import Optional, List, Dict
12
+ import os
13
 
14
  # Apply nest_asyncio for async operations in Streamlit
15
+ try:
16
+ import nest_asyncio
17
+ nest_asyncio.apply()
18
+ except ImportError:
19
+ pass
20
 
21
+ # Get Hugging Face token from environment variables (set in HF Spaces secrets)
22
+ HUGGINGFACE_TOKEN = os.environ.get("HUGGINGFACE_TOKEN", "")
23
 
24
  if HUGGINGFACE_TOKEN:
25
  try:
 
28
  except Exception as e:
29
  st.error(f"❌ Hugging Face login failed: {e}")
30
 
31
+ # Custom CSS for beautiful silver/sky blue theme
32
  st.markdown("""
33
  <style>
34
  .main {
35
+ background: linear-gradient(135deg, #f8f9fa 0%, #e3f2fd 100%);
36
+ font-family: 'Inter', sans-serif;
37
  }
38
+
39
  .stChatMessage {
40
+ padding: 20px;
41
+ border-radius: 16px;
42
+ margin: 12px 0;
43
+ box-shadow: 0 2px 8px rgba(0,0,0,0.1);
44
+ border: none;
 
45
  }
46
+
47
  /* User message styling */
48
  .stChatMessage:has(div[data-testid="stChatMessageContent"] > div:first-child > div:first-child) {
49
+ background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%);
50
+ border-left: 6px solid #2196f3;
51
  }
52
+
53
  /* Assistant message styling */
54
  .stChatMessage:has(div[data-testid="stChatMessageContent"] > div:first-child > div:last-child) {
55
+ background: linear-gradient(135deg, #ffffff 0%, #f5f5f5 100%);
56
+ border-left: 6px solid #78909c;
57
+ border: 1px solid #e0e0e0;
58
  }
59
+
60
  .stTextInput > div > div > input {
61
  border: 2px solid #90caf9;
62
+ border-radius: 25px;
63
+ padding: 15px 20px;
64
+ font-size: 16px;
65
+ background: white;
66
+ box-shadow: 0 2px 10px rgba(33, 150, 243, 0.1);
67
  }
68
+
69
  .stButton > button {
70
+ background: linear-gradient(135deg, #2196f3 0%, #1976d2 100%);
71
  color: white;
72
  border: none;
73
+ border-radius: 25px;
74
+ padding: 12px 28px;
75
+ font-weight: 600;
76
+ font-size: 16px;
77
+ box-shadow: 0 4px 12px rgba(33, 150, 243, 0.3);
78
+ transition: all 0.3s ease;
79
  }
80
+
81
  .stButton > button:hover {
82
+ transform: translateY(-2px);
83
+ box-shadow: 0 6px 16px rgba(33, 150, 243, 0.4);
84
  }
85
+
86
  .sidebar .sidebar-content {
87
+ background: linear-gradient(180deg, #eceff1 0%, #cfd8dc 100%);
88
+ border-right: 1px solid #b0bec5;
89
  }
90
+
91
  .api-status {
92
+ padding: 12px;
93
+ border-radius: 10px;
94
+ margin: 8px 0;
95
+ font-size: 14px;
96
+ font-weight: 500;
97
  }
98
+
99
  .api-success {
100
+ background: linear-gradient(135deg, #e8f5e8 0%, #c8e6c9 100%);
101
  border-left: 4px solid #4caf50;
102
  }
103
+
104
  .api-error {
105
+ background: linear-gradient(135deg, #ffebee 0%, #ffcdd2 100%);
106
  border-left: 4px solid #f44336;
107
  }
108
+
109
+ .header-gradient {
110
+ background: linear-gradient(135deg, #2196f3 0%, #1976d2 100%);
111
+ -webkit-background-clip: text;
112
+ -webkit-text-fill-color: transparent;
113
+ background-clip: text;
114
+ }
115
  </style>
116
  """, unsafe_allow_html=True)
117
 
 
135
  "stage": "Growth and development, focused on building sustainable processes and systems"
136
  }
137
 
138
+ # API Configuration with environment variables
139
  API_CONFIG = {
140
  "news_api": {
141
  "url": "https://newsapi.org/v2/top-headlines",
 
143
  "country": "us",
144
  "category": "technology",
145
  "pageSize": 5,
146
+ "apiKey": os.environ.get("NEWS_API_KEY", "demo_key")
147
  }
148
  },
149
  "weather_api": {
150
  "url": "https://api.openweathermap.org/data/2.5/weather",
151
  "params": {
152
  "q": "Lagos,NG",
153
+ "appid": os.environ.get("WEATHER_API_KEY", "demo_key"),
154
  "units": "metric"
155
  }
156
  },
 
159
  "params": {
160
  "function": "GLOBAL_QUOTE",
161
  "symbol": "AAPL",
162
+ "apikey": os.environ.get("ALPHA_VANTAGE_KEY", "demo_key")
163
  }
 
 
 
164
  }
165
  }
166
 
 
178
  async def make_async_request(self, url: str, params: dict = None, headers: dict = None):
179
  """Make asynchronous API request"""
180
  try:
181
+ async with self.session.get(url, params=params, headers=headers, timeout=10) as response:
182
  if response.status == 200:
183
  return await response.json()
184
  else:
 
208
  if config["params"]["apiKey"] == "demo_key":
209
  return {
210
  "articles": [
211
+ {"title": "πŸš€ AI Technology Advances in 2024", "description": "Latest breakthroughs in artificial intelligence and machine learning transforming industries..."},
212
+ {"title": "πŸ’Ό Venture Studio Model Gains Popularity", "description": "More entrepreneurs adopting the venture studio approach for scalable business creation..."},
213
+ {"title": "🌍 Economic Impact of Tech Startups", "description": "How technology startups are reshaping global economies and creating new opportunities..."}
214
  ]
215
  }
216
 
 
224
 
225
  if config["params"]["appid"] == "demo_key":
226
  return {
227
+ "weather": [{"description": "clear sky", "main": "Clear"}],
228
+ "main": {"temp": 28, "humidity": 65, "feels_like": 30},
229
+ "name": city,
230
+ "sys": {"country": "NG"}
231
  }
232
 
233
  result = await self.api_client.make_async_request(config["url"], config["params"])
 
241
  if config["params"]["apikey"] == "demo_key":
242
  return {
243
  "Global Quote": {
244
+ "01. symbol": symbol,
245
  "05. price": "185.50",
246
  "09. change": "+1.25",
247
  "10. change percent": "+0.68%"
 
252
  return result
253
 
254
  def get_crypto_data(self, coin: str = "bitcoin"):
255
+ """Get cryptocurrency data"""
256
+ # Using CoinGecko API (no key required for basic usage)
257
  url = f"https://api.coingecko.com/api/v3/simple/price"
258
  params = {
259
  "ids": coin,
 
264
  result = self.api_client.make_sync_request(url, params)
265
  return result
266
 
267
+ # Knowledge base for the AI
268
  KNOWLEDGE_BASE = {
269
  "personal": {
270
+ "who are you": f"🀡 I'm **{PERSONAL_INFO['name']}**, {PERSONAL_INFO['role']}.",
271
+ "what are your goals": f"🎯 My goals include:\nβ€’ {PERSONAL_INFO['goals'][0]}\nβ€’ {PERSONAL_INFO['goals'][1]}\nβ€’ {PERSONAL_INFO['goals'][2]}",
272
+ "what do you do": f"πŸ’Ό I'm the CEO of YAH Tech, focused on **{PERSONAL_INFO['goals'][2]}**.",
273
+ "tell me about yourself": f"🌟 I'm **{PERSONAL_INFO['name']}**, {PERSONAL_INFO['role']}. My mission is to **{PERSONAL_INFO['goals'][0].lower()}** and **{PERSONAL_INFO['goals'][1].lower()}** through innovative technology solutions.",
274
  },
275
  "company": {
276
+ "what is yah tech": f"🏒 **{COMPANY_INFO['name']}** is a {COMPANY_INFO['type']}. Our purpose is to **{COMPANY_INFO['purpose'].lower()}**.",
277
+ "what does yah tech do": f"πŸš€ We specialize in **{COMPANY_INFO['primary_activity'].lower()}**. {COMPANY_INFO['purpose']}.",
278
+ "company philosophy": f"πŸ’‘ Our philosophy is: **'{COMPANY_INFO['philosophy']}'**",
279
+ "company stage": f"πŸ“ˆ We're currently in the **{COMPANY_INFO['stage']}** phase.",
280
+ "venture studio": "🎯 As a venture studio, we don't just build apps - we build complete businesses with scalable systems and futuristic solutions that drive economic growth.",
281
  },
282
  "api_capabilities": {
283
+ "what can you do": "πŸ”§ I can fetch real-time data like:\nβ€’ πŸ“° Latest tech news\nβ€’ 🌀️ Weather information\nβ€’ πŸ“ˆ Stock market data\nβ€’ β‚Ώ Cryptocurrency prices\n\nI also have extensive knowledge about YAH Tech and Adedoyin James!",
284
+ "get news": "πŸ“° I can fetch the latest technology news to keep you updated with industry trends.",
285
+ "weather": "🌀️ I can check weather information for any city worldwide.",
286
+ "stock": "πŸ“ˆ I can get real-time stock market data for major companies.",
287
+ "crypto": "β‚Ώ I can fetch current cryptocurrency prices and market changes.",
288
  }
289
  }
290
 
 
299
  def _load_model(self):
300
  """Load the Hugging Face model"""
301
  try:
302
+ with st.spinner("πŸ”„ Loading YAH Tech AI model..."):
303
  self.tokenizer = AutoTokenizer.from_pretrained(
304
  "Adedoyinjames/YAH-Tech-Chat-Bot",
305
  use_auth_token=HUGGINGFACE_TOKEN if HUGGINGFACE_TOKEN else True
 
309
  use_auth_token=HUGGINGFACE_TOKEN if HUGGINGFACE_TOKEN else True,
310
  torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32
311
  )
312
+ st.success("βœ… YAH Tech AI model loaded successfully!")
313
  except Exception as e:
314
  st.error(f"❌ Failed to load custom model: {e}")
315
  st.info("πŸ”„ Falling back to standard FLAN-T5-small model...")
316
  try:
317
  self.tokenizer = AutoTokenizer.from_pretrained(self.model_name)
318
  self.model = AutoModelForSeq2SeqLM.from_pretrained(self.model_name)
319
+ st.success("βœ… Standard AI model loaded successfully!")
320
  except Exception as e2:
321
+ st.error(f"❌ Failed to load AI model: {e2}")
322
 
323
  def _get_knowledge_response(self, user_input):
324
  """Check if the input matches any knowledge base entries"""
 
346
  if any(word in user_input_lower for word in ["news", "headlines", "tech news"]):
347
  news_data = await self.api_service.get_tech_news()
348
  if "articles" in news_data:
349
+ articles = news_data["articles"][:3]
350
+ response = "πŸ“° **Latest Technology News:**\n\n"
351
  for i, article in enumerate(articles, 1):
352
+ response += f"**{i}. {article.get('title', 'No title')}**\n"
353
  response += f" {article.get('description', 'No description available')}\n\n"
354
  return response
355
  else:
356
  return "❌ Could not fetch news at the moment. Please try again later."
357
 
358
  elif any(word in user_input_lower for word in ["weather", "temperature"]):
 
359
  city = "Lagos"
360
  for word in user_input_lower.split():
361
+ if word not in ["weather", "temperature", "what's", "the", "in", "for"] and len(word) > 2:
362
  city = word.capitalize()
363
  break
364
 
365
  weather_data = await self.api_service.get_weather(city)
366
  if "weather" in weather_data:
367
  temp = weather_data["main"]["temp"]
368
+ desc = weather_data["weather"][0]["description"].title()
369
  humidity = weather_data["main"]["humidity"]
370
+ feels_like = weather_data["main"].get("feels_like", temp)
371
+ return f"🌀️ **Weather in {weather_data.get('name', city)}:**\n\nβ€’ Temperature: **{temp}Β°C** (Feels like: {feels_like}Β°C)\nβ€’ Conditions: **{desc}**\nβ€’ Humidity: **{humidity}%**"
372
  else:
373
  return "❌ Could not fetch weather data. Please try again later."
374
 
 
379
  price = quote.get("05. price", "N/A")
380
  change = quote.get("09. change", "N/A")
381
  change_percent = quote.get("10. change percent", "N/A")
382
+ return f"πŸ“ˆ **Apple Stock (AAPL):**\n\nβ€’ Current Price: **${price}**\nβ€’ Change: **{change}** ({change_percent})"
383
  else:
384
  return "❌ Could not fetch stock data. Please try again later."
385
 
 
389
  btc_data = crypto_data["bitcoin"]
390
  price = btc_data.get("usd", "N/A")
391
  change = btc_data.get("usd_24h_change", "N/A")
392
+ if isinstance(price, (int, float)):
393
+ price_str = f"${price:,.2f}"
394
+ else:
395
+ price_str = str(price)
396
+
397
+ if isinstance(change, (int, float)):
398
+ change_str = f"{change:.2f}%"
399
+ else:
400
+ change_str = str(change)
401
+
402
+ return f"β‚Ώ **Bitcoin Price:**\n\nβ€’ Current: **{price_str}**\nβ€’ 24h Change: **{change_str}**"
403
  else:
404
  return "❌ Could not fetch cryptocurrency data. Please try again later."
405
 
 
421
  if self.model and self.tokenizer:
422
  try:
423
  # Prepare input with context
424
+ context = f"You are YAH Bot, an AI assistant for {COMPANY_INFO['name']}. You represent {PERSONAL_INFO['name']}, {PERSONAL_INFO['role']}. Be helpful, professional and focus on technology, entrepreneurship, venture studios, and business development. Our philosophy: {COMPANY_INFO['philosophy']}"
425
  full_input = f"{context}\n\nConversation:\n" + "\n".join([f"Human: {msg['content']}\nAI: {msg['content']}"
426
  for msg in conversation_history[-3:]]) + f"\nHuman: {user_input}\nAI:"
427
 
 
430
  with torch.no_grad():
431
  outputs = self.model.generate(
432
  inputs,
433
+ max_length=200,
434
  num_return_sequences=1,
435
  temperature=0.7,
436
  do_sample=True,
 
441
  return response
442
 
443
  except Exception as e:
444
+ return f"I encountered an error: {str(e)}. However, I can tell you that at YAH Tech, we're focused on building scalable systems that drive economic growth through our venture studio model."
445
 
446
+ # Fallback responses
447
  fallback_responses = [
448
+ f"🌟 That's an interesting question! At {COMPANY_INFO['name']}, we believe in **{COMPANY_INFO['philosophy']}** to create solutions that matter.",
449
+ f"πŸš€ I'd be happy to discuss that. As a venture studio, we focus on building technology-driven ventures that create both **profit and societal value**.",
450
+ f"πŸ’‘ Great question! Our approach at {COMPANY_INFO['name']} is to develop futuristic solutions through careful evaluation and systematic creation.",
451
+ f"🎯 From my perspective as {PERSONAL_INFO['name']}, I focus on building systems that reshape the economic landscape through innovative technology and scalable business models."
452
  ]
453
  return random.choice(fallback_responses)
454
 
 
460
  st.session_state.bot = YAHBot()
461
  if "conversation_started" not in st.session_state:
462
  st.session_state.conversation_started = False
 
 
463
 
464
  def display_api_status():
465
  """Display API status in sidebar"""
466
+ st.sidebar.subheader("πŸ”Œ API Status")
467
 
468
+ # Check API status based on environment variables
469
  statuses = {
470
+ "πŸ€– AI Model": "βœ… Connected" if HUGGINGFACE_TOKEN else "⚠️ Using Standard Model",
471
+ "πŸ“° News API": "βœ… Connected" if os.environ.get("NEWS_API_KEY") and os.environ.get("NEWS_API_KEY") != "demo_key" else "🟑 Demo Mode",
472
+ "🌀️ Weather API": "βœ… Connected" if os.environ.get("WEATHER_API_KEY") and os.environ.get("WEATHER_API_KEY") != "demo_key" else "🟑 Demo Mode",
473
+ "πŸ“ˆ Stock API": "βœ… Connected" if os.environ.get("ALPHA_VANTAGE_KEY") and os.environ.get("ALPHA_VANTAGE_KEY") != "demo_key" else "🟑 Demo Mode",
474
+ "β‚Ώ Crypto API": "βœ… Connected"
475
  }
476
 
477
  for api, status in statuses.items():
478
+ st.sidebar.write(f"{api}: {status}")
 
479
 
480
  def main():
481
  # Page configuration
482
  st.set_page_config(
483
+ page_title="YAH Tech Assistant",
484
+ page_icon="πŸš€",
485
+ layout="centered",
486
+ initial_sidebar_state="expanded"
487
  )
488
 
489
  # Initialize session state
490
  initialize_session_state()
491
 
492
+ # Header with beautiful gradient
493
  col1, col2 = st.columns([1, 4])
494
  with col1:
495
+ st.image("https://via.placeholder.com/100/2196f3/ffffff?text=YT", width=100)
496
  with col2:
497
+ st.markdown('<h1 class="header-gradient">YAH Tech Assistant</h1>', unsafe_allow_html=True)
498
+ st.caption("πŸš€ Powered by AI β€’ πŸ’Ό Venture Studio β€’ 🌍 Economic Innovation")
499
 
500
  st.markdown("---")
501
 
502
  # Sidebar
503
  with st.sidebar:
504
+ st.header("🏒 About YAH Tech")
505
  st.markdown(f"""
506
+ **πŸ‘€ Founder**: {PERSONAL_INFO['name']}
507
+ **πŸ’Ό Role**: {PERSONAL_INFO['role']}
508
 
509
+ **🏒 Company**: {COMPANY_INFO['name']}
510
+ **🎯 Focus**: {COMPANY_INFO['type']}
511
+ **πŸ“ˆ Stage**: {COMPANY_INFO['stage']}
512
 
513
+ **πŸ’‘ Philosophy**: *{COMPANY_INFO['philosophy']}*
514
  """)
515
 
516
  # API Status
517
  display_api_status()
518
 
519
  st.markdown("---")
520
+ st.subheader("πŸ”§ Quick Actions")
521
  st.markdown("""
522
+ Try asking me:
523
+ - *"What's the latest tech news?"* πŸ“°
524
+ - *"Weather in Lagos"* 🌀️
525
+ - *"Apple stock price"* πŸ“ˆ
526
+ - *"Bitcoin price"* β‚Ώ
527
+ - *"Tell me about YAH Tech"* 🏒
528
+ - *"What are your goals?"* 🎯
529
  """)
530
 
531
+ if st.button("πŸ—‘οΈ Clear Chat History", use_container_width=True):
 
 
 
 
 
532
  st.session_state.messages = []
533
  st.session_state.conversation_started = False
534
  st.rerun()
535
 
536
  # Chat interface
537
  if not st.session_state.conversation_started:
538
+ welcome_msg = f"""
539
+ πŸ‘‹ **Hello! I'm YAH Bot, your AI assistant for everything related to {PERSONAL_INFO['name']} and {COMPANY_INFO['name']}!**
540
+
541
+ I can help you with:
542
+ β€’ πŸ“Š Company information and venture studio details
543
+ β€’ 🎯 Adedoyin's vision and goals
544
+ β€’ 🌐 Real-time data (news, weather, stocks, crypto)
545
+ β€’ πŸ’‘ Business and technology insights
546
+
547
+ **How can I assist you today?** πŸš€
548
+ """
549
+ st.info(welcome_msg)
550
  st.session_state.conversation_started = True
551
 
552
  # Display chat messages
 
555
  st.markdown(message["content"])
556
 
557
  # Chat input
558
+ if prompt := st.chat_input("πŸ’¬ Ask me about YAH Tech, get real-time data, or anything else..."):
559
  # Add user message to chat history
560
  st.session_state.messages.append({"role": "user", "content": prompt})
561
  with st.chat_message("user"):
 
563
 
564
  # Generate and display assistant response
565
  with st.chat_message("assistant"):
566
+ with st.spinner("πŸ€” Processing your request..."):
567
  # Use asyncio to handle async API calls
568
+ try:
569
+ response = asyncio.run(st.session_state.bot.generate_response(prompt, st.session_state.messages))
570
+ st.markdown(response)
571
+ except Exception as e:
572
+ error_msg = f"⚠️ I encountered an issue: {str(e)}\n\nBut at YAH Tech, we always find solutions! Feel free to ask me something else about our venture studio or business philosophy."
573
+ st.markdown(error_msg)
574
+ response = error_msg
575
 
576
  st.session_state.messages.append({"role": "assistant", "content": response})
577