Download mindfull_web_api.py from IamSamkk/mindfull: direct link, hf CLI and curl.
- Browser
- Download file 10 kB
-
https://huggingface.co/spaces/IamSamkk/mindfull/resolve/main/mindfull_web_api.py
- Command line
-
hf download hf://spaces/IamSamkk/mindfull/mindfull_web_api.py
-
curl -L -o mindfull_web_api.py https://huggingface.co/spaces/IamSamkk/mindfull/resolve/main/mindfull_web_api.py
10 kB
| #!/usr/bin/env python3 | |
| """ | |
| Mindfull AI Avatar Chatbot - Web API | |
| Flask web server for serving the Mindfull pipeline via HTTP API | |
| """ | |
| import os | |
| import json | |
| import uuid | |
| import threading | |
| from datetime import datetime | |
| from pathlib import Path | |
| from flask import Flask, request, jsonify, send_file, send_from_directory | |
| from flask_cors import CORS | |
| import logging | |
| # Import the pipeline | |
| from mindfull_pipeline import MindfullPipeline | |
| from mindfull_config import config, logger | |
| # Create Flask app | |
| app = Flask(__name__) | |
| CORS(app, origins=config.CORS_ORIGINS) | |
| # Global pipeline instance | |
| pipeline = None | |
| active_sessions = {} | |
| session_lock = threading.Lock() | |
| def initialize_app(): | |
| """Initialize the Flask application""" | |
| global pipeline | |
| logger.info("Initializing Mindfull Web API...") | |
| # Initialize pipeline | |
| pipeline = MindfullPipeline() | |
| if not pipeline.is_initialized: | |
| logger.error("Failed to initialize Mindfull pipeline") | |
| return False | |
| logger.info("✅ Mindfull Web API initialized successfully") | |
| return True | |
| def health_check(): | |
| """Health check endpoint""" | |
| if not pipeline or not pipeline.is_initialized: | |
| return jsonify({ | |
| 'status': 'error', | |
| 'message': 'Pipeline not initialized' | |
| }), 503 | |
| return jsonify({ | |
| 'status': 'healthy', | |
| 'timestamp': datetime.now().isoformat(), | |
| 'components': { | |
| 'ollama': pipeline.ollama_available, | |
| 'f5tts': pipeline.f5tts_available, | |
| 'sadtalker': pipeline.sadtalker_available | |
| } | |
| }) | |
| def create_session(): | |
| """Create a new chat session""" | |
| try: | |
| session_id = pipeline.create_session() | |
| with session_lock: | |
| active_sessions[session_id] = { | |
| 'created': datetime.now().isoformat(), | |
| 'last_activity': datetime.now().isoformat() | |
| } | |
| return jsonify({ | |
| 'status': 'success', | |
| 'session_id': session_id, | |
| 'message': 'Session created successfully' | |
| }) | |
| except Exception as e: | |
| logger.error(f"Error creating session: {str(e)}") | |
| return jsonify({ | |
| 'status': 'error', | |
| 'message': 'Failed to create session' | |
| }), 500 | |
| def get_session_info(session_id): | |
| """Get session information""" | |
| try: | |
| if session_id not in active_sessions: | |
| return jsonify({ | |
| 'status': 'error', | |
| 'message': 'Session not found' | |
| }), 404 | |
| session_info = pipeline.get_session_info() | |
| return jsonify({ | |
| 'status': 'success', | |
| 'session_info': session_info | |
| }) | |
| except Exception as e: | |
| logger.error(f"Error getting session info: {str(e)}") | |
| return jsonify({ | |
| 'status': 'error', | |
| 'message': 'Failed to get session info' | |
| }), 500 | |
| def chat(): | |
| """Main chat endpoint""" | |
| try: | |
| data = request.get_json() | |
| if not data or 'message' not in data: | |
| return jsonify({ | |
| 'status': 'error', | |
| 'message': 'Missing message in request' | |
| }), 400 | |
| user_message = data['message'].strip() | |
| session_id = data.get('session_id') | |
| include_video = data.get('include_video', True) | |
| avatar_image = data.get('avatar_image') # Optional custom avatar | |
| # Validate input | |
| if len(user_message) < config.MIN_TEXT_LENGTH: | |
| return jsonify({ | |
| 'status': 'error', | |
| 'message': 'Message too short' | |
| }), 400 | |
| if len(user_message) > config.MAX_TEXT_LENGTH: | |
| return jsonify({ | |
| 'status': 'error', | |
| 'message': 'Message too long' | |
| }), 400 | |
| # Update session activity | |
| if session_id and session_id in active_sessions: | |
| with session_lock: | |
| active_sessions[session_id]['last_activity'] = datetime.now().isoformat() | |
| # Process the interaction | |
| if include_video: | |
| result = pipeline.process_complete_interaction(user_message, avatar_image) | |
| else: | |
| # Text and audio only | |
| response_text, emotion = pipeline.generate_response(user_message) | |
| audio_path = pipeline.generate_audio(response_text) | |
| result = { | |
| 'session_id': session_id, | |
| 'user_input': user_message, | |
| 'timestamp': datetime.now().isoformat(), | |
| 'response_text': response_text, | |
| 'emotion_detected': emotion, | |
| 'audio_path': audio_path, | |
| 'video_path': None, | |
| 'processing_time': 0, | |
| 'errors': [] | |
| } | |
| # Prepare response | |
| response_data = { | |
| 'status': 'success', | |
| 'session_id': result['session_id'], | |
| 'response_text': result['response_text'], | |
| 'emotion_detected': result['emotion_detected'], | |
| 'processing_time': result['processing_time'], | |
| 'timestamp': result['timestamp'] | |
| } | |
| # Add file URLs if files were generated | |
| if result['audio_path']: | |
| audio_filename = Path(result['audio_path']).name | |
| response_data['audio_url'] = f'/audio/{audio_filename}' | |
| if result['video_path']: | |
| video_filename = Path(result['video_path']).name | |
| response_data['video_url'] = f'/video/{video_filename}' | |
| if result['errors']: | |
| response_data['warnings'] = result['errors'] | |
| return jsonify(response_data) | |
| except Exception as e: | |
| logger.error(f"Error in chat endpoint: {str(e)}") | |
| return jsonify({ | |
| 'status': 'error', | |
| 'message': 'Internal server error' | |
| }), 500 | |
| def serve_audio(filename): | |
| """Serve audio files""" | |
| try: | |
| return send_from_directory(config.AUDIO_OUTPUT_DIR, filename) | |
| except FileNotFoundError: | |
| return jsonify({'error': 'Audio file not found'}), 404 | |
| def serve_video(filename): | |
| """Serve video files""" | |
| try: | |
| return send_from_directory(config.VIDEO_OUTPUT_DIR, filename) | |
| except FileNotFoundError: | |
| return jsonify({'error': 'Video file not found'}), 404 | |
| def get_model_status(): | |
| """Get status of all models""" | |
| try: | |
| model_status = config.get_model_status() | |
| return jsonify({ | |
| 'status': 'success', | |
| 'models': model_status, | |
| 'pipeline_status': { | |
| 'ollama': pipeline.ollama_available if pipeline else False, | |
| 'f5tts': pipeline.f5tts_available if pipeline else False, | |
| 'sadtalker': pipeline.sadtalker_available if pipeline else False | |
| } | |
| }) | |
| except Exception as e: | |
| logger.error(f"Error getting model status: {str(e)}") | |
| return jsonify({ | |
| 'status': 'error', | |
| 'message': 'Failed to get model status' | |
| }), 500 | |
| def cleanup_files(): | |
| """Clean up old generated files""" | |
| try: | |
| data = request.get_json() or {} | |
| max_age_hours = data.get('max_age_hours', 24) | |
| if pipeline: | |
| pipeline.cleanup_old_files(max_age_hours) | |
| return jsonify({ | |
| 'status': 'success', | |
| 'message': f'Cleaned up files older than {max_age_hours} hours' | |
| }) | |
| except Exception as e: | |
| logger.error(f"Error during cleanup: {str(e)}") | |
| return jsonify({ | |
| 'status': 'error', | |
| 'message': 'Cleanup failed' | |
| }), 500 | |
| def get_config(): | |
| """Get configuration information""" | |
| return jsonify({ | |
| 'status': 'success', | |
| 'config': { | |
| 'max_text_length': config.MAX_TEXT_LENGTH, | |
| 'min_text_length': config.MIN_TEXT_LENGTH, | |
| 'allowed_languages': config.ALLOWED_LANGUAGES, | |
| 'session_timeout': config.SESSION_TIMEOUT, | |
| 'available_emotions': list(config.EMOTION_KEYWORDS.keys()), | |
| 'default_model': config.DEFAULT_MODEL, | |
| 'fallback_model': config.FALLBACK_MODEL | |
| } | |
| }) | |
| def index(): | |
| """Main index page""" | |
| return jsonify({ | |
| 'service': 'Mindfull AI Avatar Chatbot', | |
| 'version': '1.0.0', | |
| 'status': 'running', | |
| 'endpoints': { | |
| 'health': '/health', | |
| 'create_session': '/session [POST]', | |
| 'chat': '/chat [POST]', | |
| 'get_config': '/config [GET]', | |
| 'model_status': '/models [GET]', | |
| 'cleanup': '/cleanup [POST]' | |
| }, | |
| 'documentation': 'See API documentation for usage details' | |
| }) | |
| def not_found(error): | |
| return jsonify({'error': 'Endpoint not found'}), 404 | |
| def internal_error(error): | |
| return jsonify({'error': 'Internal server error'}), 500 | |
| def run_server(host=None, port=None, debug=None): | |
| """Run the Flask server""" | |
| host = host or config.WEB_HOST | |
| port = port or config.WEB_PORT | |
| debug = debug or config.WEB_DEBUG | |
| logger.info(f"Starting Mindfull Web API server on {host}:{port}") | |
| app.run( | |
| host=host, | |
| port=port, | |
| debug=debug, | |
| threaded=config.WEB_THREADED | |
| ) | |
| if __name__ == '__main__': | |
| if initialize_app(): | |
| run_server() | |
| else: | |
| logger.error("Failed to initialize application") | |
| exit(1) | |