Stanley03 commited on
Commit
9f0e3fa
Β·
verified Β·
1 Parent(s): 52d0032

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +194 -499
app.py CHANGED
@@ -1,23 +1,17 @@
1
- from flask import Flask, request, jsonify, send_file
2
  from flask_cors import CORS
3
- from transformers import AutoModelForCausalLM, AutoTokenizer, TextStreamer
4
- from knowledgebase import KiswahiliKnowledgeBase, enhance_with_kiswahili
5
- import torch
6
  import time
7
- import re
8
  import logging
9
- from threading import Thread
10
- import queue
11
  import io
12
  import base64
13
  import requests
14
- from PIL import Image, ImageDraw, ImageFont
15
- import os
16
  import random
17
  import tempfile
18
  import cv2
19
  import numpy as np
20
- from typing import Optional, Dict, Any, List
21
 
22
  # Configure logging
23
  logging.basicConfig(level=logging.INFO)
@@ -26,29 +20,20 @@ logger = logging.getLogger(__name__)
26
  app = Flask(__name__)
27
  CORS(app)
28
 
29
- # Initialize Kiswahili Knowledge Base
30
- kb = KiswahiliKnowledgeBase()
31
-
32
- model = None
33
- tokenizer = None
34
- model_loaded = False
35
-
36
  # Hugging Face Configuration
37
  HF_TOKEN = os.getenv('HF_TOKEN', '')
38
  HF_API_URLS = {
39
- "text": "https://api-inference.huggingface.co/models/Qwen/Qwen2.5-7B-Instruct",
40
- "image": "https://api-inference.huggingface.co/models/runwayml/stable-diffusion-v1-5",
41
- "fast_image": "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-2-1",
42
- "video": "https://api-inference.huggingface.co/models/cerspense/zeroscope_v2_576w",
43
- "image_to_video": "https://api-inference.huggingface.co/models/stabilityai/stable-video-diffusion-img2vid-xt"
44
  }
45
 
46
  # Performance optimizations
47
  response_cache = {}
48
  CACHE_SIZE = 100
49
- request_timeout = 45
50
 
51
- # Advanced System Prompt (Enhanced for Video Generation)
52
  STANLEY_AI_SYSTEM = """You are STANLEY AI - an advanced AI assistant created by Stanley Samwel Owino, a Machine Learning Engineer from Kenya.
53
 
54
  CORE IDENTITY:
@@ -68,8 +53,7 @@ KEY CAPABILITIES:
68
  VIDEO GENERATION SKILLS:
69
  - I can create 4-second videos from text descriptions
70
  - I can generate cultural theme videos (safari, dance, market, etc.)
71
- - I can create animations from images
72
- - I can make slideshows from multiple images
73
  - All video generation is FREE using Hugging Face
74
 
75
  KISWAHILI INTEGRATION:
@@ -94,66 +78,8 @@ RESPONSE STYLE:
94
 
95
  Remember: You represent the intersection of cutting-edge AI technology and rich African cultural heritage."""
96
 
97
- def load_model():
98
- """Load model with Hugging Face optimizations"""
99
- global model, tokenizer, model_loaded
100
-
101
- if model_loaded:
102
- return
103
-
104
- logger.info("πŸš€ Loading STANLEY AI Model from Hugging Face...")
105
-
106
- try:
107
- # Use a faster, smaller model for better performance
108
- model_name = "microsoft/DialoGPT-small" # More reliable and smaller
109
-
110
- tokenizer = AutoTokenizer.from_pretrained(
111
- model_name,
112
- cache_dir="./model_cache"
113
- )
114
-
115
- if tokenizer.pad_token is None:
116
- tokenizer.pad_token = tokenizer.eos_token
117
-
118
- model = AutoModelForCausalLM.from_pretrained(
119
- model_name,
120
- torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
121
- device_map="auto" if torch.cuda.is_available() else None,
122
- cache_dir="./model_cache",
123
- low_cpu_mem_usage=True
124
- )
125
-
126
- # Optimize for inference
127
- model.eval()
128
- model_loaded = True
129
- logger.info("βœ… STANLEY AI Model loaded successfully!")
130
-
131
- except Exception as e:
132
- logger.error(f"❌ Error loading model: {e}")
133
- model_loaded = False
134
- logger.info("πŸ”„ Using Hugging Face API fallback for text generation")
135
-
136
- load_model()
137
-
138
- class TextGenerationStream:
139
- def __init__(self):
140
- self.text_queue = queue.Queue()
141
-
142
- def put(self, text):
143
- self.text_queue.put(text)
144
-
145
- def end(self):
146
- self.text_queue.put(None)
147
-
148
- def generate(self):
149
- while True:
150
- text = self.text_queue.get()
151
- if text is None:
152
- break
153
- yield text
154
-
155
  # ============================================================================
156
- # ENHANCED DETECTION FUNCTIONS WITH VIDEO SUPPORT
157
  # ============================================================================
158
 
159
  def detect_kiswahili_context(text):
@@ -172,8 +98,7 @@ def detect_image_request(text):
172
  image_triggers = [
173
  'generate image', 'create image', 'make a picture', 'draw',
174
  'show me an image', 'visualize', 'picture of', 'image of',
175
- 'generate a picture', 'create a picture', 'make art of',
176
- 'paint a picture of', 'illustrate', 'draw me'
177
  ]
178
  text_lower = text.lower()
179
  return any(trigger in text_lower for trigger in image_triggers)
@@ -183,10 +108,7 @@ def detect_video_request(text):
183
  video_triggers = [
184
  'generate video', 'create video', 'make a video', 'video of',
185
  'animate', 'animation', 'moving picture', 'motion picture',
186
- 'video generation', 'create animation', 'make animation',
187
- 'video clip', 'short video', 'motion graphics', 'cinematic',
188
- 'film', 'movie', 'moving image', 'dynamic image', 'animated video',
189
- 'make a film', 'create movie', 'produce video', 'animate this'
190
  ]
191
  text_lower = text.lower()
192
  return any(trigger in text_lower for trigger in video_triggers)
@@ -199,42 +121,21 @@ def extract_prompt(text, request_type="image"):
199
  remove_phrases = [
200
  'generate image of', 'create image of', 'make a picture of',
201
  'show me an image of', 'visualize', 'draw', 'picture of',
202
- 'generate a picture of', 'create a picture of', 'make art of',
203
- 'paint a picture of', 'illustrate', 'draw me', 'show picture of'
204
  ]
205
  else: # video
206
  remove_phrases = [
207
  'generate video of', 'create video of', 'make a video of',
208
  'create animation of', 'make animation of', 'animate',
209
- 'generate animation of', 'video of', 'animation of',
210
- 'make a film about', 'create a film about', 'produce video of'
211
  ]
212
 
213
  prompt = text_lower
214
  for phrase in remove_phrases:
215
  prompt = prompt.replace(phrase, '')
216
 
217
- # Remove question words
218
- question_words = ['how to', 'what is', 'can you', 'could you', 'would you', 'please']
219
- for word in question_words:
220
- if prompt.startswith(word):
221
- prompt = prompt[len(word):].strip()
222
-
223
  return prompt.strip().capitalize()
224
 
225
- def enhance_with_cultural_context(response, user_message):
226
- """Enhance response with Kiswahili cultural elements"""
227
- if detect_kiswahili_context(user_message):
228
- enhanced_response = kb.generate_kiswahili_response(response)
229
-
230
- # Add cultural proverb if relevant
231
- if any(word in user_message.lower() for word in ['wisdom', 'advice', 'life lesson', 'philosophy']):
232
- proverb = kb.get_random_proverb()
233
- enhanced_response += f"\n\n🌍 **Cultural Wisdom**: {proverb}"
234
-
235
- return enhanced_response
236
- return response
237
-
238
  def get_cached_response(user_message):
239
  """Get cached response"""
240
  cache_key = user_message.lower().strip()[:100]
@@ -247,21 +148,43 @@ def set_cached_response(user_message, response):
247
  response_cache.pop(next(iter(response_cache)))
248
  response_cache[cache_key] = response
249
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  # ============================================================================
251
  # TEXT GENERATION FUNCTIONS
252
  # ============================================================================
253
 
254
- def generate_with_huggingface_api(messages):
255
- """Use Hugging Face Inference API for faster responses"""
256
  try:
257
  headers = {
258
  "Authorization": f"Bearer {HF_TOKEN}",
259
  "Content-Type": "application/json"
260
  }
261
 
262
- # Use GPT-2 as fallback (more reliable)
263
  payload = {
264
- "inputs": messages[-1]["content"], # Last user message
265
  "parameters": {
266
  "max_new_tokens": 300,
267
  "temperature": 0.7,
@@ -272,7 +195,7 @@ def generate_with_huggingface_api(messages):
272
  }
273
 
274
  response = requests.post(
275
- "https://api-inference.huggingface.co/models/gpt2",
276
  headers=headers,
277
  json=payload,
278
  timeout=request_timeout
@@ -290,80 +213,68 @@ def generate_with_huggingface_api(messages):
290
  logger.error(f"HF API error: {e}")
291
  return None
292
 
293
- def generate_comprehensive_response(user_message, stream=False):
294
- """Generate responses with fallback to Hugging Face API"""
295
 
296
  # Check cache first
297
  cached_response = get_cached_response(user_message)
298
  if cached_response:
299
  return cached_response
300
 
301
- # Check for common questions first
302
  common_responses = {
303
  'hello': 'Habari! Stanley AI hapa. Ninaweza kukusaidia nini leo?',
304
  'hi': 'Habari! Karibu kwa Stanley AI. How can I help you today?',
305
  'who created you': 'I was created by Stanley Samwel Owino, a Machine Learning Engineer from Kenya.',
306
  'what can you do': 'I can: 1) Answer questions, 2) Generate images, 3) Create videos, 4) Teach Kiswahili, 5) Share cultural wisdom.',
307
- 'video generation': 'I can create FREE videos! Try saying "generate video of African sunset" or use the video generation endpoint.',
308
- 'make a video': 'Sure! Describe what you want: "create video of wildlife" or use the video generation feature.'
 
 
 
 
 
 
 
 
 
 
309
  }
310
 
311
  msg_lower = user_message.lower().strip()
 
 
312
  if msg_lower in common_responses:
313
  response = common_responses[msg_lower]
314
  set_cached_response(user_message, response)
315
  return response
316
 
317
- # Try local model first
318
- if model_loaded and model is not None:
319
- try:
320
- system_prompt = STANLEY_AI_SYSTEM
321
- if detect_kiswahili_context(user_message):
322
- system_prompt += "\n\nSPECIAL NOTE: Integrate Kiswahili phrases naturally."
323
-
324
- # Format messages for DialoGPT
325
- chat_history_ids = None
326
- new_user_input_ids = tokenizer.encode(user_message + tokenizer.eos_token, return_tensors='pt')
327
-
328
- # Generate response
329
- with torch.no_grad():
330
- chat_history_ids = model.generate(
331
- new_user_input_ids,
332
- max_length=1000,
333
- pad_token_id=tokenizer.eos_token_id,
334
- temperature=0.7,
335
- do_sample=True,
336
- top_p=0.9
337
- )
338
-
339
- response = tokenizer.decode(chat_history_ids[:, new_user_input_ids.shape[-1]:][0], skip_special_tokens=True)
340
- enhanced_response = enhance_with_cultural_context(response.strip(), user_message)
341
-
342
- # Cache the response
343
- set_cached_response(user_message, enhanced_response)
344
- return enhanced_response
345
-
346
- except Exception as e:
347
- logger.error(f"Local model error: {e}")
348
 
349
- # Fallback to Hugging Face API
350
- logger.info("πŸ”„ Using Hugging Face API for response")
351
- api_response = generate_with_huggingface_api([
352
- {"role": "user", "content": f"{STANLEY_AI_SYSTEM}\n\nUser: {user_message}"}
353
- ])
354
 
355
  if api_response:
356
- enhanced_response = enhance_with_cultural_context(api_response.strip(), user_message)
 
357
  set_cached_response(user_message, enhanced_response)
358
  return enhanced_response
359
 
360
- # Final fallback
361
  fallback_responses = [
362
  "Pole! I'm experiencing high demand. Please try again in a moment.",
363
  "Asante kwa kuwasiliana! Nina shida ya kiufundi. Tafadhali jaribu tena.",
364
  "Habari yako? Samahani, sijaweza kujibu swali lako kwa sasa."
365
  ]
366
- return random.choice(fallback_responses)
 
 
 
367
 
368
  # ============================================================================
369
  # IMAGE GENERATION FUNCTIONS
@@ -371,14 +282,14 @@ def generate_comprehensive_response(user_message, stream=False):
371
 
372
  def generate_image_huggingface(prompt, retry_count=2):
373
  """Generate images using Hugging Face Inference API"""
374
- headers = {"Authorization": f"Bearer {HF_TOKEN}"}
375
 
376
  for attempt in range(retry_count):
377
  try:
378
- logger.info(f"🎨 Generating image (attempt {attempt + 1}): {prompt[:50]}...")
379
 
380
  response = requests.post(
381
- HF_API_URLS["fast_image"],
382
  headers=headers,
383
  json={"inputs": prompt},
384
  timeout=60
@@ -394,7 +305,6 @@ def generate_image_huggingface(prompt, retry_count=2):
394
  return f"data:image/png;base64,{img_str}"
395
 
396
  elif response.status_code == 503:
397
- # Model is loading, wait and retry
398
  wait_time = (attempt + 1) * 5
399
  logger.info(f"⏳ Model loading, waiting {wait_time}s...")
400
  time.sleep(wait_time)
@@ -404,9 +314,6 @@ def generate_image_huggingface(prompt, retry_count=2):
404
  logger.error(f"❌ HF Image API error: {response.status_code}")
405
  continue
406
 
407
- except requests.exceptions.Timeout:
408
- logger.warning(f"⏰ Request timeout, attempt {attempt + 1}")
409
- continue
410
  except Exception as e:
411
  logger.error(f"❌ Image generation error: {e}")
412
  break
@@ -414,7 +321,7 @@ def generate_image_huggingface(prompt, retry_count=2):
414
  return None
415
 
416
  def generate_image_fallback(prompt):
417
- """Create simple placeholder images with text"""
418
  try:
419
  width, height = 512, 512
420
  img = Image.new('RGB', (width, height), color=(
@@ -425,25 +332,13 @@ def generate_image_fallback(prompt):
425
 
426
  draw = ImageDraw.Draw(img)
427
 
428
- # Add some simple shapes
429
  for _ in range(5):
430
  x1, y1 = random.randint(0, width), random.randint(0, height)
431
  x2, y2 = random.randint(x1, width), random.randint(y1, height)
432
  color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
433
  draw.rectangle([x1, y1, x2, y2], outline=color, width=3)
434
 
435
- # Add text
436
- try:
437
- font = ImageFont.truetype("arial.ttf", 20)
438
- except:
439
- font = ImageFont.load_default()
440
-
441
- # Truncate long prompts
442
- display_text = prompt[:50] + "..." if len(prompt) > 50 else prompt
443
- text_color = (255, 255, 255) if sum(img.getpixel((width//2, height//2))) < 384 else (0, 0, 0)
444
-
445
- draw.text((width//2, height//2), display_text, fill=text_color, font=font, anchor="mm")
446
-
447
  # Convert to base64
448
  buffered = io.BytesIO()
449
  img.save(buffered, format="PNG")
@@ -455,18 +350,17 @@ def generate_image_fallback(prompt):
455
  return None
456
 
457
  def enhance_prompt_with_kiswahili(prompt):
458
- """Add cultural context to image prompts"""
459
- if detect_kiswahili_context(prompt):
460
  enhancements = [
461
  "East African style", "vibrant African colors", "African landscape",
462
- "cultural elements", "traditional patterns", "warm sunset colors",
463
- "savanna background", "rich cultural symbolism"
464
  ]
465
  return f"{prompt}, {random.choice(enhancements)}"
466
  return prompt
467
 
468
  # ============================================================================
469
- # FREE VIDEO GENERATION FUNCTIONS
470
  # ============================================================================
471
 
472
  class FreeVideoGenerator:
@@ -478,7 +372,7 @@ class FreeVideoGenerator:
478
  self.max_retries = 2
479
 
480
  def generate_text_to_video(self, prompt: str) -> Optional[str]:
481
- """Generate video from text prompt using FREE Hugging Face API"""
482
  headers = {"Authorization": f"Bearer {self.hf_token}"} if self.hf_token else {}
483
 
484
  # Enhance prompt for better video results
@@ -531,14 +425,14 @@ class FreeVideoGenerator:
531
 
532
  def enhance_video_prompt(self, prompt: str) -> str:
533
  """Enhance video prompts with cinematic context"""
534
- cinematic_enhancements = [
535
- "cinematic, 8k, ultra detailed, high quality, masterpiece",
536
- "epic, dramatic lighting, film grain, cinematic shot, professional",
537
- "beautiful, stunning, visually striking, vivid colors, trending"
538
  ]
539
 
540
  enhanced = prompt
541
- enhanced += f", {random.choice(cinematic_enhancements)}"
542
 
543
  # Add cultural context for African themes
544
  if any(word in prompt.lower() for word in ['africa', 'kenya', 'tanzania', 'safari', 'wildlife']):
@@ -549,14 +443,13 @@ class FreeVideoGenerator:
549
  return enhanced
550
 
551
  def create_cultural_video(self, theme: str, style: str = "animated") -> Optional[str]:
552
- """Create videos with Kiswahili cultural themes"""
553
  cultural_themes = {
554
  "safari": "African safari sunset with elephants and giraffes, majestic savanna landscape",
555
  "dance": "Traditional Maasai warriors dancing, vibrant colors, cultural celebration",
556
  "market": "Busy African market scene, vibrant colors, people trading goods",
557
  "coastal": "Swahili coast with traditional dhows sailing, Indian Ocean waves",
558
- "wildlife": "African wildlife documentary style, lions hunting on savanna",
559
- "village": "Traditional African village life, community activities, sunset"
560
  }
561
 
562
  base_prompt = cultural_themes.get(theme, f"African {theme}, cultural, vibrant")
@@ -576,7 +469,7 @@ class FreeVideoGenerator:
576
  with tempfile.TemporaryDirectory() as tmpdir:
577
  # Create frames with text
578
  fps = 10
579
- duration = 3 # seconds
580
  total_frames = fps * duration
581
  height, width = 320, 576
582
 
@@ -584,20 +477,18 @@ class FreeVideoGenerator:
584
  fourcc = cv2.VideoWriter_fourcc(*'mp4v')
585
  out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
586
 
587
- # Create gradient background colors
588
  colors = [
589
  (41, 128, 185), # Blue
590
  (39, 174, 96), # Green
591
  (142, 68, 173), # Purple
592
- (230, 126, 34), # Orange
593
- (231, 76, 60) # Red
594
  ]
595
 
596
  for frame_num in range(total_frames):
597
  # Create gradient background
598
  frame = np.zeros((height, width, 3), dtype=np.uint8)
599
 
600
- # Select color based on frame
601
  color_idx = (frame_num // (total_frames // len(colors))) % len(colors)
602
  bg_color = colors[color_idx]
603
 
@@ -612,10 +503,10 @@ class FreeVideoGenerator:
612
  frame[i, :, 1] = g
613
  frame[i, :, 2] = r
614
 
615
- # Add text with animation
616
  font = cv2.FONT_HERSHEY_SIMPLEX
617
 
618
- # Calculate text size and position
619
  text_size = cv2.getTextSize(text, font, 1, 2)[0]
620
  text_x = (width - text_size[0]) // 2
621
  text_y = (height + text_size[1]) // 2
@@ -664,26 +555,20 @@ def home():
664
  "role": "Machine Learning Engineer",
665
  "location": "Kenya, East Africa",
666
  "features": [
667
- "Hugging Face Optimized",
668
- "Fast Text Generation",
669
- "FREE Image Generation",
670
- "FREE Video Generation", # NEW
671
- "Kiswahili Integration",
672
- "Cultural Knowledge",
673
- "Response Caching",
674
- "API Fallbacks"
675
- ],
676
- "video_capabilities": [ # NEW
677
- "Text-to-Video (FREE)",
678
- "Cultural Theme Videos",
679
- "Text Animations",
680
- "576x320 Resolution",
681
- "4-second videos"
682
  ],
683
  "status": "active",
684
- "model": "DialoGPT + HF Inference",
685
- "image_generation": "Hugging Face API",
686
- "video_generation": "Hugging Face FREE API" # NEW
 
 
 
 
687
  })
688
 
689
  @app.route('/api/chat', methods=['POST'])
@@ -694,73 +579,65 @@ def chat():
694
  user_message = data.get('message', '')
695
 
696
  if not user_message:
697
- return jsonify({"error": "Tafadhali provide a message"}), 400
698
 
699
  logger.info(f"πŸ’¬ Processing: {user_message[:50]}...")
700
 
701
- # Check if user wants to generate an image
702
  if detect_image_request(user_message):
703
- image_prompt = extract_prompt(user_message, "image")
704
- enhanced_prompt = enhance_prompt_with_kiswahili(image_prompt)
705
 
706
  return jsonify({
707
- "response": f"🎨 I'll generate an image for: '{enhanced_prompt}'. Use the image generation feature!",
708
- "image_suggestion": enhanced_prompt,
709
  "status": "success",
710
- "suggest_image": True,
711
- "response_time": round(time.time() - start_time, 2)
712
  })
713
 
714
- # Check if user wants to generate a video
715
  if detect_video_request(user_message):
716
- video_prompt = extract_prompt(user_message, "video")
717
 
718
  return jsonify({
719
- "response": f"🎬 I can create a video for: '{video_prompt}'. Use the video generation feature!",
720
- "video_suggestion": video_prompt,
721
  "status": "success",
722
- "suggest_video": True,
723
- "response_time": round(time.time() - start_time, 2)
724
  })
725
 
726
  response = generate_comprehensive_response(user_message)
727
  response_time = round(time.time() - start_time, 2)
728
 
729
- has_kiswahili = detect_kiswahili_context(response)
730
-
731
  return jsonify({
732
  "response": response,
733
  "status": "success",
734
  "response_time": response_time,
735
  "word_count": len(response.split()),
736
- "model": "STANLEY-AI-HF",
737
- "cultural_context": has_kiswahili,
738
- "language": "en+sw" if has_kiswahili else "en",
739
- "cached": get_cached_response(user_message) is not None,
740
  "creator": "Stanley Samwel Owino"
741
  })
742
 
743
  except Exception as e:
744
  logger.error(f"Chat error: {e}")
745
  return jsonify({
746
- "error": f"Pole! Processing error: {str(e)}",
747
  "status": "error"
748
  }), 500
749
 
750
  @app.route('/api/generate-image', methods=['POST'])
751
  def generate_image_endpoint():
752
- """Generate images using Hugging Face"""
753
  try:
754
  start_time = time.time()
755
  data = request.get_json()
756
  prompt = data.get('prompt', '')
757
 
758
  if not prompt:
759
- return jsonify({"error": "Tafadhali provide a prompt"}), 400
760
 
761
- # Enhance prompt with cultural context
762
  enhanced_prompt = enhance_prompt_with_kiswahili(prompt)
763
-
764
  logger.info(f"🎨 Generating image: {enhanced_prompt[:50]}...")
765
 
766
  # Generate image
@@ -780,93 +657,31 @@ def generate_image_endpoint():
780
  "status": "success",
781
  "generation_time": generation_time,
782
  "provider": "hugging_face",
783
- "cultural_enhancement": enhanced_prompt != prompt,
784
- "creator": "Stanley Samwel Owino"
785
- })
786
- else:
787
- return jsonify({
788
- "error": "Pole! Image generation service is busy",
789
- "status": "error",
790
- "suggestion": "Try again in a moment or use a simpler description"
791
- }), 500
792
-
793
- except Exception as e:
794
- logger.error(f"Image endpoint error: {e}")
795
- return jsonify({
796
- "error": f"Pole! Image generation failed: {str(e)}",
797
- "status": "error"
798
- }), 500
799
-
800
- @app.route('/api/generate-cultural-image', methods=['POST'])
801
- def generate_cultural_image():
802
- """Generate images with specific Kiswahili cultural themes"""
803
- try:
804
- data = request.get_json()
805
- theme = data.get('theme', '')
806
- style = data.get('style', 'vibrant')
807
-
808
- if not theme:
809
- return jsonify({"error": "Tafadhali provide a theme"}), 400
810
-
811
- # Cultural prompt templates
812
- cultural_templates = {
813
- 'safari': f"African savanna landscape with {theme}, acacia trees, warm sunset, majestic",
814
- 'wildlife': f"African wildlife {theme}, natural habitat, detailed, realistic, beautiful",
815
- 'culture': f"East African cultural scene {theme}, traditional, vibrant colors, community",
816
- 'coastal': f"Swahili coast {theme}, Indian Ocean, dhows, traditional architecture",
817
- 'lion_king': f"Lion King inspired {theme}, emotional, Disney style, African elements"
818
- }
819
-
820
- base_template = cultural_templates.get(style, f"East African {theme}, cultural, vibrant")
821
-
822
- # Style modifiers
823
- modifiers = {
824
- 'vibrant': 'vibrant colors, highly detailed, 4K resolution',
825
- 'realistic': 'photorealistic, detailed, realistic lighting',
826
- 'artistic': 'painterly, artistic, brush strokes, creative',
827
- 'traditional': 'traditional African art, symbolic, patterns'
828
- }
829
-
830
- final_prompt = f"{base_template}, {modifiers.get(style, 'vibrant colors')}"
831
-
832
- image_data = generate_image_huggingface(final_prompt)
833
-
834
- if image_data:
835
- return jsonify({
836
- "image": image_data,
837
- "theme": theme,
838
- "style": style,
839
- "prompt": final_prompt,
840
- "status": "success",
841
- "cultural_context": "kiswahili_theme",
842
  "creator": "Stanley Samwel Owino"
843
  })
844
  else:
845
  return jsonify({
846
- "error": "Pole! Cultural image generation failed",
847
  "status": "error"
848
  }), 500
849
 
850
  except Exception as e:
 
851
  return jsonify({
852
- "error": f"Pole! Cultural image error: {str(e)}",
853
  "status": "error"
854
  }), 500
855
 
856
- # ============================================================================
857
- # VIDEO GENERATION ROUTES (NEW)
858
- # ============================================================================
859
-
860
  @app.route('/api/generate-video', methods=['POST'])
861
  def generate_video_endpoint():
862
- """Generate FREE videos from text prompts"""
863
  try:
864
  start_time = time.time()
865
  data = request.get_json()
866
  prompt = data.get('prompt', '')
867
 
868
  if not prompt:
869
- return jsonify({"error": "Tafadhali provide a video prompt"}), 400
870
 
871
  logger.info(f"🎬 Generating video: {prompt[:50]}...")
872
 
@@ -883,71 +698,60 @@ def generate_video_endpoint():
883
  "generation_time": generation_time,
884
  "provider": "hugging_face_free",
885
  "format": "mp4",
886
- "duration": "3-4 seconds",
887
  "resolution": "576x320",
888
  "creator": "Stanley Samwel Owino"
889
  })
890
  else:
891
  return jsonify({
892
- "error": "Pole! Video generation service is busy. Try again in a moment.",
893
  "status": "error",
894
- "suggestion": "Try a simpler description or use image generation instead"
895
  }), 500
896
 
897
  except Exception as e:
898
  logger.error(f"Video endpoint error: {e}")
899
  return jsonify({
900
- "error": f"Pole! Video generation failed: {str(e)}",
901
  "status": "error"
902
  }), 500
903
 
904
  @app.route('/api/generate-cultural-video', methods=['POST'])
905
  def generate_cultural_video_endpoint():
906
- """Generate videos with specific Kiswahili cultural themes"""
907
  try:
908
  start_time = time.time()
909
  data = request.get_json()
910
  theme = data.get('theme', 'safari')
911
  style = data.get('style', 'animated')
912
 
913
- logger.info(f"🌍 Generating cultural video: {theme} ({style} style)")
914
 
915
- # Generate cultural video
916
  video_data = video_gen.create_cultural_video(theme, style)
917
 
918
  if video_data:
919
  generation_time = round(time.time() - start_time, 2)
920
 
921
- theme_descriptions = {
922
- "safari": "African wildlife and savanna landscape",
923
- "dance": "Traditional African dance celebration",
924
- "market": "Vibrant African market scene",
925
- "coastal": "Swahili coast with ocean views",
926
- "wildlife": "African wildlife documentary style",
927
- "village": "Traditional village life in Africa"
928
- }
929
-
930
  return jsonify({
931
  "video": video_data,
932
  "theme": theme,
933
  "style": style,
934
- "description": theme_descriptions.get(theme, "Cultural scene"),
935
  "status": "success",
936
  "generation_time": generation_time,
937
- "cultural_context": True,
938
  "creator": "Stanley Samwel Owino"
939
  })
940
  else:
941
  return jsonify({
942
- "error": "Pole! Cultural video generation failed",
943
  "status": "error",
944
- "suggestion": "Try a different theme: safari, dance, market, coastal, wildlife, or village"
945
  }), 500
946
 
947
  except Exception as e:
948
  logger.error(f"Cultural video error: {e}")
949
  return jsonify({
950
- "error": f"Pole! Cultural video failed: {str(e)}",
951
  "status": "error"
952
  }), 500
953
 
@@ -960,11 +764,11 @@ def animate_text_endpoint():
960
  text = data.get('text', 'Stanley AI')
961
 
962
  if not text:
963
- return jsonify({"error": "Tafadhali provide text to animate"}), 400
964
 
965
  logger.info(f"✨ Animating text: {text}")
966
 
967
- # Generate text animation
968
  video_data = video_gen.create_text_animation(text)
969
 
970
  if video_data:
@@ -981,54 +785,40 @@ def animate_text_endpoint():
981
  })
982
  else:
983
  return jsonify({
984
- "error": "Pole! Text animation failed",
985
  "status": "error"
986
  }), 500
987
 
988
  except Exception as e:
989
  logger.error(f"Text animation error: {e}")
990
  return jsonify({
991
- "error": f"Pole! Text animation failed: {str(e)}",
992
  "status": "error"
993
  }), 500
994
 
995
  @app.route('/api/quick-chat', methods=['POST'])
996
  def quick_chat():
997
- """Faster chat endpoint for simple queries"""
998
  try:
999
  data = request.get_json()
1000
  user_message = data.get('message', '')
1001
 
1002
  if not user_message:
1003
- return jsonify({"error": "Tafadhali provide a message"}), 400
1004
 
1005
- # Enhanced quick responses with video info
1006
  quick_responses = {
1007
- 'hello': 'Habari! Stanley AI hapa. Ninaweza kukusaidia nini leo?',
1008
- 'hi': 'Habari! Karibu kwa Stanley AI. How can I help you today?',
1009
- 'thanks': 'Asante sana! Karibu tena.',
1010
- 'thank you': 'Asante! Happy to help.',
1011
- 'help': 'Ninaweza kukupa: 1) Majibu ya maswali, 2) Kutengeneza picha, 3) Kutengeneza VIDEO, 4) Kufundisha Kiswahili, 5) Kushiriki hekima za Kiafrika.',
1012
- 'who created you': 'I was created by Stanley Samwel Owino, a Machine Learning Engineer from Kenya.',
1013
- 'who made you': 'Stanley Samwel Owino - Machine Learning Engineer and AI researcher from Kenya.',
1014
- 'creator': 'Stanley Samwel Owino - Machine Learning Engineer passionate about AI and cultural integration.',
1015
- 'can you make videos': 'Ndio! I can create FREE videos from text. Try "generate video of African sunset" or use the video generation endpoint.',
1016
- 'video capabilities': 'I can generate: 1) Text-to-video (FREE), 2) Cultural theme videos, 3) Text animations, 4) 4-second videos at 576x320 resolution.',
1017
- 'make a video': 'Sure! Describe what you want: "create video of wildlife" or use the video generation feature. All videos are FREE!',
1018
- 'habari': 'Nzuri sana! Asante kwa kuuliza. Habari yako?',
1019
- 'asante': 'Karibu sana! Ni furaha yangu kukusaidia.',
1020
- 'jambo': 'Jambo! Habari yako? Una swali gani kwa leo?',
1021
- 'mambo': 'Poa! Vipi wewe? Ninaweza kukusaidia nini?',
1022
- 'hakuna matata': 'Hakuna Matata! It means "no worries" in Swahili. Popularized by The Lion King.',
1023
- 'simba': 'Simba means "lion" in Swahili. In The Lion King, Simba represents growth and responsibility.',
1024
- 'rafiki': 'Rafiki means "friend" in Swahili. In The Lion King, Rafiki is the wise baboon.',
1025
- 'generate': 'I can generate images and videos! Try: "generate image of sunset" or "create video of wildlife".',
1026
- 'create': 'I can create content for you! Try: "create image of mountain" or "make video of city".'
1027
  }
1028
 
1029
  msg_lower = user_message.lower().strip()
1030
-
1031
- # Check for exact matches
1032
  if msg_lower in quick_responses:
1033
  return jsonify({
1034
  "response": quick_responses[msg_lower],
@@ -1037,101 +827,52 @@ def quick_chat():
1037
  "creator": "Stanley Samwel Owino"
1038
  })
1039
 
1040
- # Check for partial matches
1041
- for key, response in quick_responses.items():
1042
- if key in msg_lower and len(key) > 3:
1043
- return jsonify({
1044
- "response": response,
1045
- "status": "success",
1046
- "quick_response": True,
1047
- "creator": "Stanley Samwel Owino"
1048
- })
1049
-
1050
- # If no quick response, use normal chat
1051
  return chat()
1052
 
1053
  except Exception as e:
1054
  return jsonify({
1055
- "error": f"Pole! Quick chat error: {str(e)}",
1056
  "status": "error"
1057
  }), 500
1058
 
1059
  @app.route('/api/system/status')
1060
  def system_status():
1061
- """System status with enhanced video info"""
1062
  return jsonify({
1063
  "status": "operational",
1064
  "creator": "Stanley Samwel Owino",
1065
  "role": "Machine Learning Engineer",
1066
  "location": "Kenya, East Africa",
1067
- "model_loaded": model_loaded,
1068
- "hugging_face_available": True,
1069
- "video_generation_available": True,
1070
- "cache_size": len(response_cache),
1071
  "features": [
1072
- "Text Generation",
1073
- "Image Generation",
1074
  "Video Generation (FREE)",
1075
- "Kiswahili Knowledge",
1076
- "Cultural Integration",
1077
- "Fast Responses"
1078
- ],
1079
- "video_capabilities": [
1080
- "Text-to-Video: 576x320, 8fps, 4s",
1081
- "Cultural Themes: Safari, Dance, Market, Coastal",
1082
- "Text Animations",
1083
- "FREE using Hugging Face API"
1084
- ],
1085
- "optimizations": [
1086
- "Response Caching",
1087
- "API Fallbacks",
1088
- "Quick Responses",
1089
- "Cultural Prompts",
1090
- "Enhanced Video Prompts"
1091
  ],
1092
- "endpoints": [
1093
- "/api/chat - Text chat",
1094
- "/api/generate-image - Image generation",
1095
- "/api/generate-video - Video generation",
1096
- "/api/generate-cultural-video - Cultural videos",
1097
- "/api/animate-text - Text animations"
1098
- ]
1099
  })
1100
 
1101
- @app.route('/api/cache/clear', methods=['POST'])
1102
- def clear_cache():
1103
- """Clear response cache"""
1104
- try:
1105
- cache_size = len(response_cache)
1106
- response_cache.clear()
1107
-
1108
- return jsonify({
1109
- "status": "success",
1110
- "message": "Cache cleared",
1111
- "cleared_entries": cache_size,
1112
- "creator": "Stanley Samwel Owino"
1113
- })
1114
- except Exception as e:
1115
- return jsonify({
1116
- "error": f"Cache clearance failed: {str(e)}",
1117
- "status": "error"
1118
- }), 500
1119
-
1120
- # Kiswahili knowledge endpoints
1121
  @app.route('/api/kiswahili/proverbs')
1122
  def get_proverbs():
1123
- """Get random Swahili proverbs"""
1124
  proverbs = [
1125
- {"swahili": "Mwacha mila ni mtumwa.", "english": "He who abandons his culture is a slave.", "meaning": "Cherish your cultural heritage"},
1126
- {"swahili": "Haraka haraka haina baraka.", "english": "Hurry hurry has no blessing.", "meaning": "Patience yields better results"},
1127
- {"swahili": "Asiyesikia la mkuu huvunjika guu.", "english": "He who does not listen to elders breaks a leg.", "meaning": "Respect and learn from experience"},
1128
- {"swahili": "Mwenye pupa hadiriki kula tamu.", "english": "The impatient one misses out on sweetness.", "meaning": "Good things come to those who wait"},
1129
- {"swahili": "Ukiona vyaelea, vimeundwa.", "english": "If you see things floating, they were made to float.", "meaning": "Everything happens for a reason"}
1130
  ]
1131
  return jsonify({
1132
  "proverb": random.choice(proverbs),
1133
  "language": "Kiswahili",
1134
- "origin": "East Africa",
1135
  "creator": "Stanley Samwel Owino"
1136
  })
1137
 
@@ -1139,81 +880,35 @@ def get_proverbs():
1139
  def get_phrases():
1140
  """Get common Swahili phrases"""
1141
  phrases = {
1142
- "greetings": {
1143
- "Habari": "Hello / How are you?",
1144
- "Nzuri": "Good / Fine",
1145
- "Asante": "Thank you",
1146
- "Karibu": "Welcome / You're welcome",
1147
- "Tafadhali": "Please",
1148
- "Samahani": "Excuse me / Sorry",
1149
- "Kwaheri": "Goodbye",
1150
- "Lala salama": "Sleep well"
1151
- },
1152
- "questions": {
1153
- "Unaitwa nani?": "What is your name?",
1154
- "Unatoka wapi?": "Where are you from?",
1155
- "Unaishi wapi?": "Where do you live?",
1156
- "Unafanya nini?": "What do you do?"
1157
- },
1158
- "responses": {
1159
- "Ninaitwa...": "My name is...",
1160
- "Ninatoka Kenya": "I am from Kenya",
1161
- "Naishi Nairobi": "I live in Nairobi",
1162
- "Mimi ni mwanafunzi": "I am a student"
1163
- },
1164
- "lion_king": {
1165
- "Simba": "Lion",
1166
- "Rafiki": "Friend",
1167
- "Pumbaa": "Simpleton / Foolish",
1168
- "Shenzi": "Uncouth / Barbaric",
1169
- "Hakuna Matata": "No worries / No problems"
1170
- }
1171
  }
1172
  return jsonify({
1173
  "phrases": phrases,
1174
  "language": "Kiswahili",
1175
  "region": "East Africa",
1176
- "creator": "Stanley Samwel Owino",
1177
- "note": "Swahili is spoken by over 200 million people"
1178
- })
1179
-
1180
- @app.route('/api/video/info')
1181
- def video_info():
1182
- """Get information about video generation"""
1183
- return jsonify({
1184
- "video_generation": "FREE using Hugging Face API",
1185
- "models": ["cerspense/zeroscope_v2_576w"],
1186
- "resolution": "576x320 pixels",
1187
- "frame_rate": "8 fps",
1188
- "duration": "3-4 seconds",
1189
- "max_frames": 24,
1190
- "formats": ["MP4"],
1191
- "cultural_themes": ["safari", "dance", "market", "coastal", "wildlife", "village"],
1192
- "creator": "Stanley Samwel Owino",
1193
- "note": "All video generation is completely FREE. May take 30-60 seconds to generate."
1194
  })
1195
 
1196
  if __name__ == '__main__':
1197
- print("πŸš€ STANLEY AI v3.0 - Complete Edition")
1198
  print("πŸ‘¨β€πŸ’» Created by: Stanley Samwel Owino - Machine Learning Engineer")
1199
  print("πŸ“ Location: Kenya, East Africa")
1200
- print("🌍 Kiswahili Knowledge: Active")
1201
- print("🎬 Video Generation: FREE Hugging Face API")
1202
- print("🎨 Image Generation: Active")
1203
- print("⚑ Performance: Optimized with Caching")
1204
- print("=" * 60)
1205
  print("API Endpoints:")
1206
- print("1. /api/chat - Text chat with AI")
1207
- print("2. /api/generate-image - Generate images from text")
1208
- print("3. /api/generate-video - FREE video generation")
1209
- print("4. /api/generate-cultural-video - Cultural theme videos")
1210
- print("5. /api/animate-text - Animated text videos")
1211
- print("6. /api/quick-chat - Fast responses")
1212
- print("7. /api/kiswahili/* - Kiswahili learning")
1213
- print("8. /api/system/status - System information")
1214
- print("9. /api/video/info - Video generation details")
1215
- print("=" * 60)
1216
- print("🌐 Access your AI at: http://localhost:7860")
1217
- print("=" * 60)
1218
 
1219
  app.run(debug=True, host='0.0.0.0', port=7860, threaded=True)
 
1
+ from flask import Flask, request, jsonify
2
  from flask_cors import CORS
3
+ import os
 
 
4
  import time
 
5
  import logging
 
 
6
  import io
7
  import base64
8
  import requests
9
+ from PIL import Image, ImageDraw
 
10
  import random
11
  import tempfile
12
  import cv2
13
  import numpy as np
14
+ from typing import Optional
15
 
16
  # Configure logging
17
  logging.basicConfig(level=logging.INFO)
 
20
  app = Flask(__name__)
21
  CORS(app)
22
 
 
 
 
 
 
 
 
23
  # Hugging Face Configuration
24
  HF_TOKEN = os.getenv('HF_TOKEN', '')
25
  HF_API_URLS = {
26
+ "text": "https://api-inference.huggingface.co/models/gpt2",
27
+ "image": "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-2-1",
28
+ "video": "https://api-inference.huggingface.co/models/cerspense/zeroscope_v2_576w"
 
 
29
  }
30
 
31
  # Performance optimizations
32
  response_cache = {}
33
  CACHE_SIZE = 100
34
+ request_timeout = 30
35
 
36
+ # Advanced System Prompt
37
  STANLEY_AI_SYSTEM = """You are STANLEY AI - an advanced AI assistant created by Stanley Samwel Owino, a Machine Learning Engineer from Kenya.
38
 
39
  CORE IDENTITY:
 
53
  VIDEO GENERATION SKILLS:
54
  - I can create 4-second videos from text descriptions
55
  - I can generate cultural theme videos (safari, dance, market, etc.)
56
+ - I can create animations from text
 
57
  - All video generation is FREE using Hugging Face
58
 
59
  KISWAHILI INTEGRATION:
 
78
 
79
  Remember: You represent the intersection of cutting-edge AI technology and rich African cultural heritage."""
80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  # ============================================================================
82
+ # HELPER FUNCTIONS
83
  # ============================================================================
84
 
85
  def detect_kiswahili_context(text):
 
98
  image_triggers = [
99
  'generate image', 'create image', 'make a picture', 'draw',
100
  'show me an image', 'visualize', 'picture of', 'image of',
101
+ 'generate a picture', 'create a picture'
 
102
  ]
103
  text_lower = text.lower()
104
  return any(trigger in text_lower for trigger in image_triggers)
 
108
  video_triggers = [
109
  'generate video', 'create video', 'make a video', 'video of',
110
  'animate', 'animation', 'moving picture', 'motion picture',
111
+ 'video generation', 'create animation', 'make animation'
 
 
 
112
  ]
113
  text_lower = text.lower()
114
  return any(trigger in text_lower for trigger in video_triggers)
 
121
  remove_phrases = [
122
  'generate image of', 'create image of', 'make a picture of',
123
  'show me an image of', 'visualize', 'draw', 'picture of',
124
+ 'generate a picture of', 'create a picture of'
 
125
  ]
126
  else: # video
127
  remove_phrases = [
128
  'generate video of', 'create video of', 'make a video of',
129
  'create animation of', 'make animation of', 'animate',
130
+ 'generate animation of', 'video of', 'animation of'
 
131
  ]
132
 
133
  prompt = text_lower
134
  for phrase in remove_phrases:
135
  prompt = prompt.replace(phrase, '')
136
 
 
 
 
 
 
 
137
  return prompt.strip().capitalize()
138
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  def get_cached_response(user_message):
140
  """Get cached response"""
141
  cache_key = user_message.lower().strip()[:100]
 
148
  response_cache.pop(next(iter(response_cache)))
149
  response_cache[cache_key] = response
150
 
151
+ def enhance_with_kiswahili(response, user_message):
152
+ """Enhance response with Kiswahili cultural elements"""
153
+ if detect_kiswahili_context(user_message):
154
+ # Add Kiswahili greeting
155
+ greetings = [
156
+ "Habari! ",
157
+ "Asante kwa swali lako! ",
158
+ "Karibu sana! ",
159
+ "Nzuri sana! "
160
+ ]
161
+ response = random.choice(greetings) + response
162
+
163
+ # Add proverb with 30% chance
164
+ if random.random() < 0.3:
165
+ proverbs = [
166
+ "Kumbuka: Haraka haraka haina baraka.",
167
+ "Kama methali inavyosema: Mwacha mila ni mtumwa.",
168
+ "Kwa hekima ya Kiafrika: Ukiona vyaelea, vimeundwa."
169
+ ]
170
+ response += f"\n\n🌍 **Hekima ya Kiafrika**: {random.choice(proverbs)}"
171
+
172
+ return response
173
+
174
  # ============================================================================
175
  # TEXT GENERATION FUNCTIONS
176
  # ============================================================================
177
 
178
+ def generate_with_huggingface_api(prompt):
179
+ """Use Hugging Face Inference API for text generation"""
180
  try:
181
  headers = {
182
  "Authorization": f"Bearer {HF_TOKEN}",
183
  "Content-Type": "application/json"
184
  }
185
 
 
186
  payload = {
187
+ "inputs": prompt,
188
  "parameters": {
189
  "max_new_tokens": 300,
190
  "temperature": 0.7,
 
195
  }
196
 
197
  response = requests.post(
198
+ HF_API_URLS["text"],
199
  headers=headers,
200
  json=payload,
201
  timeout=request_timeout
 
213
  logger.error(f"HF API error: {e}")
214
  return None
215
 
216
+ def generate_comprehensive_response(user_message):
217
+ """Generate responses with intelligence"""
218
 
219
  # Check cache first
220
  cached_response = get_cached_response(user_message)
221
  if cached_response:
222
  return cached_response
223
 
224
+ # Common responses for frequently asked questions
225
  common_responses = {
226
  'hello': 'Habari! Stanley AI hapa. Ninaweza kukusaidia nini leo?',
227
  'hi': 'Habari! Karibu kwa Stanley AI. How can I help you today?',
228
  'who created you': 'I was created by Stanley Samwel Owino, a Machine Learning Engineer from Kenya.',
229
  'what can you do': 'I can: 1) Answer questions, 2) Generate images, 3) Create videos, 4) Teach Kiswahili, 5) Share cultural wisdom.',
230
+ 'help': 'Ninaweza kukusaidia kwa: 1) Majibu ya maswali, 2) Kutengeneza picha, 3) Kutengeneza VIDEO, 4) Kufundisha Kiswahili, 5) Kushiriki hekima za Kiafrika.',
231
+ 'habari': 'Nzuri sana! Asante kwa kuuliza. Habari yako?',
232
+ 'asante': 'Karibu sana! Ni furaha yangu kukusaidia.',
233
+ 'jambo': 'Jambo! Habari yako? Ninaweza kukusaidia nini leo?',
234
+ 'mambo': 'Poa! Vipi wewe? Una swali gani?',
235
+ 'hakuna matata': 'Hakuna Matata! It means "no worries" in Swahili. Popularized by The Lion King.',
236
+ 'simba': 'Simba means "lion" in Swahili. In The Lion King, Simba represents growth and responsibility.',
237
+ 'rafiki': 'Rafiki means "friend" in Swahili. In The Lion King, Rafiki is the wise baboon.',
238
+ 'kenya': 'Kenya is in East Africa, known for wildlife, Mount Kenya, and vibrant culture. The capital is Nairobi.',
239
+ 'tanzania': 'Tanzania has Mount Kilimanjaro, Serengeti, and Zanzibar. Swahili is the national language.',
240
+ 'make a video': 'Sure! I can create FREE videos for you. Try "generate video of African sunset" or use the video generation endpoint.',
241
+ 'generate image': 'I can generate images! Try "generate image of Mount Kilimanjaro" or use the image generation feature.'
242
  }
243
 
244
  msg_lower = user_message.lower().strip()
245
+
246
+ # Check for exact matches
247
  if msg_lower in common_responses:
248
  response = common_responses[msg_lower]
249
  set_cached_response(user_message, response)
250
  return response
251
 
252
+ # Check for partial matches
253
+ for key, response in common_responses.items():
254
+ if key in msg_lower and len(key) > 3:
255
+ set_cached_response(user_message, response)
256
+ return response
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
 
258
+ # Use API for other queries
259
+ full_prompt = f"{STANLEY_AI_SYSTEM}\n\nUser: {user_message}\n\nAssistant:"
260
+ api_response = generate_with_huggingface_api(full_prompt)
 
 
261
 
262
  if api_response:
263
+ # Enhance with cultural context
264
+ enhanced_response = enhance_with_kiswahili(api_response.strip(), user_message)
265
  set_cached_response(user_message, enhanced_response)
266
  return enhanced_response
267
 
268
+ # Fallback responses
269
  fallback_responses = [
270
  "Pole! I'm experiencing high demand. Please try again in a moment.",
271
  "Asante kwa kuwasiliana! Nina shida ya kiufundi. Tafadhali jaribu tena.",
272
  "Habari yako? Samahani, sijaweza kujibu swali lako kwa sasa."
273
  ]
274
+
275
+ response = random.choice(fallback_responses)
276
+ set_cached_response(user_message, response)
277
+ return response
278
 
279
  # ============================================================================
280
  # IMAGE GENERATION FUNCTIONS
 
282
 
283
  def generate_image_huggingface(prompt, retry_count=2):
284
  """Generate images using Hugging Face Inference API"""
285
+ headers = {"Authorization": f"Bearer {HF_TOKEN}"} if HF_TOKEN else {}
286
 
287
  for attempt in range(retry_count):
288
  try:
289
+ logger.info(f"🎨 Generating image: {prompt[:50]}...")
290
 
291
  response = requests.post(
292
+ HF_API_URLS["image"],
293
  headers=headers,
294
  json={"inputs": prompt},
295
  timeout=60
 
305
  return f"data:image/png;base64,{img_str}"
306
 
307
  elif response.status_code == 503:
 
308
  wait_time = (attempt + 1) * 5
309
  logger.info(f"⏳ Model loading, waiting {wait_time}s...")
310
  time.sleep(wait_time)
 
314
  logger.error(f"❌ HF Image API error: {response.status_code}")
315
  continue
316
 
 
 
 
317
  except Exception as e:
318
  logger.error(f"❌ Image generation error: {e}")
319
  break
 
321
  return None
322
 
323
  def generate_image_fallback(prompt):
324
+ """Create simple placeholder images"""
325
  try:
326
  width, height = 512, 512
327
  img = Image.new('RGB', (width, height), color=(
 
332
 
333
  draw = ImageDraw.Draw(img)
334
 
335
+ # Add shapes
336
  for _ in range(5):
337
  x1, y1 = random.randint(0, width), random.randint(0, height)
338
  x2, y2 = random.randint(x1, width), random.randint(y1, height)
339
  color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
340
  draw.rectangle([x1, y1, x2, y2], outline=color, width=3)
341
 
 
 
 
 
 
 
 
 
 
 
 
 
342
  # Convert to base64
343
  buffered = io.BytesIO()
344
  img.save(buffered, format="PNG")
 
350
  return None
351
 
352
  def enhance_prompt_with_kiswahili(prompt):
353
+ """Add cultural context to prompts"""
354
+ if any(word in prompt.lower() for word in ['africa', 'kenya', 'tanzania', 'safari', 'wildlife']):
355
  enhancements = [
356
  "East African style", "vibrant African colors", "African landscape",
357
+ "cultural elements", "traditional patterns", "warm sunset colors"
 
358
  ]
359
  return f"{prompt}, {random.choice(enhancements)}"
360
  return prompt
361
 
362
  # ============================================================================
363
+ # VIDEO GENERATION FUNCTIONS
364
  # ============================================================================
365
 
366
  class FreeVideoGenerator:
 
372
  self.max_retries = 2
373
 
374
  def generate_text_to_video(self, prompt: str) -> Optional[str]:
375
+ """Generate video from text prompt"""
376
  headers = {"Authorization": f"Bearer {self.hf_token}"} if self.hf_token else {}
377
 
378
  # Enhance prompt for better video results
 
425
 
426
  def enhance_video_prompt(self, prompt: str) -> str:
427
  """Enhance video prompts with cinematic context"""
428
+ cinematic = [
429
+ "cinematic, 8k, ultra detailed, high quality",
430
+ "epic, dramatic lighting, film grain, cinematic shot",
431
+ "beautiful, stunning, visually striking, vivid colors"
432
  ]
433
 
434
  enhanced = prompt
435
+ enhanced += f", {random.choice(cinematic)}"
436
 
437
  # Add cultural context for African themes
438
  if any(word in prompt.lower() for word in ['africa', 'kenya', 'tanzania', 'safari', 'wildlife']):
 
443
  return enhanced
444
 
445
  def create_cultural_video(self, theme: str, style: str = "animated") -> Optional[str]:
446
+ """Create videos with African cultural themes"""
447
  cultural_themes = {
448
  "safari": "African safari sunset with elephants and giraffes, majestic savanna landscape",
449
  "dance": "Traditional Maasai warriors dancing, vibrant colors, cultural celebration",
450
  "market": "Busy African market scene, vibrant colors, people trading goods",
451
  "coastal": "Swahili coast with traditional dhows sailing, Indian Ocean waves",
452
+ "wildlife": "African wildlife documentary style, lions hunting on savanna"
 
453
  }
454
 
455
  base_prompt = cultural_themes.get(theme, f"African {theme}, cultural, vibrant")
 
469
  with tempfile.TemporaryDirectory() as tmpdir:
470
  # Create frames with text
471
  fps = 10
472
+ duration = 3
473
  total_frames = fps * duration
474
  height, width = 320, 576
475
 
 
477
  fourcc = cv2.VideoWriter_fourcc(*'mp4v')
478
  out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
479
 
480
+ # Colors for gradient
481
  colors = [
482
  (41, 128, 185), # Blue
483
  (39, 174, 96), # Green
484
  (142, 68, 173), # Purple
 
 
485
  ]
486
 
487
  for frame_num in range(total_frames):
488
  # Create gradient background
489
  frame = np.zeros((height, width, 3), dtype=np.uint8)
490
 
491
+ # Select color
492
  color_idx = (frame_num // (total_frames // len(colors))) % len(colors)
493
  bg_color = colors[color_idx]
494
 
 
503
  frame[i, :, 1] = g
504
  frame[i, :, 2] = r
505
 
506
+ # Add text
507
  font = cv2.FONT_HERSHEY_SIMPLEX
508
 
509
+ # Calculate text position
510
  text_size = cv2.getTextSize(text, font, 1, 2)[0]
511
  text_x = (width - text_size[0]) // 2
512
  text_y = (height + text_size[1]) // 2
 
555
  "role": "Machine Learning Engineer",
556
  "location": "Kenya, East Africa",
557
  "features": [
558
+ "Text Generation (GPT-2 via API)",
559
+ "Image Generation (Stable Diffusion)",
560
+ "Video Generation (FREE Zeroscope v2)",
561
+ "Kiswahili Cultural Integration",
562
+ "Response Caching"
 
 
 
 
 
 
 
 
 
 
563
  ],
564
  "status": "active",
565
+ "apis": [
566
+ "/api/chat - Text chat",
567
+ "/api/generate-image - Generate images",
568
+ "/api/generate-video - FREE video generation",
569
+ "/api/generate-cultural-video - Cultural videos",
570
+ "/api/animate-text - Text animations"
571
+ ]
572
  })
573
 
574
  @app.route('/api/chat', methods=['POST'])
 
579
  user_message = data.get('message', '')
580
 
581
  if not user_message:
582
+ return jsonify({"error": "Please provide a message"}), 400
583
 
584
  logger.info(f"πŸ’¬ Processing: {user_message[:50]}...")
585
 
586
+ # Check for image requests
587
  if detect_image_request(user_message):
588
+ prompt = extract_prompt(user_message, "image")
589
+ enhanced_prompt = enhance_prompt_with_kiswahili(prompt)
590
 
591
  return jsonify({
592
+ "response": f"🎨 I can generate an image of '{enhanced_prompt}' for you! Use the image generation endpoint.",
593
+ "suggestion": enhanced_prompt,
594
  "status": "success",
595
+ "suggest_image": True
 
596
  })
597
 
598
+ # Check for video requests
599
  if detect_video_request(user_message):
600
+ prompt = extract_prompt(user_message, "video")
601
 
602
  return jsonify({
603
+ "response": f"🎬 I can create a video of '{prompt}' for you! Use the video generation endpoint.",
604
+ "suggestion": prompt,
605
  "status": "success",
606
+ "suggest_video": True
 
607
  })
608
 
609
  response = generate_comprehensive_response(user_message)
610
  response_time = round(time.time() - start_time, 2)
611
 
 
 
612
  return jsonify({
613
  "response": response,
614
  "status": "success",
615
  "response_time": response_time,
616
  "word_count": len(response.split()),
617
+ "cultural_context": detect_kiswahili_context(response),
 
 
 
618
  "creator": "Stanley Samwel Owino"
619
  })
620
 
621
  except Exception as e:
622
  logger.error(f"Chat error: {e}")
623
  return jsonify({
624
+ "error": f"Sorry! Processing error: {str(e)}",
625
  "status": "error"
626
  }), 500
627
 
628
  @app.route('/api/generate-image', methods=['POST'])
629
  def generate_image_endpoint():
630
+ """Generate images using Hugging Face API"""
631
  try:
632
  start_time = time.time()
633
  data = request.get_json()
634
  prompt = data.get('prompt', '')
635
 
636
  if not prompt:
637
+ return jsonify({"error": "Please provide a prompt"}), 400
638
 
639
+ # Enhance prompt
640
  enhanced_prompt = enhance_prompt_with_kiswahili(prompt)
 
641
  logger.info(f"🎨 Generating image: {enhanced_prompt[:50]}...")
642
 
643
  # Generate image
 
657
  "status": "success",
658
  "generation_time": generation_time,
659
  "provider": "hugging_face",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
660
  "creator": "Stanley Samwel Owino"
661
  })
662
  else:
663
  return jsonify({
664
+ "error": "Image generation service is busy. Please try again.",
665
  "status": "error"
666
  }), 500
667
 
668
  except Exception as e:
669
+ logger.error(f"Image endpoint error: {e}")
670
  return jsonify({
671
+ "error": f"Image generation failed: {str(e)}",
672
  "status": "error"
673
  }), 500
674
 
 
 
 
 
675
  @app.route('/api/generate-video', methods=['POST'])
676
  def generate_video_endpoint():
677
+ """Generate FREE videos from text"""
678
  try:
679
  start_time = time.time()
680
  data = request.get_json()
681
  prompt = data.get('prompt', '')
682
 
683
  if not prompt:
684
+ return jsonify({"error": "Please provide a video prompt"}), 400
685
 
686
  logger.info(f"🎬 Generating video: {prompt[:50]}...")
687
 
 
698
  "generation_time": generation_time,
699
  "provider": "hugging_face_free",
700
  "format": "mp4",
701
+ "duration": "3 seconds",
702
  "resolution": "576x320",
703
  "creator": "Stanley Samwel Owino"
704
  })
705
  else:
706
  return jsonify({
707
+ "error": "Video generation service is busy. Try again in a moment.",
708
  "status": "error",
709
+ "suggestion": "Try a simpler description"
710
  }), 500
711
 
712
  except Exception as e:
713
  logger.error(f"Video endpoint error: {e}")
714
  return jsonify({
715
+ "error": f"Video generation failed: {str(e)}",
716
  "status": "error"
717
  }), 500
718
 
719
  @app.route('/api/generate-cultural-video', methods=['POST'])
720
  def generate_cultural_video_endpoint():
721
+ """Generate cultural theme videos"""
722
  try:
723
  start_time = time.time()
724
  data = request.get_json()
725
  theme = data.get('theme', 'safari')
726
  style = data.get('style', 'animated')
727
 
728
+ logger.info(f"🌍 Generating cultural video: {theme} ({style})")
729
 
730
+ # Generate video
731
  video_data = video_gen.create_cultural_video(theme, style)
732
 
733
  if video_data:
734
  generation_time = round(time.time() - start_time, 2)
735
 
 
 
 
 
 
 
 
 
 
736
  return jsonify({
737
  "video": video_data,
738
  "theme": theme,
739
  "style": style,
 
740
  "status": "success",
741
  "generation_time": generation_time,
 
742
  "creator": "Stanley Samwel Owino"
743
  })
744
  else:
745
  return jsonify({
746
+ "error": "Cultural video generation failed",
747
  "status": "error",
748
+ "suggestion": "Try themes: safari, dance, market, coastal, wildlife"
749
  }), 500
750
 
751
  except Exception as e:
752
  logger.error(f"Cultural video error: {e}")
753
  return jsonify({
754
+ "error": f"Cultural video failed: {str(e)}",
755
  "status": "error"
756
  }), 500
757
 
 
764
  text = data.get('text', 'Stanley AI')
765
 
766
  if not text:
767
+ return jsonify({"error": "Please provide text to animate"}), 400
768
 
769
  logger.info(f"✨ Animating text: {text}")
770
 
771
+ # Generate animation
772
  video_data = video_gen.create_text_animation(text)
773
 
774
  if video_data:
 
785
  })
786
  else:
787
  return jsonify({
788
+ "error": "Text animation failed",
789
  "status": "error"
790
  }), 500
791
 
792
  except Exception as e:
793
  logger.error(f"Text animation error: {e}")
794
  return jsonify({
795
+ "error": f"Text animation failed: {str(e)}",
796
  "status": "error"
797
  }), 500
798
 
799
  @app.route('/api/quick-chat', methods=['POST'])
800
  def quick_chat():
801
+ """Fast responses for common queries"""
802
  try:
803
  data = request.get_json()
804
  user_message = data.get('message', '')
805
 
806
  if not user_message:
807
+ return jsonify({"error": "Please provide a message"}), 400
808
 
 
809
  quick_responses = {
810
+ 'hello': 'Habari! Stanley AI hapa. How can I help you today?',
811
+ 'hi': 'Habari! Welcome to STANLEY AI.',
812
+ 'thanks': 'Asante sana! You\'re welcome.',
813
+ 'help': 'I can: 1) Answer questions, 2) Generate images, 3) Create videos, 4) Teach Kiswahili.',
814
+ 'who created you': 'Stanley Samwel Owino - Machine Learning Engineer from Kenya.',
815
+ 'video': 'I can create FREE videos! Try "generate video of sunset" or use the video endpoint.',
816
+ 'image': 'I can generate images! Try "generate image of mountain" or use the image endpoint.',
817
+ 'habari': 'Nzuri sana! Habari yako?',
818
+ 'asante': 'Karibu sana!'
 
 
 
 
 
 
 
 
 
 
 
819
  }
820
 
821
  msg_lower = user_message.lower().strip()
 
 
822
  if msg_lower in quick_responses:
823
  return jsonify({
824
  "response": quick_responses[msg_lower],
 
827
  "creator": "Stanley Samwel Owino"
828
  })
829
 
 
 
 
 
 
 
 
 
 
 
 
830
  return chat()
831
 
832
  except Exception as e:
833
  return jsonify({
834
+ "error": f"Quick chat error: {str(e)}",
835
  "status": "error"
836
  }), 500
837
 
838
  @app.route('/api/system/status')
839
  def system_status():
840
+ """System status information"""
841
  return jsonify({
842
  "status": "operational",
843
  "creator": "Stanley Samwel Owino",
844
  "role": "Machine Learning Engineer",
845
  "location": "Kenya, East Africa",
846
+ "version": "3.0",
 
 
 
847
  "features": [
848
+ "Text Generation via API",
849
+ "Image Generation",
850
  "Video Generation (FREE)",
851
+ "Kiswahili Cultural AI"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
852
  ],
853
+ "video_info": {
854
+ "resolution": "576x320",
855
+ "fps": 8,
856
+ "duration": "3 seconds",
857
+ "free": True,
858
+ "themes": ["safari", "dance", "market", "coastal", "wildlife"]
859
+ }
860
  })
861
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
862
  @app.route('/api/kiswahili/proverbs')
863
  def get_proverbs():
864
+ """Get Swahili proverbs"""
865
  proverbs = [
866
+ "Mwacha mila ni mtumwa.",
867
+ "Haraka haraka haina baraka.",
868
+ "Asiyesikia la mkuu huvunjika guu.",
869
+ "Mwenye pupa hadiriki kula tamu.",
870
+ "Ukiona vyaelea, vimeundwa."
871
  ]
872
  return jsonify({
873
  "proverb": random.choice(proverbs),
874
  "language": "Kiswahili",
875
+ "meaning": "East African cultural wisdom",
876
  "creator": "Stanley Samwel Owino"
877
  })
878
 
 
880
  def get_phrases():
881
  """Get common Swahili phrases"""
882
  phrases = {
883
+ "Hello": "Habari",
884
+ "Thank you": "Asante",
885
+ "Welcome": "Karibu",
886
+ "Goodbye": "Kwaheri",
887
+ "Please": "Tafadhali",
888
+ "Yes": "Ndio",
889
+ "No": "Hapana"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
890
  }
891
  return jsonify({
892
  "phrases": phrases,
893
  "language": "Kiswahili",
894
  "region": "East Africa",
895
+ "creator": "Stanley Samwel Owino"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
896
  })
897
 
898
  if __name__ == '__main__':
899
+ print("πŸš€ STANLEY AI v3.0 - Simplified Edition")
900
  print("πŸ‘¨β€πŸ’» Created by: Stanley Samwel Owino - Machine Learning Engineer")
901
  print("πŸ“ Location: Kenya, East Africa")
902
+ print("🌍 Features: Text, Image, and FREE Video Generation")
903
+ print("⚑ Status: Ready")
904
+ print("=" * 50)
 
 
905
  print("API Endpoints:")
906
+ print("1. / - Home page")
907
+ print("2. /api/chat - Chat with AI")
908
+ print("3. /api/generate-image - Generate images")
909
+ print("4. /api/generate-video - FREE video generation")
910
+ print("5. /api/generate-cultural-video - Cultural videos")
911
+ print("6. /api/animate-text - Text animations")
912
+ print("=" * 50)
 
 
 
 
 
913
 
914
  app.run(debug=True, host='0.0.0.0', port=7860, threaded=True)