| from flask import Flask, request, jsonify, send_file |
| from flask_cors import CORS |
| from transformers import AutoModelForCausalLM, AutoTokenizer |
| from knowledgebase import KiswahiliKnowledgeBase, enhance_with_kiswahili |
| from video_generation import FreeVideoGenerator |
| import torch |
| import time |
| import re |
| import logging |
| from threading import Thread |
| import queue |
| import io |
| import base64 |
| import requests |
| from PIL import Image |
| import os |
| import random |
| import tempfile |
|
|
| |
| logging.basicConfig(level=logging.INFO) |
| logger = logging.getLogger(__name__) |
|
|
| app = Flask(__name__) |
| CORS(app) |
|
|
| |
| kb = KiswahiliKnowledgeBase() |
|
|
| |
| HF_TOKEN = os.getenv('HF_TOKEN', 'your_hugging_face_token_here') |
| video_gen = FreeVideoGenerator(HF_TOKEN) |
|
|
| model = None |
| tokenizer = None |
| model_loaded = False |
|
|
| |
| HF_API_URLS = { |
| "text": "https://api-inference.huggingface.co/models/Qwen/Qwen2.5-7B-Instruct", |
| "image": "https://api-inference.huggingface.co/models/runwayml/stable-diffusion-v1-5", |
| "fast_image": "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-2-1", |
| "video": "https://api-inference.huggingface.co/models/cerspense/zeroscope_v2_576w" |
| } |
|
|
| |
| response_cache = {} |
| CACHE_SIZE = 100 |
| request_timeout = 30 |
|
|
| |
| STANLEY_AI_SYSTEM = """You are STANLEY AI - an advanced AI assistant created by Stanley Samwel Owino, a Machine Learning Engineer from Kenya. |
| CORE CAPABILITIES: |
| - Provide detailed, comprehensive responses |
| - Integrate Kiswahili phrases naturally when relevant |
| - Share cultural insights and proverbs |
| - Reference Lion King lore accurately |
| - Generate and describe images and videos |
| - Be helpful, knowledgeable, and engaging |
| KISWAHILI INTEGRATION: |
| Use phrases like "Habari", "Asante", "Karibu", "Pole sana" appropriately |
| Explain cultural concepts with authenticity |
| Share Swahili proverbs when relevant |
| IMAGE & VIDEO GENERATION: |
| You can generate images and videos based on user descriptions |
| Enhance prompts with cultural context when relevant |
| Describe generated content in detail |
| VIDEO CAPABILITIES: |
| - Create 4-second videos from text |
| - Generate cultural theme videos |
| - Create animations from text |
| - Make slideshows from images |
| RESPONSE STYLE: Be concise yet comprehensive, culturally aware, and genuinely helpful.""" |
|
|
| def load_model(): |
| """Load model with Hugging Face optimizations""" |
| global model, tokenizer, model_loaded |
| |
| if model_loaded: |
| return |
| |
| logger.info("π Loading STANLEY AI Model from Hugging Face...") |
| |
| try: |
| |
| model_name = "Qwen/Qwen2.5-0.5B-Instruct" |
| |
| tokenizer = AutoTokenizer.from_pretrained( |
| model_name, |
| trust_remote_code=True, |
| cache_dir="./model_cache" |
| ) |
| |
| if tokenizer.pad_token is None: |
| tokenizer.pad_token = tokenizer.eos_token |
| |
| model = AutoModelForCausalLM.from_pretrained( |
| model_name, |
| torch_dtype=torch.float16, |
| device_map="auto", |
| trust_remote_code=True, |
| cache_dir="./model_cache", |
| low_cpu_mem_usage=True |
| ) |
| |
| |
| model.eval() |
| if torch.cuda.is_available(): |
| model = torch.compile(model) |
| |
| model_loaded = True |
| logger.info("β
STANLEY AI Model loaded successfully!") |
| |
| except Exception as e: |
| logger.error(f"β Error loading model: {e}") |
| model_loaded = False |
| logger.info("π Using Hugging Face API fallback for text generation") |
|
|
| load_model() |
|
|
| class TextGenerationStream: |
| def __init__(self): |
| self.text_queue = queue.Queue() |
| |
| def put(self, text): |
| self.text_queue.put(text) |
| |
| def end(self): |
| self.text_queue.put(None) |
| |
| def generate(self): |
| while True: |
| text = self.text_queue.get() |
| if text is None: |
| break |
| yield text |
|
|
| def detect_kiswahili_context(text): |
| """Detect Kiswahili or cultural context""" |
| kiswahili_triggers = [ |
| 'swahili', 'kiswahili', 'hakuna', 'matata', 'asante', 'rafiki', |
| 'jambo', 'mambo', 'pole', 'sawa', 'karibu', 'kwaheri', 'simba', |
| 'lion king', 'mufasa', 'nala', 'africa', 'kenya', 'tanzania', |
| 'east africa', 'culture', 'cultural', 'language' |
| ] |
| text_lower = text.lower() |
| return any(trigger in text_lower for trigger in kiswahili_triggers) |
|
|
| def detect_image_request(text): |
| """Detect if user wants to generate an image""" |
| image_triggers = [ |
| 'generate image', 'create image', 'make a picture', 'draw', |
| 'show me an image', 'visualize', 'picture of', 'image of', |
| 'generate a picture', 'create a picture' |
| ] |
| text_lower = text.lower() |
| return any(trigger in text_lower for trigger in image_triggers) |
|
|
| def extract_image_prompt(text): |
| """Extract image description from user message""" |
| |
| prompt = text.lower() |
| remove_phrases = [ |
| 'generate image of', 'create image of', 'make a picture of', |
| 'show me an image of', 'visualize', 'draw', 'picture of', |
| 'generate a picture of', 'create a picture of' |
| ] |
| |
| for phrase in remove_phrases: |
| prompt = prompt.replace(phrase, '') |
| |
| return prompt.strip() |
|
|
| def enhance_with_cultural_context(response, user_message): |
| """Enhance response with Kiswahili cultural elements""" |
| if detect_kiswahili_context(user_message): |
| enhanced_response = kb.generate_kiswahili_response(response) |
| |
| |
| if any(word in user_message.lower() for word in ['wisdom', 'advice', 'life lesson', 'philosophy']): |
| proverb = kb.get_random_proverb() |
| enhanced_response += f"\n\nπ **Cultural Wisdom**: {proverb}" |
| |
| return enhanced_response |
| return response |
|
|
| def get_cached_response(user_message): |
| """Get cached response""" |
| cache_key = user_message.lower().strip()[:100] |
| return response_cache.get(cache_key) |
|
|
| def set_cached_response(user_message, response): |
| """Cache response""" |
| cache_key = user_message.lower().strip()[:100] |
| if len(response_cache) >= CACHE_SIZE: |
| response_cache.pop(next(iter(response_cache))) |
| response_cache[cache_key] = response |
|
|
| def generate_with_huggingface_api(messages): |
| """Use Hugging Face Inference API for faster responses""" |
| try: |
| headers = { |
| "Authorization": f"Bearer {HF_TOKEN}", |
| "Content-Type": "application/json" |
| } |
| |
| payload = { |
| "inputs": messages[-1]["content"], |
| "parameters": { |
| "max_new_tokens": 512, |
| "temperature": 0.7, |
| "top_p": 0.9, |
| "return_full_text": False |
| } |
| } |
| |
| response = requests.post( |
| HF_API_URLS["text"], |
| headers=headers, |
| json=payload, |
| timeout=request_timeout |
| ) |
| |
| if response.status_code == 200: |
| result = response.json() |
| return result[0]['generated_text'] |
| else: |
| logger.warning(f"HF API failed: {response.status_code}") |
| return None |
| |
| except Exception as e: |
| logger.error(f"HF API error: {e}") |
| return None |
|
|
| def generate_comprehensive_response(user_message, stream=False): |
| """Generate responses with fallback to Hugging Face API""" |
| |
| |
| cached_response = get_cached_response(user_message) |
| if cached_response: |
| return cached_response |
| |
| |
| if model_loaded and model is not None: |
| try: |
| system_prompt = STANLEY_AI_SYSTEM |
| if detect_kiswahili_context(user_message): |
| system_prompt += "\n\nSPECIAL NOTE: Integrate Kiswahili phrases naturally." |
| |
| messages = [ |
| {"role": "system", "content": system_prompt}, |
| {"role": "user", "content": user_message} |
| ] |
| |
| text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) |
| inputs = tokenizer(text, return_tensors="pt").to(model.device) |
| |
| with torch.no_grad(): |
| outputs = model.generate( |
| **inputs, |
| max_new_tokens=512, |
| temperature=0.7, |
| do_sample=True, |
| top_p=0.9, |
| pad_token_id=tokenizer.eos_token_id, |
| eos_token_id=tokenizer.eos_token_id, |
| ) |
| |
| response = tokenizer.decode(outputs[0][inputs['input_ids'].shape[1]:], skip_special_tokens=True) |
| enhanced_response = enhance_with_cultural_context(response.strip(), user_message) |
| |
| |
| set_cached_response(user_message, enhanced_response) |
| return enhanced_response |
| |
| except Exception as e: |
| logger.error(f"Local model error: {e}") |
| |
| |
| logger.info("π Using Hugging Face API for response") |
| api_response = generate_with_huggingface_api([ |
| {"role": "user", "content": f"{STANLEY_AI_SYSTEM}\n\nUser: {user_message}"} |
| ]) |
| |
| if api_response: |
| enhanced_response = enhance_with_cultural_context(api_response.strip(), user_message) |
| set_cached_response(user_message, enhanced_response) |
| return enhanced_response |
| |
| |
| fallback_response = "Pole! I'm experiencing high demand. Please try again in a moment. Tafadhali jaribu tena." |
| return fallback_response |
|
|
| |
| |
| |
|
|
| def generate_image_huggingface(prompt, retry_count=3): |
| """Generate images using Hugging Face Inference API""" |
| headers = {"Authorization": f"Bearer {HF_TOKEN}"} |
| |
| for attempt in range(retry_count): |
| try: |
| logger.info(f"π¨ Generating image (attempt {attempt + 1}): {prompt[:50]}...") |
| |
| response = requests.post( |
| HF_API_URLS["image"], |
| headers=headers, |
| json={"inputs": prompt}, |
| timeout=60 |
| ) |
| |
| if response.status_code == 200: |
| image = Image.open(io.BytesIO(response.content)) |
| |
| |
| buffered = io.BytesIO() |
| image.save(buffered, format="PNG") |
| img_str = base64.b64encode(buffered.getvalue()).decode() |
| return f"data:image/png;base64,{img_str}" |
| |
| elif response.status_code == 503: |
| |
| wait_time = (attempt + 1) * 10 |
| logger.info(f"β³ Model loading, waiting {wait_time}s...") |
| time.sleep(wait_time) |
| continue |
| |
| else: |
| logger.error(f"β HF Image API error: {response.status_code}") |
| continue |
| |
| except requests.exceptions.Timeout: |
| logger.warning(f"β° Request timeout, attempt {attempt + 1}") |
| continue |
| except Exception as e: |
| logger.error(f"β Image generation error: {e}") |
| break |
| |
| return None |
|
|
| def generate_image_fallback(prompt): |
| """Create simple placeholder images""" |
| try: |
| from PIL import Image, ImageDraw |
| |
| |
| width, height = 512, 512 |
| img = Image.new('RGB', (width, height), color=( |
| random.randint(50, 200), |
| random.randint(50, 200), |
| random.randint(50, 200) |
| )) |
| |
| draw = ImageDraw.Draw(img) |
| |
| |
| for _ in range(5): |
| x1, y1 = random.randint(0, width), random.randint(0, height) |
| x2, y2 = random.randint(x1, width), random.randint(y1, height) |
| color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) |
| draw.rectangle([x1, y1, x2, y2], outline=color, width=3) |
| |
| |
| buffered = io.BytesIO() |
| img.save(buffered, format="PNG") |
| img_str = base64.b64encode(buffered.getvalue()).decode() |
| return f"data:image/png;base64,{img_str}" |
| |
| except Exception as e: |
| logger.error(f"Fallback image failed: {e}") |
| return None |
|
|
| def enhance_prompt_with_kiswahili(prompt): |
| """Add cultural context to image prompts""" |
| if detect_kiswahili_context(prompt): |
| enhancements = [ |
| "East African style", "vibrant African colors", "African landscape", |
| "cultural elements", "traditional patterns", "warm sunset colors", |
| "savanna background", "rich cultural symbolism" |
| ] |
| return f"{prompt}, {random.choice(enhancements)}" |
| return prompt |
|
|
| |
| |
| |
|
|
| @app.route('/') |
| def home(): |
| return jsonify({ |
| "message": "π STANLEY AI - Created by Stanley Samwel Owino (Machine Learning Engineer)", |
| "version": "3.0", |
| "creator": "Stanley Samwel Owino", |
| "role": "Machine Learning Engineer", |
| "features": [ |
| "Hugging Face Optimized", |
| "Fast Text Generation", |
| "Free Image Generation", |
| "Free Video Generation", |
| "Kiswahili Integration", |
| "Cultural Knowledge", |
| "Response Caching", |
| "API Fallbacks" |
| ], |
| "video_capabilities": [ |
| "Text-to-Video", |
| "Image-to-Video", |
| "Slideshow Creation", |
| "Text Animation", |
| "Cultural Themes" |
| ], |
| "status": "active", |
| "model": "Qwen2.5 + HF Inference", |
| "image_generation": "Hugging Face API", |
| "video_generation": "Hugging Face Free Models" |
| }) |
|
|
| @app.route('/api/chat', methods=['POST']) |
| def chat(): |
| try: |
| start_time = time.time() |
| data = request.get_json() |
| user_message = data.get('message', '') |
| |
| if not user_message: |
| return jsonify({"error": "Tafadhali provide a message"}), 400 |
| |
| logger.info(f"π¬ Processing: {user_message[:50]}...") |
| |
| |
| if detect_image_request(user_message): |
| image_prompt = extract_image_prompt(user_message) |
| enhanced_prompt = enhance_prompt_with_kiswahili(image_prompt) |
| |
| return jsonify({ |
| "response": f"π¨ I'll generate an image for: '{enhanced_prompt}'. Please use the image generation feature below!", |
| "image_suggestion": enhanced_prompt, |
| "status": "success", |
| "suggest_image": True, |
| "response_time": round(time.time() - start_time, 2) |
| }) |
| |
| |
| if video_gen.detect_video_request(user_message): |
| video_prompt = video_gen.extract_video_prompt(user_message) |
| enhanced_video_prompt = video_gen.enhance_prompt_with_context(video_prompt) |
| |
| return jsonify({ |
| "response": f"π¬ I can create a video for: '{enhanced_video_prompt}'. Use the video generation feature below!", |
| "video_suggestion": enhanced_video_prompt, |
| "status": "success", |
| "suggest_video": True, |
| "response_time": round(time.time() - start_time, 2) |
| }) |
| |
| response = generate_comprehensive_response(user_message) |
| response_time = round(time.time() - start_time, 2) |
| |
| has_kiswahili = detect_kiswahili_context(response) |
| |
| return jsonify({ |
| "response": response, |
| "status": "success", |
| "response_time": response_time, |
| "word_count": len(response.split()), |
| "model": "STANLEY-AI-HF", |
| "cultural_context": has_kiswahili, |
| "language": "en+sw" if has_kiswahili else "en", |
| "cached": get_cached_response(user_message) is not None |
| }) |
| |
| except Exception as e: |
| logger.error(f"Chat error: {e}") |
| return jsonify({ |
| "error": f"Pole! Processing error: {str(e)}", |
| "status": "error" |
| }), 500 |
|
|
| @app.route('/api/generate-image', methods=['POST']) |
| def generate_image_endpoint(): |
| """Generate images using Hugging Face""" |
| try: |
| start_time = time.time() |
| data = request.get_json() |
| prompt = data.get('prompt', '') |
| |
| if not prompt: |
| return jsonify({"error": "Tafadhali provide a prompt"}), 400 |
| |
| |
| enhanced_prompt = enhance_prompt_with_kiswahili(prompt) |
| |
| |
| image_data = generate_image_huggingface(enhanced_prompt) |
| |
| if not image_data: |
| logger.info("π Using fallback image generation") |
| image_data = generate_image_fallback(enhanced_prompt) |
| |
| if image_data: |
| generation_time = round(time.time() - start_time, 2) |
| |
| return jsonify({ |
| "image": image_data, |
| "prompt": prompt, |
| "enhanced_prompt": enhanced_prompt, |
| "status": "success", |
| "generation_time": generation_time, |
| "provider": "hugging_face", |
| "cultural_enhancement": enhanced_prompt != prompt |
| }) |
| else: |
| return jsonify({ |
| "error": "Pole! Image generation service is busy", |
| "status": "error" |
| }), 500 |
| |
| except Exception as e: |
| logger.error(f"Image endpoint error: {e}") |
| return jsonify({ |
| "error": f"Pole! Image generation failed: {str(e)}", |
| "status": "error" |
| }), 500 |
|
|
| @app.route('/api/generate-cultural-image', methods=['POST']) |
| def generate_cultural_image(): |
| """Generate images with specific Kiswahili cultural themes""" |
| try: |
| data = request.get_json() |
| theme = data.get('theme', '') |
| style = data.get('style', 'vibrant') |
| |
| if not theme: |
| return jsonify({"error": "Tafadhali provide a theme"}), 400 |
| |
| |
| cultural_templates = { |
| 'savanna': f"African savanna landscape with {theme}, acacia trees, warm sunset, majestic", |
| 'wildlife': f"African wildlife {theme}, natural habitat, detailed, realistic, beautiful", |
| 'culture': f"East African cultural scene {theme}, traditional, vibrant colors, community", |
| 'coastal': f"Swahili coast {theme}, Indian Ocean, dhows, traditional architecture", |
| 'lion_king': f"Lion King inspired {theme}, emotional, Disney style, African elements" |
| } |
| |
| base_template = cultural_templates.get(style, f"East African {theme}, cultural, vibrant") |
| |
| |
| modifiers = { |
| 'vibrant': 'vibrant colors, highly detailed, 4K resolution', |
| 'realistic': 'photorealistic, detailed, realistic lighting', |
| 'artistic': 'painterly, artistic, brush strokes, creative', |
| 'traditional': 'traditional African art, symbolic, patterns' |
| } |
| |
| final_prompt = f"{base_template}, {modifiers.get(style, 'vibrant colors')}" |
| |
| image_data = generate_image_huggingface(final_prompt) |
| |
| if image_data: |
| return jsonify({ |
| "image": image_data, |
| "theme": theme, |
| "style": style, |
| "prompt": final_prompt, |
| "status": "success", |
| "cultural_context": "kiswahili_theme" |
| }) |
| else: |
| return jsonify({ |
| "error": "Pole! Cultural image generation failed", |
| "status": "error" |
| }), 500 |
| |
| except Exception as e: |
| return jsonify({ |
| "error": f"Pole! Cultural image error: {str(e)}", |
| "status": "error" |
| }), 500 |
|
|
| @app.route('/api/generate-video', methods=['POST']) |
| def generate_video_endpoint(): |
| """Generate videos from text prompts""" |
| try: |
| start_time = time.time() |
| data = request.get_json() |
| prompt = data.get('prompt', '') |
| |
| if not prompt: |
| return jsonify({"error": "Tafadhali provide a video prompt"}), 400 |
| |
| |
| enhanced_prompt = video_gen.enhance_prompt_with_context(prompt) |
| |
| logger.info(f"π¬ Generating video: {enhanced_prompt[:50]}...") |
| |
| |
| video_data = video_gen.generate_text_to_video(enhanced_prompt) |
| |
| if video_data: |
| generation_time = round(time.time() - start_time, 2) |
| |
| return jsonify({ |
| "video": video_data, |
| "prompt": prompt, |
| "enhanced_prompt": enhanced_prompt, |
| "status": "success", |
| "generation_time": generation_time, |
| "format": "mp4", |
| "duration": "3-4 seconds", |
| "provider": "hugging_face_free", |
| "message": "Video generated successfully!" |
| }) |
| else: |
| return jsonify({ |
| "error": "Pole! Video generation service is busy. Try again in a moment.", |
| "status": "error", |
| "fallback_suggestion": "You can try generating individual images instead." |
| }), 500 |
| |
| except Exception as e: |
| logger.error(f"Video endpoint error: {e}") |
| return jsonify({ |
| "error": f"Pole! Video generation failed: {str(e)}", |
| "status": "error" |
| }), 500 |
|
|
| @app.route('/api/generate-cultural-video', methods=['POST']) |
| def generate_cultural_video_endpoint(): |
| """Generate videos with specific Kiswahili cultural themes""" |
| try: |
| start_time = time.time() |
| data = request.get_json() |
| theme = data.get('theme', 'safari') |
| style = data.get('style', 'animated') |
| |
| logger.info(f"π Generating cultural video: {theme} ({style} style)") |
| |
| |
| video_data = video_gen.create_cultural_video(theme, style) |
| |
| if video_data: |
| generation_time = round(time.time() - start_time, 2) |
| |
| |
| theme_descriptions = { |
| "safari": "African wildlife and landscapes", |
| "dance": "Traditional dance and celebration", |
| "market": "Vibrant African market scene", |
| "coastal": "Swahili coast and ocean", |
| "wildlife": "African wildlife documentary", |
| "village": "Traditional village life" |
| } |
| |
| return jsonify({ |
| "video": video_data, |
| "theme": theme, |
| "style": style, |
| "description": theme_descriptions.get(theme, "Cultural scene"), |
| "status": "success", |
| "generation_time": generation_time, |
| "cultural_context": "kiswahili_theme", |
| "message": f"Cultural video generated: {theme.replace('_', ' ').title()}" |
| }) |
| else: |
| return jsonify({ |
| "error": "Pole! Cultural video generation failed", |
| "status": "error", |
| "suggestion": "Try a different theme or style" |
| }), 500 |
| |
| except Exception as e: |
| logger.error(f"Cultural video error: {e}") |
| return jsonify({ |
| "error": f"Pole! Cultural video failed: {str(e)}", |
| "status": "error" |
| }), 500 |
|
|
| @app.route('/api/animate-text', methods=['POST']) |
| def animate_text_endpoint(): |
| """Create animated text videos""" |
| try: |
| start_time = time.time() |
| data = request.get_json() |
| text = data.get('text', 'Hello World!') |
| animation_type = data.get('animation_type', 'pulse') |
| |
| if not text: |
| return jsonify({"error": "Tafadhali provide text to animate"}), 400 |
| |
| |
| video_data = video_gen.generate_animation_from_text(text) |
| |
| if video_data: |
| generation_time = round(time.time() - start_time, 2) |
| |
| return jsonify({ |
| "video": video_data, |
| "text": text, |
| "animation_type": animation_type, |
| "status": "success", |
| "generation_time": generation_time, |
| "format": "mp4", |
| "duration": "3 seconds", |
| "message": "Text animation created!" |
| }) |
| else: |
| return jsonify({ |
| "error": "Pole! Text animation failed", |
| "status": "error" |
| }), 500 |
| |
| except Exception as e: |
| logger.error(f"Text animation error: {e}") |
| return jsonify({ |
| "error": f"Pole! Text animation failed: {str(e)}", |
| "status": "error" |
| }), 500 |
|
|
| @app.route('/api/create-slideshow', methods=['POST']) |
| def create_slideshow_endpoint(): |
| """Create video slideshow from images""" |
| try: |
| start_time = time.time() |
| data = request.get_json() |
| images = data.get('images', []) |
| duration = data.get('duration', 2.0) |
| |
| if not images or len(images) < 2: |
| return jsonify({ |
| "error": "Tafadhali provide at least 2 images", |
| "status": "error" |
| }), 400 |
| |
| |
| video_data = video_gen.create_slideshow_video(images, duration) |
| |
| if video_data: |
| generation_time = round(time.time() - start_time, 2) |
| |
| return jsonify({ |
| "video": video_data, |
| "image_count": len(images), |
| "duration_per_image": duration, |
| "total_duration": len(images) * duration, |
| "status": "success", |
| "generation_time": generation_time, |
| "format": "mp4", |
| "message": f"Slideshow created with {len(images)} images" |
| }) |
| else: |
| return jsonify({ |
| "error": "Pole! Slideshow creation failed", |
| "status": "error" |
| }), 500 |
| |
| except Exception as e: |
| logger.error(f"Slideshow error: {e}") |
| return jsonify({ |
| "error": f"Pole! Slideshow failed: {str(e)}", |
| "status": "error" |
| }), 500 |
|
|
| @app.route('/api/image-to-video', methods=['POST']) |
| def image_to_video_endpoint(): |
| """Generate video from an image""" |
| try: |
| start_time = time.time() |
| data = request.get_json() |
| image_data = data.get('image', '') |
| prompt = data.get('prompt', '') |
| |
| if not image_data: |
| return jsonify({"error": "Tafadhali provide an image"}), 400 |
| |
| |
| video_data = video_gen.generate_image_to_video(image_data, prompt) |
| |
| if video_data: |
| generation_time = round(time.time() - start_time, 2) |
| |
| return jsonify({ |
| "video": video_data, |
| "prompt": prompt if prompt else "Generated from image", |
| "status": "success", |
| "generation_time": generation_time, |
| "format": "mp4", |
| "duration": "4 seconds", |
| "provider": "hugging_face_free", |
| "message": "Video generated from image!" |
| }) |
| else: |
| return jsonify({ |
| "error": "Pole! Image to video conversion failed", |
| "status": "error" |
| }), 500 |
| |
| except Exception as e: |
| logger.error(f"Image to video error: {e}") |
| return jsonify({ |
| "error": f"Pole! Image to video failed: {str(e)}", |
| "status": "error" |
| }), 500 |
|
|
| @app.route('/api/video/info') |
| def video_info_endpoint(): |
| """Get information about video generation capabilities""" |
| try: |
| info = video_gen.get_video_info() |
| |
| return jsonify({ |
| "status": "success", |
| "video_capabilities": info, |
| "creator": "Stanley Samwel Owino", |
| "note": "Free video generation powered by Hugging Face open-source models", |
| "supported_formats": ["MP4", "WebM"], |
| "max_resolution": "576x320", |
| "typical_generation_time": "30-90 seconds", |
| "free_models_available": True |
| }) |
| |
| except Exception as e: |
| return jsonify({ |
| "error": f"Pole! Could not get video info: {str(e)}", |
| "status": "error" |
| }), 500 |
|
|
| @app.route('/api/detect-video-request', methods=['POST']) |
| def detect_video_request_endpoint(): |
| """Detect if user wants to generate a video""" |
| try: |
| data = request.get_json() |
| text = data.get('text', '') |
| |
| if not text: |
| return jsonify({"error": "Tafadhali provide text"}), 400 |
| |
| is_video_request = video_gen.detect_video_request(text) |
| prompt = None |
| |
| if is_video_request: |
| prompt = video_gen.extract_video_prompt(text) |
| |
| return jsonify({ |
| "is_video_request": is_video_request, |
| "extracted_prompt": prompt, |
| "suggested_endpoint": "/api/generate-video" if is_video_request else None, |
| "status": "success" |
| }) |
| |
| except Exception as e: |
| return jsonify({ |
| "error": f"Pole! Detection failed: {str(e)}", |
| "status": "error" |
| }), 500 |
|
|
| @app.route('/api/quick-chat', methods=['POST']) |
| def quick_chat(): |
| """Faster chat endpoint for simple queries""" |
| try: |
| data = request.get_json() |
| user_message = data.get('message', '') |
| |
| if not user_message: |
| return jsonify({"error": "Tafadhali provide a message"}), 400 |
| |
| |
| quick_responses = { |
| 'hello': 'Habari! Stanley AI hapa. Ninaweza kukusaidia nini leo?', |
| 'hi': 'Habari! Karibu kwa Stanley AI. How can I help you today?', |
| 'thanks': 'Asante sana! Karibu tena.', |
| 'thank you': 'Asante! Happy to help.', |
| 'help': 'Ninaweza kukupa: Maelezo, Picha, Video, Maarifa ya Kiswahili, na zaidi!', |
| 'who created you': 'I was created by Stanley Samwel Owino, a Machine Learning Engineer from Kenya.', |
| 'who made you': 'Stanley Samwel Owino - Machine Learning Engineer and AI researcher from Kenya.', |
| 'creator': 'Stanley Samwel Owino - Machine Learning Engineer passionate about AI and cultural integration.', |
| 'can you make videos': 'Ndio! I can create videos from text, images, and cultural themes. Try the video generation feature!', |
| 'video capabilities': 'I can generate: 1) Text-to-video, 2) Image-to-video, 3) Slideshows, 4) Text animations, 5) Cultural theme videos', |
| 'make a video': 'Sure! Just use the video generation endpoint or tell me what you want to create a video of.' |
| } |
| |
| msg_lower = user_message.lower().strip() |
| if msg_lower in quick_responses: |
| return jsonify({ |
| "response": quick_responses[msg_lower], |
| "status": "success", |
| "quick_response": True |
| }) |
| |
| |
| return chat() |
| |
| except Exception as e: |
| return jsonify({ |
| "error": f"Pole! Quick chat error: {str(e)}", |
| "status": "error" |
| }), 500 |
|
|
| @app.route('/api/system/status') |
| def system_status(): |
| """System status with Hugging Face info""" |
| return jsonify({ |
| "status": "operational", |
| "creator": "Stanley Samwel Owino", |
| "role": "Machine Learning Engineer", |
| "model_loaded": model_loaded, |
| "hugging_face_available": True, |
| "video_generation_available": True, |
| "cache_size": len(response_cache), |
| "features": [ |
| "Text Generation", |
| "Image Generation", |
| "Video Generation", |
| "Kiswahili Knowledge", |
| "Cultural Integration", |
| "Fast Responses" |
| ], |
| "optimizations": [ |
| "Response Caching", |
| "API Fallbacks", |
| "Quick Responses", |
| "Cultural Prompts", |
| "Video Compression" |
| ] |
| }) |
|
|
| @app.route('/api/cache/clear', methods=['POST']) |
| def clear_cache(): |
| """Clear response cache""" |
| try: |
| cache_size = len(response_cache) |
| response_cache.clear() |
| |
| return jsonify({ |
| "status": "success", |
| "message": "Cache cleared", |
| "cleared_entries": cache_size |
| }) |
| except Exception as e: |
| return jsonify({ |
| "error": f"Cache clearance failed: {str(e)}", |
| "status": "error" |
| }), 500 |
|
|
| @app.route('/api/kiswahili/proverbs') |
| def get_proverbs(): |
| """Get random Swahili proverbs""" |
| proverbs = [ |
| "Mwacha mila ni mtumwa.", |
| "Haraka haraka haina baraka.", |
| "Asiyesikia la mkuu huvunjika guu.", |
| "Mwenye pupa hadiriki kula tamu.", |
| "Ukiona vyaelea, vimeundwa." |
| ] |
| return jsonify({ |
| "proverb": random.choice(proverbs), |
| "language": "Kiswahili", |
| "meaning": "Cultural wisdom from East Africa" |
| }) |
|
|
| @app.route('/api/kiswahili/phrases') |
| def get_phrases(): |
| """Get common Swahili phrases""" |
| phrases = { |
| "Hello": "Habari", |
| "Thank you": "Asante", |
| "Welcome": "Karibu", |
| "Sorry": "Pole", |
| "Goodbye": "Kwaheri", |
| "How are you?": "Habari yako?", |
| "I'm fine": "Nzuri", |
| "Please": "Tafadhali", |
| "Yes": "Ndio", |
| "No": "Hapana", |
| "I love you": "Nakupenda", |
| "See you later": "Tutaonana", |
| "Congratulations": "Hongera", |
| "Good luck": "Bahati njema", |
| "Have a good day": "Siku njema" |
| } |
| return jsonify(phrases) |
|
|
| @app.route('/api/kiswahili/learn') |
| def learn_kiswahili(): |
| """Interactive Kiswahili learning""" |
| lessons = { |
| "basics": { |
| "greetings": { |
| "Habari": "Hello / How are you?", |
| "Nzuri": "Good / Fine", |
| "Asante": "Thank you", |
| "Karibu": "Welcome / You're welcome", |
| "Tafadhali": "Please" |
| }, |
| "questions": { |
| "Unaitwa nani?": "What is your name?", |
| "Unatoka wapi?": "Where are you from?", |
| "Unaishi wapi?": "Where do you live?", |
| "Unafanya nini?": "What do you do?" |
| }, |
| "responses": { |
| "Ninaitwa...": "My name is...", |
| "Ninatoka Kenya": "I am from Kenya", |
| "Naishi Nairobi": "I live in Nairobi", |
| "Mimi ni mwanafunzi": "I am a student" |
| } |
| }, |
| "numbers": { |
| "1": "Moja", |
| "2": "Mbili", |
| "3": "Tatu", |
| "4": "Nne", |
| "5": "Tano", |
| "10": "Kumi", |
| "100": "Mia moja" |
| }, |
| "culture": { |
| "Hakuna Matata": "No worries / No problems", |
| "Pole pole": "Slowly slowly (proverb)", |
| "Haraka haraka haina baraka": "Hurry hurry has no blessing", |
| "Jambo": "Hello / Matter / Issue" |
| } |
| } |
| return jsonify({ |
| "lessons": lessons, |
| "language": "Kiswahili", |
| "region": "East Africa", |
| "note": "Interactive learning by Stanley AI" |
| }) |
|
|
| if __name__ == '__main__': |
| print("π STANLEY AI - Complete Edition with Video Generation") |
| print("π¨βπ» Created by: Stanley Samwel Owino - Machine Learning Engineer") |
| print("π Kiswahili Knowledge: Loaded") |
| print("πΌοΈ Image Generation: Hugging Face API") |
| print("π¬ Video Generation: Free Hugging Face Models") |
| print("β‘ Performance: Optimized") |
| print("π§ Fallbacks: Enabled") |
| print("π API Endpoints: Active") |
| print("=" * 50) |
| print("Available Endpoints:") |
| print("1. /api/chat - Text chat with AI") |
| print("2. /api/generate-image - Image generation") |
| print("3. /api/generate-video - Video generation from text") |
| print("4. /api/generate-cultural-video - Cultural theme videos") |
| print("5. /api/animate-text - Text animation") |
| print("6. /api/create-slideshow - Slideshow from images") |
| print("7. /api/image-to-video - Video from images") |
| print("8. /api/quick-chat - Fast responses") |
| print("9. /api/kiswahili/* - Kiswahili learning") |
| print("=" * 50) |
| |
| app.run(debug=True, host='0.0.0.0', port=7860, threaded=True) |