Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -101,6 +101,8 @@ def ensure_packages():
|
|
101 |
'seaborn': '0.11.2', # For enhanced visualizations
|
102 |
'scipy': '1.7.3', # For scientific computations
|
103 |
'huggingface_hub': '0.16.0', # For Hugging Face API
|
|
|
|
|
104 |
}
|
105 |
|
106 |
with st.spinner("Checking required packages..."):
|
@@ -239,7 +241,7 @@ def install_custom_packages(package_list):
|
|
239 |
|
240 |
@st.cache_resource(ttl=3600)
|
241 |
def init_ai_models(model_name=None):
|
242 |
-
try:
|
243 |
# Get the GitHub token from secrets
|
244 |
github_token = get_secret("github_token_api")
|
245 |
if not github_token:
|
@@ -248,27 +250,23 @@ def init_ai_models(model_name=None):
|
|
248 |
|
249 |
# Use default model if none specified
|
250 |
if not model_name:
|
251 |
-
model_name = "
|
252 |
-
|
253 |
-
with st.spinner(f"
|
254 |
-
#
|
255 |
-
from
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
)
|
265 |
|
266 |
-
if code_model is None:
|
267 |
-
st.error("Failed to initialize code model")
|
268 |
-
return None
|
269 |
-
|
270 |
return {
|
271 |
-
"
|
272 |
"model_name": model_name,
|
273 |
"last_loaded": datetime.now().isoformat()
|
274 |
}
|
@@ -277,6 +275,61 @@ def init_ai_models(model_name=None):
|
|
277 |
logger.error(f"AI model initialization error: {str(e)}")
|
278 |
return None
|
279 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
280 |
def check_model_freshness():
|
281 |
"""Check if models need to be reloaded based on TTL"""
|
282 |
if 'ai_models' not in st.session_state or st.session_state.ai_models is None:
|
@@ -1550,7 +1603,9 @@ def main():
|
|
1550 |
"animation_speed": "Normal"
|
1551 |
}
|
1552 |
st.session_state.password_entered = False # Track password authentication
|
1553 |
-
st.session_state.custom_model = "
|
|
|
|
|
1554 |
|
1555 |
# Page configuration with improved layout
|
1556 |
st.set_page_config(
|
@@ -1773,7 +1828,7 @@ def main():
|
|
1773 |
language="python",
|
1774 |
theme="monokai",
|
1775 |
min_lines=20,
|
1776 |
-
key="
|
1777 |
)
|
1778 |
else:
|
1779 |
current_code = st.session_state.code if hasattr(st.session_state, 'code') and st.session_state.code else ""
|
@@ -1781,7 +1836,7 @@ def main():
|
|
1781 |
"Manim Python Code",
|
1782 |
value=current_code,
|
1783 |
height=400,
|
1784 |
-
key="
|
1785 |
)
|
1786 |
|
1787 |
# Update code in session state if it changed
|
@@ -1923,14 +1978,14 @@ class MyScene(Scene):
|
|
1923 |
# Model selection - only visible after authentication
|
1924 |
st.markdown("#### Model Selection")
|
1925 |
|
1926 |
-
# Predefined
|
1927 |
popular_models = [
|
1928 |
"Select a predefined model...",
|
1929 |
-
"
|
1930 |
-
"
|
1931 |
-
"
|
1932 |
-
"
|
1933 |
-
"
|
1934 |
]
|
1935 |
|
1936 |
custom_model_option = st.radio(
|
@@ -1948,9 +2003,9 @@ class MyScene(Scene):
|
|
1948 |
st.session_state.custom_model = selected_model
|
1949 |
else:
|
1950 |
custom_model_name = st.text_input(
|
1951 |
-
"Enter custom model name
|
1952 |
value=st.session_state.custom_model,
|
1953 |
-
placeholder="e.g.,
|
1954 |
)
|
1955 |
|
1956 |
if custom_model_name:
|
@@ -2027,8 +2082,8 @@ class MyScene(Scene):
|
|
2027 |
if st.button("Use This Code", key="use_gen_code"):
|
2028 |
st.session_state.code = st.session_state.generated_code
|
2029 |
st.session_state.temp_code = st.session_state.generated_code
|
2030 |
-
#
|
2031 |
-
st.session_state.
|
2032 |
st.rerun()
|
2033 |
|
2034 |
with col_ai2:
|
@@ -2125,7 +2180,7 @@ class MyScene(Scene):
|
|
2125 |
if st.button(formula["name"], key=f"latex_{formula['name']}"):
|
2126 |
# Insert formula into the text area
|
2127 |
st.session_state.latex_formula = formula["latex"]
|
2128 |
-
#
|
2129 |
st.rerun()
|
2130 |
|
2131 |
# LaTeX code snippet
|
@@ -2168,8 +2223,8 @@ self.wait(2)
|
|
2168 |
st.session_state.temp_code = st.session_state.code
|
2169 |
st.success("LaTeX formula inserted into the editor!")
|
2170 |
|
2171 |
-
#
|
2172 |
-
st.session_state.
|
2173 |
st.rerun()
|
2174 |
else:
|
2175 |
st.warning("Could not find 'construct' method in your code. Please add a scene class first.")
|
@@ -2188,8 +2243,8 @@ class LatexScene(Scene):
|
|
2188 |
st.session_state.temp_code = basic_scene
|
2189 |
st.success("Created new scene with your LaTeX formula!")
|
2190 |
|
2191 |
-
#
|
2192 |
-
st.session_state.
|
2193 |
st.rerun()
|
2194 |
|
2195 |
with col_latex2:
|
@@ -2259,7 +2314,6 @@ class LatexScene(Scene):
|
|
2259 |
if "image_paths" not in st.session_state:
|
2260 |
st.session_state.image_paths = []
|
2261 |
|
2262 |
-
# Check if this image was already added
|
2263 |
# Check if this image was already added
|
2264 |
image_already_added = False
|
2265 |
for img in st.session_state.image_paths:
|
@@ -2305,8 +2359,8 @@ class ImageScene(Scene):
|
|
2305 |
st.session_state.temp_code = st.session_state.code
|
2306 |
st.success(f"Added {img_info['name']} to your code!")
|
2307 |
|
2308 |
-
#
|
2309 |
-
st.session_state.
|
2310 |
st.rerun()
|
2311 |
except Exception as e:
|
2312 |
st.error(f"Error loading image {img_info['name']}: {e}")
|
@@ -2708,14 +2762,14 @@ plt.legend()
|
|
2708 |
language="python",
|
2709 |
theme="monokai",
|
2710 |
min_lines=15,
|
2711 |
-
key="
|
2712 |
)
|
2713 |
else:
|
2714 |
python_code = st.text_area(
|
2715 |
"Python Code",
|
2716 |
value=python_code,
|
2717 |
height=400,
|
2718 |
-
key="
|
2719 |
)
|
2720 |
|
2721 |
# Store script in session state (without clearing existing code)
|
@@ -2784,8 +2838,8 @@ self.wait(1)
|
|
2784 |
st.session_state.code += "\n" + plot_code
|
2785 |
st.session_state.temp_code = st.session_state.code
|
2786 |
st.success(f"Plot {i+1} added to your animation code!")
|
2787 |
-
#
|
2788 |
-
st.session_state.
|
2789 |
st.rerun()
|
2790 |
else:
|
2791 |
basic_scene = f"""from manim import *
|
@@ -2797,8 +2851,8 @@ class PlotScene(Scene):
|
|
2797 |
st.session_state.code = basic_scene
|
2798 |
st.session_state.temp_code = basic_scene
|
2799 |
st.success(f"Created new scene with Plot {i+1}!")
|
2800 |
-
#
|
2801 |
-
st.session_state.
|
2802 |
st.rerun()
|
2803 |
|
2804 |
# Provide option to save the script
|
@@ -2875,12 +2929,19 @@ class PlotScene(Scene):
|
|
2875 |
```
|
2876 |
""")
|
2877 |
|
2878 |
-
#
|
2879 |
-
if st.session_state.
|
|
|
|
|
|
|
|
|
2880 |
for i, tab in enumerate(tabs):
|
2881 |
if i == st.session_state.active_tab:
|
2882 |
tab.active = True
|
2883 |
-
|
|
|
|
|
|
|
2884 |
|
2885 |
if __name__ == "__main__":
|
2886 |
-
main()
|
|
|
101 |
'seaborn': '0.11.2', # For enhanced visualizations
|
102 |
'scipy': '1.7.3', # For scientific computations
|
103 |
'huggingface_hub': '0.16.0', # For Hugging Face API
|
104 |
+
'azure-ai-inference': '1.0.0',
|
105 |
+
'azure-core': '1.29.5',
|
106 |
}
|
107 |
|
108 |
with st.spinner("Checking required packages..."):
|
|
|
241 |
|
242 |
@st.cache_resource(ttl=3600)
|
243 |
def init_ai_models(model_name=None):
|
244 |
+
try:
|
245 |
# Get the GitHub token from secrets
|
246 |
github_token = get_secret("github_token_api")
|
247 |
if not github_token:
|
|
|
250 |
|
251 |
# Use default model if none specified
|
252 |
if not model_name:
|
253 |
+
model_name = "gpt-4o"
|
254 |
+
|
255 |
+
with st.spinner(f"Initializing AI model: {model_name}..."):
|
256 |
+
# Import Azure modules
|
257 |
+
from azure.ai.inference import ChatCompletionsClient
|
258 |
+
from azure.ai.inference.models import SystemMessage, UserMessage
|
259 |
+
from azure.core.credentials import AzureKeyCredential
|
260 |
+
|
261 |
+
# Setup Azure Inference client
|
262 |
+
endpoint = "https://models.inference.ai.azure.com"
|
263 |
+
client = ChatCompletionsClient(
|
264 |
+
endpoint=endpoint,
|
265 |
+
credential=AzureKeyCredential(github_token),
|
266 |
)
|
267 |
|
|
|
|
|
|
|
|
|
268 |
return {
|
269 |
+
"client": client,
|
270 |
"model_name": model_name,
|
271 |
"last_loaded": datetime.now().isoformat()
|
272 |
}
|
|
|
275 |
logger.error(f"AI model initialization error: {str(e)}")
|
276 |
return None
|
277 |
|
278 |
+
def suggest_code_completion(code_snippet, models):
|
279 |
+
if not models or "client" not in models:
|
280 |
+
st.error("AI models not properly initialized")
|
281 |
+
return None
|
282 |
+
|
283 |
+
try:
|
284 |
+
prompt = f"""Write a complete Manim animation scene based on this code or idea:
|
285 |
+
{code_snippet}
|
286 |
+
|
287 |
+
The code should be a complete, working Manim animation that includes:
|
288 |
+
- Proper Scene class definition
|
289 |
+
- Constructor with animations
|
290 |
+
- Proper use of self.play() for animations
|
291 |
+
- Proper wait times between animations
|
292 |
+
|
293 |
+
Here's the complete Manim code:
|
294 |
+
"""
|
295 |
+
with st.spinner("AI is generating your animation code..."):
|
296 |
+
from azure.ai.inference.models import UserMessage
|
297 |
+
|
298 |
+
# Generate the response using Azure Inference API
|
299 |
+
response = models["client"].complete(
|
300 |
+
messages=[
|
301 |
+
UserMessage(prompt),
|
302 |
+
],
|
303 |
+
max_tokens=1024,
|
304 |
+
model=models["model_name"]
|
305 |
+
)
|
306 |
+
|
307 |
+
# Extract the generated code from the response
|
308 |
+
if response and response.choices and len(response.choices) > 0:
|
309 |
+
completed_code = response.choices[0].message.content
|
310 |
+
else:
|
311 |
+
st.error("No valid completion generated")
|
312 |
+
return None
|
313 |
+
|
314 |
+
# Extract code if wrapped in markdown code blocks
|
315 |
+
if "```python" in completed_code:
|
316 |
+
completed_code = completed_code.split("```python")[1].split("```")[0]
|
317 |
+
elif "```" in completed_code:
|
318 |
+
completed_code = completed_code.split("```")[1].split("```")[0]
|
319 |
+
|
320 |
+
if "Scene" not in completed_code:
|
321 |
+
completed_code = f"""from manim import *
|
322 |
+
|
323 |
+
class MyScene(Scene):
|
324 |
+
def construct(self):
|
325 |
+
{completed_code}"""
|
326 |
+
|
327 |
+
return completed_code
|
328 |
+
except Exception as e:
|
329 |
+
st.error(f"Error suggesting code: {str(e)}")
|
330 |
+
logger.error(f"Code suggestion error: {str(e)}")
|
331 |
+
return None
|
332 |
+
|
333 |
def check_model_freshness():
|
334 |
"""Check if models need to be reloaded based on TTL"""
|
335 |
if 'ai_models' not in st.session_state or st.session_state.ai_models is None:
|
|
|
1603 |
"animation_speed": "Normal"
|
1604 |
}
|
1605 |
st.session_state.password_entered = False # Track password authentication
|
1606 |
+
st.session_state.custom_model = "gpt-4o" # Default model
|
1607 |
+
st.session_state.first_load_complete = False # Prevent refreshes on first load
|
1608 |
+
st.session_state.pending_tab_switch = None # Track pending tab switches
|
1609 |
|
1610 |
# Page configuration with improved layout
|
1611 |
st.set_page_config(
|
|
|
1828 |
language="python",
|
1829 |
theme="monokai",
|
1830 |
min_lines=20,
|
1831 |
+
key=f"ace_editor_{st.session_state.editor_key}"
|
1832 |
)
|
1833 |
else:
|
1834 |
current_code = st.session_state.code if hasattr(st.session_state, 'code') and st.session_state.code else ""
|
|
|
1836 |
"Manim Python Code",
|
1837 |
value=current_code,
|
1838 |
height=400,
|
1839 |
+
key=f"code_textarea_{st.session_state.editor_key}"
|
1840 |
)
|
1841 |
|
1842 |
# Update code in session state if it changed
|
|
|
1978 |
# Model selection - only visible after authentication
|
1979 |
st.markdown("#### Model Selection")
|
1980 |
|
1981 |
+
# Predefined Azure models
|
1982 |
popular_models = [
|
1983 |
"Select a predefined model...",
|
1984 |
+
"gpt-4o",
|
1985 |
+
"gpt-4",
|
1986 |
+
"gpt-35-turbo",
|
1987 |
+
"claude-3-opus-20240229",
|
1988 |
+
"claude-3-sonnet-20240229",
|
1989 |
]
|
1990 |
|
1991 |
custom_model_option = st.radio(
|
|
|
2003 |
st.session_state.custom_model = selected_model
|
2004 |
else:
|
2005 |
custom_model_name = st.text_input(
|
2006 |
+
"Enter custom model name:",
|
2007 |
value=st.session_state.custom_model,
|
2008 |
+
placeholder="e.g., gpt-4o"
|
2009 |
)
|
2010 |
|
2011 |
if custom_model_name:
|
|
|
2082 |
if st.button("Use This Code", key="use_gen_code"):
|
2083 |
st.session_state.code = st.session_state.generated_code
|
2084 |
st.session_state.temp_code = st.session_state.generated_code
|
2085 |
+
# Set pending tab switch to editor tab
|
2086 |
+
st.session_state.pending_tab_switch = 0
|
2087 |
st.rerun()
|
2088 |
|
2089 |
with col_ai2:
|
|
|
2180 |
if st.button(formula["name"], key=f"latex_{formula['name']}"):
|
2181 |
# Insert formula into the text area
|
2182 |
st.session_state.latex_formula = formula["latex"]
|
2183 |
+
# Refresh without full page rerun
|
2184 |
st.rerun()
|
2185 |
|
2186 |
# LaTeX code snippet
|
|
|
2223 |
st.session_state.temp_code = st.session_state.code
|
2224 |
st.success("LaTeX formula inserted into the editor!")
|
2225 |
|
2226 |
+
# Set pending tab switch to editor tab
|
2227 |
+
st.session_state.pending_tab_switch = 0
|
2228 |
st.rerun()
|
2229 |
else:
|
2230 |
st.warning("Could not find 'construct' method in your code. Please add a scene class first.")
|
|
|
2243 |
st.session_state.temp_code = basic_scene
|
2244 |
st.success("Created new scene with your LaTeX formula!")
|
2245 |
|
2246 |
+
# Set pending tab switch to editor tab
|
2247 |
+
st.session_state.pending_tab_switch = 0
|
2248 |
st.rerun()
|
2249 |
|
2250 |
with col_latex2:
|
|
|
2314 |
if "image_paths" not in st.session_state:
|
2315 |
st.session_state.image_paths = []
|
2316 |
|
|
|
2317 |
# Check if this image was already added
|
2318 |
image_already_added = False
|
2319 |
for img in st.session_state.image_paths:
|
|
|
2359 |
st.session_state.temp_code = st.session_state.code
|
2360 |
st.success(f"Added {img_info['name']} to your code!")
|
2361 |
|
2362 |
+
# Set pending tab switch to editor tab
|
2363 |
+
st.session_state.pending_tab_switch = 0
|
2364 |
st.rerun()
|
2365 |
except Exception as e:
|
2366 |
st.error(f"Error loading image {img_info['name']}: {e}")
|
|
|
2762 |
language="python",
|
2763 |
theme="monokai",
|
2764 |
min_lines=15,
|
2765 |
+
key=f"python_editor_{st.session_state.editor_key}"
|
2766 |
)
|
2767 |
else:
|
2768 |
python_code = st.text_area(
|
2769 |
"Python Code",
|
2770 |
value=python_code,
|
2771 |
height=400,
|
2772 |
+
key=f"python_textarea_{st.session_state.editor_key}"
|
2773 |
)
|
2774 |
|
2775 |
# Store script in session state (without clearing existing code)
|
|
|
2838 |
st.session_state.code += "\n" + plot_code
|
2839 |
st.session_state.temp_code = st.session_state.code
|
2840 |
st.success(f"Plot {i+1} added to your animation code!")
|
2841 |
+
# Set pending tab switch to editor tab
|
2842 |
+
st.session_state.pending_tab_switch = 0
|
2843 |
st.rerun()
|
2844 |
else:
|
2845 |
basic_scene = f"""from manim import *
|
|
|
2851 |
st.session_state.code = basic_scene
|
2852 |
st.session_state.temp_code = basic_scene
|
2853 |
st.success(f"Created new scene with Plot {i+1}!")
|
2854 |
+
# Set pending tab switch to editor tab
|
2855 |
+
st.session_state.pending_tab_switch = 0
|
2856 |
st.rerun()
|
2857 |
|
2858 |
# Provide option to save the script
|
|
|
2929 |
```
|
2930 |
""")
|
2931 |
|
2932 |
+
# Handle tab switching with session state to prevent refresh loop
|
2933 |
+
if st.session_state.pending_tab_switch is not None:
|
2934 |
+
st.session_state.active_tab = st.session_state.pending_tab_switch
|
2935 |
+
st.session_state.pending_tab_switch = None
|
2936 |
+
|
2937 |
+
# Set tabs active state
|
2938 |
for i, tab in enumerate(tabs):
|
2939 |
if i == st.session_state.active_tab:
|
2940 |
tab.active = True
|
2941 |
+
|
2942 |
+
# Mark first load as complete to prevent unnecessary refreshes
|
2943 |
+
if not st.session_state.first_load_complete:
|
2944 |
+
st.session_state.first_load_complete = True
|
2945 |
|
2946 |
if __name__ == "__main__":
|
2947 |
+
main()
|