dfdfdsfgs commited on
Commit
2c50e10
·
1 Parent(s): 550af36
Files changed (4) hide show
  1. DEPLOYMENT_GUIDE.md +150 -170
  2. app.py +380 -5
  3. requirements_hf.txt +27 -3
  4. test_video_generation.py +116 -0
DEPLOYMENT_GUIDE.md CHANGED
@@ -1,230 +1,210 @@
1
- # 🚀 Hugging Face Spaces Deployment Guide
2
 
3
- This guide will walk you through deploying the Theorem Explanation Agent to Hugging Face Spaces.
 
4
 
5
- ## 📋 Prerequisites
 
 
 
6
 
7
- 1. **Hugging Face Account**: Create an account at [huggingface.co](https://huggingface.co)
8
- 2. **Gemini API Key(s)**: Get from [Google AI Studio](https://makersuite.google.com/app/apikey)
9
- 3. **Optional**: ElevenLabs API key for text-to-speech
10
-
11
- ## 🔧 Step-by-Step Deployment
12
-
13
- ### Step 1: Create a New Space
14
 
 
15
  1. Go to [Hugging Face Spaces](https://huggingface.co/spaces)
16
  2. Click "Create new Space"
17
- 3. Fill in details:
18
- - **Space name**: `theorem-explanation-agent` (or your choice)
19
  - **License**: MIT
20
  - **SDK**: Gradio
21
- - **Hardware**: CPU Basic (can upgrade later)
22
- - **Visibility**: Public
23
 
24
- ### Step 2: Upload Your Code
 
 
 
 
 
25
 
26
- You have two options:
 
27
 
28
- #### Option A: Git Clone (Recommended)
29
  ```bash
30
- git clone https://github.com/yourusername/theorem-explanation-agent
31
- cd theorem-explanation-agent
32
- git remote add hf https://huggingface.co/spaces/yourusername/theorem-explanation-agent
33
- git push hf main
34
- ```
35
-
36
- #### Option B: Upload Files Manually
37
- 1. Upload these key files to your Space:
38
- - `app.py`
39
- - `huggingface_spaces_app.py`
40
- - `requirements_hf.txt`
41
- - `README_HUGGINGFACE.md`
42
- - All folders: `src/`, `mllm_tools/`, etc.
43
-
44
- ### Step 3: Configure API Keys
45
-
46
- 1. Go to your Space's **Settings** tab
47
- 2. Scroll down to **Repository secrets**
48
- 3. Add these secrets:
49
-
50
- #### Required Secrets
51
-
52
- **Multiple API Keys (Recommended)**
53
- ```
54
- Name: GEMINI_API_KEY
55
- Value: AIzaSyA1...,AIzaSyB2...,AIzaSyC3...,AIzaSyD4...
56
  ```
57
 
58
- **Single API Key**
59
- ```
60
- Name: GEMINI_API_KEY
61
- Value: AIzaSyA1...
62
  ```
63
 
64
- #### Optional Secrets
65
-
66
- **Enable Full Mode**
67
- ```
68
- Name: DEMO_MODE
69
- Value: false
70
  ```
71
 
72
- **Text-to-Speech (Optional)**
73
- ```
74
- Name: ELEVENLABS_API_KEY
75
- Value: your_elevenlabs_api_key
76
- ```
77
 
78
- ### Step 4: Configure App Settings
 
 
 
79
 
80
- In your Space settings:
 
 
 
81
 
82
- 1. **Hardware**:
83
- - Start with CPU Basic (free)
84
- - Upgrade to CPU Optimized for better performance
85
- - Use GPU only if you enable advanced features
86
 
87
- 2. **Environment**:
88
- - Python version: 3.9+
89
- - Gradio SDK will be automatically detected
90
 
91
- 3. **Persistent Storage** (Optional):
92
- - Enable if you want to keep generated videos
93
- - Useful for caching and avoiding regeneration
94
 
95
- ## 🔑 API Key Setup Details
 
 
 
 
96
 
97
- ### How the Fallback System Works
 
 
 
98
 
99
- The app uses a smart API key rotation system:
100
 
101
- ```python
102
- # Your GEMINI_API_KEY can be:
103
- # Single key: "AIzaSyA..."
104
- # Multiple keys: "AIzaSyA...,AIzaSyB...,AIzaSyC..."
105
 
106
- # The system will:
107
- # 1. Parse comma-separated keys
108
- # 2. Randomly select one for each request
109
- # 3. Automatically retry with different keys if one fails
110
- # 4. Log which key is being used (first 20 chars only)
111
  ```
112
 
113
- ### Benefits of Multiple Keys
114
-
115
- 1. **Rate Limit Avoidance**: Distributes requests across keys
116
- 2. **Higher Throughput**: Can handle more concurrent requests
117
- 3. **Fault Tolerance**: If one key fails, others continue working
118
- 4. **Cost Distribution**: Spreads usage across multiple billing accounts
119
-
120
- ### Recommended Setup
121
-
122
- For production use, we recommend **4 API keys**:
123
-
124
  ```
125
- GEMINI_API_KEY=key1,key2,key3,key4
 
126
  ```
127
 
128
- This provides good balance between rate limit avoidance and key management complexity.
129
-
130
- ## 📊 Monitoring and Costs
131
-
132
- ### Cost Estimation
133
-
134
- - **Demo Mode**: Free (no API calls)
135
- - **Single Scene**: ~$0.001-0.01 per generation
136
- - **Full Video (3-6 scenes)**: ~$0.01-0.05 per generation
137
- - **Multiple API Keys**: Costs distributed across accounts
138
-
139
- ### Monitoring Usage
140
-
141
- 1. **Google Cloud Console**: Monitor API usage per key
142
- 2. **Hugging Face Metrics**: View Space usage and performance
143
- 3. **App Logs**: Check which API keys are being selected
144
-
145
- ### Usage Patterns
146
-
147
  ```
148
- Selected random Gemini API key from 4 available keys: AIzaSyDuKKriNMayoPwn...
149
- Selected random Gemini API key from 4 available keys: AIzaSyDa44QjZES9qp8L...
150
  ```
151
 
152
- ## 🔧 Troubleshooting
153
-
154
- ### Common Issues
 
 
155
 
156
- 1. **"Demo mode active"**
157
- - Check `GEMINI_API_KEY` is set in Secrets
158
- - Verify key format (comma-separated if multiple)
159
- - Ensure `DEMO_MODE=false` if you want full functionality
160
 
161
- 2. **"Rate limit exceeded"**
162
- - Add more API keys to your `GEMINI_API_KEY`
163
- - Wait a few minutes before retrying
164
- - Consider upgrading to paid Gemini tier
165
 
166
- 3. **"Generation failed"**
167
- - Try simpler topics first
168
- - Check API key validity
169
- - Verify topic is educational/mathematical
 
170
 
171
- 4. **Slow performance**
172
- - Upgrade Hardware tier in Space settings
173
- - Use multiple API keys for better throughput
174
- - Enable persistent storage for caching
 
175
 
176
- ### Error Messages and Solutions
177
 
178
- | Error | Solution |
179
- |-------|----------|
180
- | `No API_KEY found` | Set `GEMINI_API_KEY` in Secrets |
181
- | `Model is overloaded` | Add more API keys or retry later |
182
- | `Invalid API key` | Check key format and validity |
183
- | `Demo mode active` | Set API keys and `DEMO_MODE=false` |
184
 
185
- ## 🚀 Performance Optimization
 
 
 
186
 
187
- ### Hardware Recommendations
 
 
 
188
 
189
- - **CPU Basic**: Good for demo and light usage
190
- - **CPU Optimized**: Better for regular usage
191
- - **GPU**: Only needed for advanced video processing
192
 
193
- ### API Key Strategy
 
 
 
 
 
 
 
 
 
194
 
 
 
195
  ```python
196
- # Optimal setup for production:
197
- GEMINI_API_KEY=key1,key2,key3,key4
198
- DEMO_MODE=false
199
- ELEVENLABS_API_KEY=optional_tts_key
200
  ```
201
 
202
- ### Scaling Considerations
 
 
 
 
 
 
 
203
 
204
- 1. **Multiple Keys**: 4-6 keys for high usage
205
- 2. **Persistent Storage**: Cache results to avoid regeneration
206
- 3. **Hardware Upgrade**: CPU Optimized or GPU for faster processing
207
- 4. **Rate Limiting**: Implement user request limiting if needed
208
 
209
- ## 📞 Support and Resources
 
 
 
210
 
211
- ### Hugging Face Resources
212
- - [Spaces Documentation](https://huggingface.co/docs/hub/spaces)
213
- - [Gradio Documentation](https://gradio.app/docs/)
214
- - [Community Forums](https://discuss.huggingface.co/)
215
 
216
- ### API Resources
217
- - [Google AI Studio](https://makersuite.google.com/)
218
- - [Gemini API Documentation](https://ai.google.dev/)
219
- - [ElevenLabs API](https://elevenlabs.io/docs/)
220
 
221
  ### Getting Help
 
 
 
 
 
 
 
 
 
 
 
 
222
 
223
- 1. **Check app logs** in Space settings
224
- 2. **Test with simple topics** first
225
- 3. **Verify API keys** in Google Cloud Console
226
- 4. **Monitor costs** and usage patterns
227
 
228
  ---
229
 
230
- **Ready to deploy?** Follow these steps and you'll have your Theorem Explanation Agent running on Hugging Face Spaces with automatic API key rotation!
 
1
+ # Deployment Guide: Theorem Explanation Agent
2
 
3
+ ## Overview
4
+ This guide explains how to deploy the Theorem Explanation Agent to Hugging Face Spaces for actual video generation.
5
 
6
+ ## Prerequisites
7
+ - Hugging Face account
8
+ - Gemini API key(s) from Google AI Studio
9
+ - Basic understanding of environment variables
10
 
11
+ ## Quick Start
 
 
 
 
 
 
12
 
13
+ ### 1. Create New Hugging Face Space
14
  1. Go to [Hugging Face Spaces](https://huggingface.co/spaces)
15
  2. Click "Create new Space"
16
+ 3. Configure:
17
+ - **Space name**: Your choice (e.g., "theorem-explanation-agent")
18
  - **License**: MIT
19
  - **SDK**: Gradio
20
+ - **Hardware**: CPU Basic (sufficient for most cases)
21
+ - **Visibility**: Public or Private
22
 
23
+ ### 2. Upload Files
24
+ Upload these files to your space:
25
+ - `app.py` (main application)
26
+ - `requirements_hf.txt` (rename to `requirements.txt`)
27
+ - `README_HUGGINGFACE.md` (rename to `README.md`)
28
+ - All source files from `src/`, `mllm_tools/`, etc.
29
 
30
+ ### 3. Set Environment Variables
31
+ In your Hugging Face Space settings, add:
32
 
33
+ **For Single API Key:**
34
  ```bash
35
+ GEMINI_API_KEY=your-actual-gemini-api-key
36
+ DEMO_MODE=false
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  ```
38
 
39
+ **For Multiple API Keys (Recommended):**
40
+ ```bash
41
+ GEMINI_API_KEY=key1,key2,key3,key4
42
+ DEMO_MODE=false
43
  ```
44
 
45
+ **Optional Settings:**
46
+ ```bash
47
+ ELEVENLABS_API_KEY=your-elevenlabs-key # For TTS
48
+ LANGFUSE_SECRET_KEY=your-langfuse-key # For logging
 
 
49
  ```
50
 
51
+ ## Features Enabled
 
 
 
 
52
 
53
+ ### Real Video Generation
54
+ - **DEMO_MODE=false**: Enables actual video generation
55
+ - **Gemini 2.0 Flash Exp**: Latest model for best results
56
+ - **Manim Integration**: Professional mathematical animations
57
 
58
+ ### Comma-Separated API Keys
59
+ - **Load Balancing**: Distributes requests across multiple keys
60
+ - **Failover**: Automatic switching if one key fails
61
+ - **Cost Distribution**: Spreads usage across billing accounts
62
 
63
+ ### Educational Focus
64
+ - **Mathematical Concepts**: Optimized for STEM education
65
+ - **Visual Learning**: Geometric proofs and demonstrations
66
+ - **Progressive Difficulty**: Suitable for various learning levels
67
 
68
+ ## Usage Instructions
 
 
69
 
70
+ ### 1. Access Your Space
71
+ Visit: `https://huggingface.co/spaces/YOUR_USERNAME/YOUR_SPACE_NAME`
 
72
 
73
+ ### 2. Generate Videos
74
+ 1. **Enter Topic**: e.g., "Pythagorean Theorem"
75
+ 2. **Add Context**: Specify focus areas or audience
76
+ 3. **Set Scenes**: 2-3 scenes for testing, up to 6 for full videos
77
+ 4. **Click Generate**: Wait for processing (2-10 minutes)
78
 
79
+ ### 3. Download Results
80
+ - Videos appear in the interface
81
+ - Download links provided for MP4 files
82
+ - Individual scene videos also available
83
 
84
+ ## Troubleshooting
85
 
86
+ ### Common Issues
 
 
 
87
 
88
+ **1. "Demo Mode" Message**
89
+ ```
90
+ Problem: App shows demo simulation instead of real generation
91
+ Solution: Set DEMO_MODE=false in environment variables
 
92
  ```
93
 
94
+ **2. "No API Keys Found"**
 
 
 
 
 
 
 
 
 
 
95
  ```
96
+ Problem: Missing or incorrect API key configuration
97
+ Solution: Set GEMINI_API_KEY with valid key(s)
98
  ```
99
 
100
+ **3. "Import Error"**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  ```
102
+ Problem: Missing dependencies
103
+ Solution: Ensure requirements.txt includes all packages
104
  ```
105
 
106
+ **4. "Generation Failed"**
107
+ ```
108
+ Problem: API quota exceeded or invalid topic
109
+ Solution: Check API limits, try different topic
110
+ ```
111
 
112
+ ### Verification Steps
 
 
 
113
 
114
+ **1. Test Local Setup:**
115
+ ```bash
116
+ python test_video_generation.py
117
+ ```
118
 
119
+ **2. Check API Keys:**
120
+ ```bash
121
+ echo $GEMINI_API_KEY | tr ',' '\n' | wc -l
122
+ # Should show number of keys
123
+ ```
124
 
125
+ **3. Verify Dependencies:**
126
+ ```bash
127
+ pip install -r requirements.txt
128
+ python -c "from generate_video import VideoGenerator; print('✅ Imports work')"
129
+ ```
130
 
131
+ ## Performance Optimization
132
 
133
+ ### API Key Management
134
+ - **4+ Keys**: Optimal for high usage
135
+ - **Rate Limiting**: 60 requests/minute per key
136
+ - **Monitoring**: Check usage in Google AI Studio
 
 
137
 
138
+ ### Hardware Requirements
139
+ - **CPU Basic**: Sufficient for most educational videos
140
+ - **CPU Upgrade**: Consider for complex visualizations
141
+ - **Persistent Storage**: Enable for caching (optional)
142
 
143
+ ### Content Guidelines
144
+ - **Educational Topics**: Math, science, engineering concepts
145
+ - **Clear Descriptions**: Specific learning objectives
146
+ - **Reasonable Scope**: 2-6 scenes per video
147
 
148
+ ## Advanced Configuration
 
 
149
 
150
+ ### Custom Model Settings
151
+ Edit `app.py` to modify:
152
+ ```python
153
+ planner_model = LiteLLMWrapper(
154
+ model_name="gemini/gemini-2.0-flash-exp", # Model choice
155
+ temperature=0.7, # Creativity level
156
+ print_cost=True, # Cost tracking
157
+ verbose=True # Debug output
158
+ )
159
+ ```
160
 
161
+ ### Output Customization
162
+ Modify `GRADIO_OUTPUT_DIR` in `app.py`:
163
  ```python
164
+ GRADIO_OUTPUT_DIR = "custom_outputs" # Change output folder
 
 
 
165
  ```
166
 
167
+ ### Feature Toggles
168
+ ```python
169
+ # In VideoGenerator initialization
170
+ use_rag=False, # Retrieval augmented generation
171
+ use_context_learning=True, # Few-shot learning
172
+ use_visual_fix_code=True, # Visual debugging
173
+ verbose=True # Detailed logging
174
+ ```
175
 
176
+ ## Security Considerations
 
 
 
177
 
178
+ ### API Key Protection
179
+ - Never commit keys to version control
180
+ - Use HF Spaces environment variables
181
+ - Monitor usage regularly
182
 
183
+ ### Content Moderation
184
+ - Educational content only
185
+ - Avoid sensitive topics
186
+ - Review generated content
187
 
188
+ ## Support
 
 
 
189
 
190
  ### Getting Help
191
+ 1. **Check Logs**: HF Spaces build logs
192
+ 2. **Test Locally**: Use `test_video_generation.py`
193
+ 3. **Issues**: Report problems with error messages
194
+ 4. **Community**: HF Spaces forums
195
+
196
+ ### Useful Resources
197
+ - [Hugging Face Spaces Documentation](https://huggingface.co/docs/hub/spaces)
198
+ - [Gradio Documentation](https://gradio.app/docs/)
199
+ - [Gemini API Documentation](https://ai.google.dev/docs)
200
+ - [Manim Documentation](https://docs.manim.community/)
201
+
202
+ ## Example Successful Deployment
203
 
204
+ **Space URL**: `https://huggingface.co/spaces/ManojINaik/menamiai`
205
+ **Features**: Full video generation with comma-separated API keys
206
+ **Status**: Operational with educational content focus
 
207
 
208
  ---
209
 
210
+ *This deployment guide ensures your Theorem Explanation Agent works with actual video generation capabilities on Hugging Face Spaces.*
app.py CHANGED
@@ -1,11 +1,386 @@
1
  #!/usr/bin/env python3
2
  """
3
- Theorem Explanation Agent - Main entry point for Hugging Face Spaces
 
4
  """
5
 
6
- # Import from our Hugging Face Spaces app
7
- from huggingface_spaces_app import create_interface
 
 
 
 
 
 
8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  if __name__ == "__main__":
10
- demo = create_interface()
11
- demo.launch()
 
 
 
 
 
1
  #!/usr/bin/env python3
2
  """
3
+ Theorem Explanation Agent - Hugging Face Spaces App
4
+ Generates educational videos using Gemini 2.0 Flash and Manim
5
  """
6
 
7
+ import os
8
+ import sys
9
+ import asyncio
10
+ import time
11
+ import random
12
+ from typing import Dict, Any, Tuple, Optional
13
+ from pathlib import Path
14
+ import gradio as gr
15
 
16
+ # Environment setup
17
+ DEMO_MODE = os.getenv("DEMO_MODE", "false").lower() == "true"
18
+ video_generator = None
19
+ CAN_IMPORT_DEPENDENCIES = True
20
+ GRADIO_OUTPUT_DIR = "gradio_outputs"
21
+
22
+ def setup_environment():
23
+ """Setup environment for HF Spaces."""
24
+ print("🚀 Setting up Theorem Explanation Agent...")
25
+
26
+ # Create output directory
27
+ os.makedirs(GRADIO_OUTPUT_DIR, exist_ok=True)
28
+
29
+ gemini_keys = os.getenv("GEMINI_API_KEY", "")
30
+ if gemini_keys:
31
+ key_count = len([k.strip() for k in gemini_keys.split(',') if k.strip()])
32
+ print(f"✅ Found {key_count} Gemini API key(s)")
33
+ return True
34
+ else:
35
+ print("⚠️ No Gemini API keys found - running in demo mode")
36
+ return False
37
+
38
+ def initialize_video_generator():
39
+ """Initialize video generator with proper dependencies."""
40
+ global video_generator, CAN_IMPORT_DEPENDENCIES
41
+
42
+ try:
43
+ if DEMO_MODE:
44
+ return "⚠️ Demo mode enabled - No video generation"
45
+
46
+ gemini_keys = os.getenv("GEMINI_API_KEY", "")
47
+ if not gemini_keys:
48
+ return "⚠️ No API keys found - Set GEMINI_API_KEY environment variable"
49
+
50
+ # Import dependencies
51
+ try:
52
+ from generate_video import VideoGenerator
53
+ from mllm_tools.litellm import LiteLLMWrapper
54
+ print("✅ Successfully imported video generation dependencies")
55
+ except ImportError as e:
56
+ CAN_IMPORT_DEPENDENCIES = False
57
+ print(f"❌ Import error: {e}")
58
+ return f"⚠️ Missing dependencies: {str(e)}"
59
+
60
+ # Initialize models with comma-separated API key support
61
+ planner_model = LiteLLMWrapper(
62
+ model_name="gemini/gemini-2.0-flash-exp",
63
+ temperature=0.7,
64
+ print_cost=True,
65
+ verbose=False,
66
+ use_langfuse=False
67
+ )
68
+
69
+ # Initialize video generator
70
+ video_generator = VideoGenerator(
71
+ planner_model=planner_model,
72
+ helper_model=planner_model,
73
+ scene_model=planner_model,
74
+ output_dir=GRADIO_OUTPUT_DIR,
75
+ use_rag=False,
76
+ use_context_learning=False,
77
+ use_visual_fix_code=False,
78
+ verbose=True
79
+ )
80
+
81
+ return "✅ Video generator initialized successfully"
82
+
83
+ except Exception as e:
84
+ CAN_IMPORT_DEPENDENCIES = False
85
+ print(f"❌ Error initializing video generator: {e}")
86
+ return f"❌ Initialization failed: {str(e)}"
87
+
88
+ def simulate_video_generation(topic: str, context: str, max_scenes: int, progress_callback=None):
89
+ """Simulate video generation for demo mode."""
90
+ stages = [
91
+ ("🔍 Analyzing topic", 15),
92
+ ("📝 Planning scenes", 30),
93
+ ("🎬 Generating content", 50),
94
+ ("✨ Creating animations", 75),
95
+ ("🎥 Rendering video", 90),
96
+ ("✅ Finalizing", 100)
97
+ ]
98
+
99
+ results = []
100
+ for stage, progress in stages:
101
+ if progress_callback:
102
+ progress_callback(progress, stage)
103
+ time.sleep(random.uniform(0.5, 1.0))
104
+ results.append(f"• {stage}")
105
+
106
+ return {
107
+ "success": True,
108
+ "message": f"Demo simulation completed for: {topic}",
109
+ "scenes_created": max_scenes,
110
+ "processing_steps": results,
111
+ "demo_note": "This is a simulation - set GEMINI_API_KEY and DEMO_MODE=false for real generation"
112
+ }
113
+
114
+ async def generate_video_async(topic: str, context: str, max_scenes: int, progress_callback=None):
115
+ """Generate video asynchronously using the actual VideoGenerator."""
116
+ global video_generator
117
+
118
+ if not topic.strip():
119
+ return {"success": False, "error": "Please enter a topic"}
120
+
121
+ try:
122
+ if DEMO_MODE or not CAN_IMPORT_DEPENDENCIES or video_generator is None:
123
+ return simulate_video_generation(topic, context, max_scenes, progress_callback)
124
+
125
+ if progress_callback:
126
+ progress_callback(10, "🚀 Starting video generation...")
127
+
128
+ # Use the actual video generation pipeline
129
+ result = await video_generator.generate_video_pipeline(
130
+ topic=topic,
131
+ description=context or f"Educational video about {topic}",
132
+ max_retries=3,
133
+ only_plan=False,
134
+ specific_scenes=list(range(1, max_scenes + 1)) if max_scenes > 0 else None
135
+ )
136
+
137
+ if progress_callback:
138
+ progress_callback(100, "✅ Video generation completed!")
139
+
140
+ # Check for generated video files
141
+ file_prefix = topic.lower().replace(' ', '_')
142
+ file_prefix = ''.join(c for c in file_prefix if c.isalnum() or c == '_')
143
+
144
+ output_folder = os.path.join(GRADIO_OUTPUT_DIR, file_prefix)
145
+ video_files = []
146
+
147
+ if os.path.exists(output_folder):
148
+ # Look for combined video
149
+ combined_video = os.path.join(output_folder, f"{file_prefix}_combined.mp4")
150
+ if os.path.exists(combined_video):
151
+ video_files.append(combined_video)
152
+
153
+ # Look for individual scene videos
154
+ for i in range(1, max_scenes + 1):
155
+ scene_video = os.path.join(output_folder, f"scene{i}", f"{file_prefix}_scene{i}.mp4")
156
+ if os.path.exists(scene_video):
157
+ video_files.append(scene_video)
158
+
159
+ return {
160
+ "success": True,
161
+ "message": f"Video generated successfully for: {topic}",
162
+ "video_files": video_files,
163
+ "output_folder": output_folder,
164
+ "result": result
165
+ }
166
+
167
+ except Exception as e:
168
+ print(f"❌ Error in video generation: {e}")
169
+ return {"success": False, "error": str(e)}
170
+
171
+ def generate_video_gradio(topic: str, context: str, max_scenes: int, progress=gr.Progress()) -> Tuple[str, str, Optional[str]]:
172
+ """Main Gradio function that handles video generation and returns results."""
173
+ def progress_callback(percent, message):
174
+ progress(percent / 100, desc=message)
175
+
176
+ # Create new event loop for this generation
177
+ loop = asyncio.new_event_loop()
178
+ asyncio.set_event_loop(loop)
179
+
180
+ try:
181
+ result = loop.run_until_complete(
182
+ generate_video_async(topic, context, max_scenes, progress_callback)
183
+ )
184
+ finally:
185
+ loop.close()
186
+
187
+ if result["success"]:
188
+ output = f"""# 🎓 Video Generation Complete!
189
+
190
+ **Topic:** {topic}
191
+ **Context:** {context if context else "None"}
192
+ **Scenes:** {max_scenes}
193
+
194
+ ## ✅ Result
195
+ {result["message"]}
196
+ """
197
+
198
+ # Add processing steps if available
199
+ if "processing_steps" in result:
200
+ output += "\n## 🔄 Processing Steps\n"
201
+ for step in result["processing_steps"]:
202
+ output += f"{step}\n"
203
+
204
+ # Add demo note if in demo mode
205
+ if "demo_note" in result:
206
+ output += f"\n⚠️ **{result['demo_note']}**"
207
+
208
+ # Add video file information
209
+ video_path = None
210
+ if "video_files" in result and result["video_files"]:
211
+ output += f"\n## 🎥 Generated Videos\n"
212
+ for video_file in result["video_files"]:
213
+ output += f"• {os.path.basename(video_file)}\n"
214
+ video_path = result["video_files"][0] # Return first video for display
215
+ elif "output_folder" in result:
216
+ output += f"\n📁 **Output folder:** {result['output_folder']}\n"
217
+
218
+ status = "🎮 Demo completed" if DEMO_MODE else "✅ Generation completed"
219
+ return output, status, video_path
220
+
221
+ else:
222
+ error_output = f"""# ❌ Video Generation Failed
223
+
224
+ **Error:** {result.get("error", "Unknown error")}
225
+
226
+ ## 💡 Troubleshooting Tips
227
+ 1. **Check API Keys:** Ensure GEMINI_API_KEY is set with valid keys
228
+ 2. **Topic Clarity:** Use specific, educational topics
229
+ 3. **Dependencies:** Make sure all required packages are installed
230
+ 4. **Demo Mode:** Set DEMO_MODE=false for real generation
231
+
232
+ ## 🔧 Environment Setup
233
+ ```bash
234
+ export GEMINI_API_KEY="your-key-1,your-key-2,your-key-3"
235
+ export DEMO_MODE=false
236
+ ```
237
+ """
238
+ return error_output, "❌ Generation failed", None
239
+
240
+ def get_examples():
241
+ """Educational example topics."""
242
+ return [
243
+ ["Pythagorean Theorem", "Mathematical proof with geometric visualization"],
244
+ ["Newton's Second Law", "F=ma with real-world examples and demonstrations"],
245
+ ["Derivatives in Calculus", "Rate of change with graphical interpretation"],
246
+ ["Photosynthesis Process", "Cellular process with chemical equations"],
247
+ ["Wave-Particle Duality", "Quantum physics concept with experiments"],
248
+ ["Quadratic Formula", "Step-by-step derivation and applications"],
249
+ ["DNA Replication", "Biological process with molecular details"],
250
+ ["Ohm's Law", "Electrical relationship with circuit examples"]
251
+ ]
252
+
253
+ # Initialize the system
254
+ has_api_keys = setup_environment()
255
+ init_status = initialize_video_generator()
256
+
257
+ # Create Gradio interface
258
+ with gr.Blocks(
259
+ title="🎓 Theorem Explanation Agent",
260
+ theme=gr.themes.Soft(),
261
+ css="footer {visibility: hidden}"
262
+ ) as demo:
263
+
264
+ gr.HTML("""
265
+ <div style="text-align: center; padding: 25px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px; color: white; margin-bottom: 25px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);">
266
+ <h1 style="margin: 0; font-size: 2.5em;">🎓 Theorem Explanation Agent</h1>
267
+ <p style="margin: 10px 0 0 0; font-size: 1.2em; opacity: 0.9;">Generate Educational Videos with AI</p>
268
+ <p style="margin: 5px 0 0 0; font-size: 0.9em; opacity: 0.8;">Powered by Gemini 2.0 Flash & Manim</p>
269
+ </div>
270
+ """)
271
+
272
+ # Status and setup information
273
+ with gr.Row():
274
+ with gr.Column():
275
+ gr.HTML(f"""
276
+ <div style="background: {'#d4edda' if has_api_keys else '#fff3cd'}; padding: 15px; border-radius: 10px; margin-bottom: 15px; border-left: 4px solid {'#28a745' if has_api_keys else '#ffc107'};">
277
+ <h4 style="margin: 0 0 8px 0;">🔐 API Setup Status</h4>
278
+ <p style="margin: 0;"><strong>Status:</strong> {"✅ API keys configured" if has_api_keys else "⚠️ No API keys found"}</p>
279
+ <p style="margin: 5px 0 0 0; font-size: 0.9em;">{"Ready for video generation" if has_api_keys else "Running in demo mode"}</p>
280
+ </div>
281
+ """)
282
+
283
+ with gr.Column():
284
+ system_status = gr.Textbox(
285
+ label="🔧 System Status",
286
+ value=init_status,
287
+ interactive=False,
288
+ lines=2
289
+ )
290
+
291
+ # API Configuration Help
292
+ if not has_api_keys or DEMO_MODE:
293
+ gr.HTML("""
294
+ <div style="background: #f8f9fa; padding: 20px; border-radius: 10px; margin: 15px 0; border: 1px solid #dee2e6;">
295
+ <h4 style="color: #495057; margin-top: 0;">🚀 Enable Full Functionality</h4>
296
+ <p style="margin-bottom: 15px;">To generate actual videos instead of simulations:</p>
297
+ <div style="background: #e9ecef; padding: 15px; border-radius: 5px; font-family: monospace;">
298
+ <strong>Single API Key:</strong><br>
299
+ <code>GEMINI_API_KEY=your-gemini-api-key</code><br><br>
300
+ <strong>Multiple Keys (Recommended):</strong><br>
301
+ <code>GEMINI_API_KEY=key1,key2,key3,key4</code><br><br>
302
+ <strong>Disable Demo Mode:</strong><br>
303
+ <code>DEMO_MODE=false</code>
304
+ </div>
305
+ <p style="margin-top: 15px; font-size: 0.9em; color: #6c757d;">
306
+ Multiple API keys enable automatic failover and load distribution across different billing accounts.
307
+ </p>
308
+ </div>
309
+ """)
310
+
311
+ # Main interface
312
+ with gr.Row():
313
+ with gr.Column(scale=2):
314
+ topic_input = gr.Textbox(
315
+ label="📚 Educational Topic",
316
+ placeholder="e.g., Pythagorean Theorem, Newton's Laws, Derivatives...",
317
+ lines=1
318
+ )
319
+
320
+ context_input = gr.Textbox(
321
+ label="📝 Additional Context (Optional)",
322
+ placeholder="Specify focus areas, target audience, or particular aspects to emphasize...",
323
+ lines=3
324
+ )
325
+
326
+ max_scenes_slider = gr.Slider(
327
+ label="🎬 Maximum Scenes",
328
+ minimum=1,
329
+ maximum=6,
330
+ value=3,
331
+ step=1,
332
+ info="More scenes = longer videos but more API usage"
333
+ )
334
+
335
+ generate_btn = gr.Button("🚀 Generate Educational Video", variant="primary", size="lg")
336
+
337
+ with gr.Column(scale=1):
338
+ gr.HTML("""
339
+ <div style="background: #f8f9fa; padding: 20px; border-radius: 10px; height: fit-content;">
340
+ <h4 style="color: #495057; margin-top: 0;">💡 Tips for Best Results</h4>
341
+ <ul style="color: #6c757d; font-size: 0.9em; line-height: 1.6;">
342
+ <li><strong>Be Specific:</strong> "Pythagorean Theorem proof" vs "Math"</li>
343
+ <li><strong>Educational Focus:</strong> Topics work best for teaching</li>
344
+ <li><strong>Context Helps:</strong> Specify audience or emphasis</li>
345
+ <li><strong>Start Small:</strong> Try 2-3 scenes first</li>
346
+ </ul>
347
+ </div>
348
+ """)
349
+
350
+ # Examples
351
+ examples = gr.Examples(
352
+ examples=get_examples(),
353
+ inputs=[topic_input, context_input],
354
+ label="📖 Example Topics"
355
+ )
356
+
357
+ # Output section
358
+ with gr.Row():
359
+ with gr.Column(scale=2):
360
+ output_display = gr.Markdown(
361
+ value="👋 **Ready to generate!** Enter an educational topic above and click 'Generate Educational Video' to begin.",
362
+ label="📋 Generation Results"
363
+ )
364
+
365
+ with gr.Column(scale=1):
366
+ video_output = gr.Video(
367
+ label="🎥 Generated Video",
368
+ visible=True
369
+ )
370
+
371
+ # Wire up the interface
372
+ generate_btn.click(
373
+ fn=generate_video_gradio,
374
+ inputs=[topic_input, context_input, max_scenes_slider],
375
+ outputs=[output_display, system_status, video_output],
376
+ show_progress=True
377
+ )
378
+
379
+ # Launch configuration
380
  if __name__ == "__main__":
381
+ demo.launch(
382
+ server_name="0.0.0.0",
383
+ server_port=7860,
384
+ share=False,
385
+ show_error=True
386
+ )
requirements_hf.txt CHANGED
@@ -1,19 +1,43 @@
1
- # Core dependencies for Hugging Face Spaces
2
  gradio==4.44.0
3
  python-dotenv>=0.19.0
4
  requests>=2.25.0
5
  numpy>=1.21.0
 
6
 
7
  # AI/ML dependencies
 
8
  litellm>=1.0.0
 
 
 
9
  google-generativeai>=0.8.0
10
 
11
- # Image processing (required for video generation)
12
  pillow>=8.3.0
 
13
 
14
- # Audio processing (optional, for TTS)
 
 
 
15
  elevenlabs>=1.0.0
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  # Utility libraries
18
  tqdm>=4.62.0
19
 
 
1
+ # Essential dependencies for Gradio and video generation
2
  gradio==4.44.0
3
  python-dotenv>=0.19.0
4
  requests>=2.25.0
5
  numpy>=1.21.0
6
+ pandas>=1.3.0
7
 
8
  # AI/ML dependencies
9
+ openai>=1.0.0
10
  litellm>=1.0.0
11
+ tqdm>=4.62.0
12
+
13
+ # Google Gemini support
14
  google-generativeai>=0.8.0
15
 
16
+ # Video processing dependencies
17
  pillow>=8.3.0
18
+ moviepy>=1.0.3
19
 
20
+ # Manim for video generation
21
+ manim>=0.18.0
22
+
23
+ # Text-to-speech
24
  elevenlabs>=1.0.0
25
 
26
+ # Audio processing
27
+ pydub>=0.25.0
28
+ soundfile>=0.12.0
29
+
30
+ # Additional utilities
31
+ langchain>=0.1.0
32
+ chromadb>=0.4.0
33
+ tiktoken>=0.4.0
34
+
35
+ # Utility libraries
36
+ tqdm>=4.62.0
37
+
38
+ # Audio processing (optional, for TTS)
39
+ # elevenlabs>=1.0.0
40
+
41
  # Utility libraries
42
  tqdm>=4.62.0
43
 
test_video_generation.py ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Test script for video generation functionality
4
+ """
5
+
6
+ import os
7
+ import asyncio
8
+ from dotenv import load_dotenv
9
+
10
+ # Load environment variables
11
+ load_dotenv()
12
+
13
+ async def test_video_generation():
14
+ """Test the video generation pipeline."""
15
+
16
+ # Check API keys
17
+ gemini_keys = os.getenv("GEMINI_API_KEY", "")
18
+ if not gemini_keys:
19
+ print("❌ No GEMINI_API_KEY found. Please set environment variable.")
20
+ print("Example: export GEMINI_API_KEY='key1,key2,key3'")
21
+ return False
22
+
23
+ key_count = len([k.strip() for k in gemini_keys.split(',') if k.strip()])
24
+ print(f"✅ Found {key_count} Gemini API key(s)")
25
+
26
+ try:
27
+ # Import dependencies
28
+ from generate_video import VideoGenerator
29
+ from mllm_tools.litellm import LiteLLMWrapper
30
+ print("✅ Successfully imported video generation dependencies")
31
+
32
+ # Initialize models
33
+ planner_model = LiteLLMWrapper(
34
+ model_name="gemini/gemini-2.0-flash-exp",
35
+ temperature=0.7,
36
+ print_cost=True,
37
+ verbose=True,
38
+ use_langfuse=False
39
+ )
40
+
41
+ # Initialize video generator
42
+ video_generator = VideoGenerator(
43
+ planner_model=planner_model,
44
+ helper_model=planner_model,
45
+ scene_model=planner_model,
46
+ output_dir="test_output",
47
+ use_rag=False,
48
+ use_context_learning=False,
49
+ use_visual_fix_code=False,
50
+ verbose=True
51
+ )
52
+
53
+ print("✅ Video generator initialized successfully")
54
+
55
+ # Test video generation
56
+ test_topic = "Pythagorean Theorem"
57
+ test_description = "Basic mathematical proof with geometric visualization"
58
+
59
+ print(f"\n🚀 Testing video generation for: {test_topic}")
60
+ print(f"📝 Description: {test_description}")
61
+
62
+ result = await video_generator.generate_video_pipeline(
63
+ topic=test_topic,
64
+ description=test_description,
65
+ max_retries=2,
66
+ only_plan=False,
67
+ specific_scenes=[1, 2] # Just test 2 scenes
68
+ )
69
+
70
+ print("✅ Video generation pipeline completed successfully!")
71
+
72
+ # Check output files
73
+ file_prefix = test_topic.lower().replace(' ', '_')
74
+ file_prefix = ''.join(c for c in file_prefix if c.isalnum() or c == '_')
75
+
76
+ output_folder = os.path.join("test_output", file_prefix)
77
+ if os.path.exists(output_folder):
78
+ print(f"📁 Output folder created: {output_folder}")
79
+
80
+ # List files in output folder
81
+ for root, dirs, files in os.walk(output_folder):
82
+ level = root.replace(output_folder, '').count(os.sep)
83
+ indent = ' ' * 2 * level
84
+ print(f"{indent}{os.path.basename(root)}/")
85
+ subindent = ' ' * 2 * (level + 1)
86
+ for file in files:
87
+ print(f"{subindent}{file}")
88
+
89
+ return True
90
+
91
+ except ImportError as e:
92
+ print(f"❌ Import error: {e}")
93
+ print("Please install required dependencies:")
94
+ print("pip install -r requirements.txt")
95
+ return False
96
+
97
+ except Exception as e:
98
+ print(f"❌ Error during video generation: {e}")
99
+ return False
100
+
101
+ if __name__ == "__main__":
102
+ print("🧪 Testing Video Generation System\n")
103
+
104
+ loop = asyncio.new_event_loop()
105
+ asyncio.set_event_loop(loop)
106
+
107
+ try:
108
+ success = loop.run_until_complete(test_video_generation())
109
+ if success:
110
+ print("\n🎉 Test completed successfully!")
111
+ print("The video generation system is working properly.")
112
+ else:
113
+ print("\n❌ Test failed.")
114
+ print("Please check the error messages above and fix any issues.")
115
+ finally:
116
+ loop.close()