update streamlit issue
Browse files- anycoder_app/prompts.py +82 -31
- anycoder_app/ui.py +97 -72
anycoder_app/prompts.py
CHANGED
|
@@ -98,15 +98,16 @@ STREAMLIT_SYSTEM_PROMPT = """You are an expert Streamlit developer. Create a com
|
|
| 98 |
|
| 99 |
## Multi-File Application Structure
|
| 100 |
|
| 101 |
-
When creating
|
| 102 |
-
|
| 103 |
-
**File Organization:**
|
| 104 |
-
- `
|
| 105 |
-
- `
|
| 106 |
-
- `
|
| 107 |
-
- `
|
| 108 |
-
- `
|
| 109 |
-
- `
|
|
|
|
| 110 |
- Additional modules as needed (e.g., `data_processing.py`, `components.py`)
|
| 111 |
|
| 112 |
**π¨ CRITICAL: DO NOT Generate README.md Files**
|
|
@@ -115,18 +116,70 @@ When creating complex Streamlit applications, organize your code into multiple f
|
|
| 115 |
- Generating a README.md will break the deployment process
|
| 116 |
- Only generate the code files listed above
|
| 117 |
|
| 118 |
-
**Output Format for
|
| 119 |
-
|
| 120 |
|
| 121 |
```
|
|
|
|
|
|
|
|
|
|
| 122 |
=== streamlit_app.py ===
|
| 123 |
[main application code]
|
| 124 |
|
| 125 |
-
=== utils.py ===
|
| 126 |
-
[utility functions]
|
| 127 |
-
|
| 128 |
=== requirements.txt ===
|
| 129 |
[dependencies]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 130 |
```
|
| 131 |
|
| 132 |
**π¨ CRITICAL: requirements.txt Formatting Rules**
|
|
@@ -146,21 +199,18 @@ When generating multi-file applications, use this exact format:
|
|
| 146 |
- pandas
|
| 147 |
```
|
| 148 |
|
| 149 |
-
**Single vs Multi-File Decision:**
|
| 150 |
-
- Use single file for simple applications (< 100 lines) - but still generate requirements.txt if dependencies exist
|
| 151 |
-
- Use multi-file structure for complex applications with:
|
| 152 |
-
- Multiple pages or sections
|
| 153 |
-
- Extensive data processing
|
| 154 |
-
- Complex UI components
|
| 155 |
-
- Multiple models or APIs
|
| 156 |
-
- When user specifically requests modular structure
|
| 157 |
-
|
| 158 |
**Multi-Page Apps:**
|
| 159 |
For multi-page Streamlit apps, use the pages/ directory structure:
|
| 160 |
```
|
|
|
|
|
|
|
|
|
|
| 161 |
=== streamlit_app.py ===
|
| 162 |
[main page]
|
| 163 |
|
|
|
|
|
|
|
|
|
|
| 164 |
=== pages/1_π_Analytics.py ===
|
| 165 |
[analytics page]
|
| 166 |
|
|
@@ -169,14 +219,15 @@ For multi-page Streamlit apps, use the pages/ directory structure:
|
|
| 169 |
```
|
| 170 |
|
| 171 |
Requirements:
|
| 172 |
-
1.
|
| 173 |
-
2.
|
| 174 |
-
3.
|
| 175 |
-
4.
|
| 176 |
-
5.
|
| 177 |
-
6.
|
| 178 |
-
7.
|
| 179 |
-
8.
|
|
|
|
| 180 |
|
| 181 |
IMPORTANT: Always include "Built with anycoder" as clickable text in the header/top section of your application that links to https://huggingface.co/spaces/akhaliq/anycoder
|
| 182 |
"""
|
|
|
|
| 98 |
|
| 99 |
## Multi-File Application Structure
|
| 100 |
|
| 101 |
+
When creating Streamlit applications, you MUST organize your code into multiple files for proper deployment:
|
| 102 |
+
|
| 103 |
+
**File Organization (CRITICAL - Always Include These):**
|
| 104 |
+
- `Dockerfile` - Docker configuration for deployment (REQUIRED)
|
| 105 |
+
- `streamlit_app.py` - Main application entry point (REQUIRED)
|
| 106 |
+
- `requirements.txt` - Python dependencies (REQUIRED)
|
| 107 |
+
- `utils.py` - Utility functions and helpers (optional)
|
| 108 |
+
- `models.py` - Model loading and inference functions (optional)
|
| 109 |
+
- `config.py` - Configuration and constants (optional)
|
| 110 |
+
- `pages/` - Additional pages for multi-page apps (optional)
|
| 111 |
- Additional modules as needed (e.g., `data_processing.py`, `components.py`)
|
| 112 |
|
| 113 |
**π¨ CRITICAL: DO NOT Generate README.md Files**
|
|
|
|
| 116 |
- Generating a README.md will break the deployment process
|
| 117 |
- Only generate the code files listed above
|
| 118 |
|
| 119 |
+
**Output Format for Streamlit Apps:**
|
| 120 |
+
You MUST use this exact format and ALWAYS include Dockerfile, streamlit_app.py, and requirements.txt:
|
| 121 |
|
| 122 |
```
|
| 123 |
+
=== Dockerfile ===
|
| 124 |
+
[Dockerfile content]
|
| 125 |
+
|
| 126 |
=== streamlit_app.py ===
|
| 127 |
[main application code]
|
| 128 |
|
|
|
|
|
|
|
|
|
|
| 129 |
=== requirements.txt ===
|
| 130 |
[dependencies]
|
| 131 |
+
|
| 132 |
+
=== utils.py ===
|
| 133 |
+
[utility functions - optional]
|
| 134 |
+
```
|
| 135 |
+
|
| 136 |
+
**π¨ CRITICAL: Dockerfile Requirements (MANDATORY for HuggingFace Spaces)**
|
| 137 |
+
Your Dockerfile MUST follow these exact specifications:
|
| 138 |
+
- Use Python 3.11+ base image (e.g., FROM python:3.11-slim)
|
| 139 |
+
- Set up a user with ID 1000 for proper permissions:
|
| 140 |
+
```
|
| 141 |
+
RUN useradd -m -u 1000 user
|
| 142 |
+
USER user
|
| 143 |
+
ENV HOME=/home/user \\
|
| 144 |
+
PATH=/home/user/.local/bin:$PATH
|
| 145 |
+
WORKDIR $HOME/app
|
| 146 |
+
```
|
| 147 |
+
- ALWAYS use --chown=user with COPY and ADD commands:
|
| 148 |
+
```
|
| 149 |
+
COPY --chown=user requirements.txt .
|
| 150 |
+
COPY --chown=user . .
|
| 151 |
+
```
|
| 152 |
+
- Install dependencies: RUN pip install --no-cache-dir -r requirements.txt
|
| 153 |
+
- Expose port 7860 (HuggingFace Spaces default): EXPOSE 7860
|
| 154 |
+
- Start with: CMD ["streamlit", "run", "streamlit_app.py", "--server.port=7860", "--server.address=0.0.0.0"]
|
| 155 |
+
|
| 156 |
+
**Example Dockerfile structure (USE THIS AS TEMPLATE):**
|
| 157 |
+
```dockerfile
|
| 158 |
+
FROM python:3.11-slim
|
| 159 |
+
|
| 160 |
+
# Set up user with ID 1000
|
| 161 |
+
RUN useradd -m -u 1000 user
|
| 162 |
+
USER user
|
| 163 |
+
ENV HOME=/home/user \\
|
| 164 |
+
PATH=/home/user/.local/bin:$PATH
|
| 165 |
+
|
| 166 |
+
# Set working directory
|
| 167 |
+
WORKDIR $HOME/app
|
| 168 |
+
|
| 169 |
+
# Copy requirements file with proper ownership
|
| 170 |
+
COPY --chown=user requirements.txt .
|
| 171 |
+
|
| 172 |
+
# Install dependencies
|
| 173 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 174 |
+
|
| 175 |
+
# Copy application files with proper ownership
|
| 176 |
+
COPY --chown=user . .
|
| 177 |
+
|
| 178 |
+
# Expose port 7860
|
| 179 |
+
EXPOSE 7860
|
| 180 |
+
|
| 181 |
+
# Start Streamlit app
|
| 182 |
+
CMD ["streamlit", "run", "streamlit_app.py", "--server.port=7860", "--server.address=0.0.0.0"]
|
| 183 |
```
|
| 184 |
|
| 185 |
**π¨ CRITICAL: requirements.txt Formatting Rules**
|
|
|
|
| 199 |
- pandas
|
| 200 |
```
|
| 201 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 202 |
**Multi-Page Apps:**
|
| 203 |
For multi-page Streamlit apps, use the pages/ directory structure:
|
| 204 |
```
|
| 205 |
+
=== Dockerfile ===
|
| 206 |
+
[Dockerfile content]
|
| 207 |
+
|
| 208 |
=== streamlit_app.py ===
|
| 209 |
[main page]
|
| 210 |
|
| 211 |
+
=== requirements.txt ===
|
| 212 |
+
[dependencies]
|
| 213 |
+
|
| 214 |
=== pages/1_π_Analytics.py ===
|
| 215 |
[analytics page]
|
| 216 |
|
|
|
|
| 219 |
```
|
| 220 |
|
| 221 |
Requirements:
|
| 222 |
+
1. ALWAYS include Dockerfile, streamlit_app.py, and requirements.txt in your output
|
| 223 |
+
2. Create a modern, responsive Streamlit application
|
| 224 |
+
3. Use appropriate Streamlit components and layouts
|
| 225 |
+
4. Include proper error handling and loading states
|
| 226 |
+
5. Follow Streamlit best practices for performance
|
| 227 |
+
6. Use caching (@st.cache_data, @st.cache_resource) appropriately
|
| 228 |
+
7. Include proper session state management when needed
|
| 229 |
+
8. Make the UI intuitive and user-friendly
|
| 230 |
+
9. Add helpful tooltips and documentation
|
| 231 |
|
| 232 |
IMPORTANT: Always include "Built with anycoder" as clickable text in the header/top section of your application that links to https://huggingface.co/spaces/akhaliq/anycoder
|
| 233 |
"""
|
anycoder_app/ui.py
CHANGED
|
@@ -1161,85 +1161,110 @@ with gr.Blocks(
|
|
| 1161 |
action_text = "Updated" if is_update else "Deployed"
|
| 1162 |
return gr.update(value=f"β
{action_text}! [Open your React Space here]({space_url})", visible=True)
|
| 1163 |
|
| 1164 |
-
# Streamlit logic
|
| 1165 |
-
|
| 1166 |
-
|
| 1167 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1168 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1169 |
import tempfile
|
|
|
|
| 1170 |
|
| 1171 |
-
|
| 1172 |
-
|
| 1173 |
-
|
| 1174 |
-
try:
|
| 1175 |
-
# Try to get existing requirements.txt content
|
| 1176 |
-
existing_requirements = api.hf_hub_download(
|
| 1177 |
-
repo_id=repo_id,
|
| 1178 |
-
filename="requirements.txt",
|
| 1179 |
-
repo_type="space"
|
| 1180 |
-
)
|
| 1181 |
-
with open(existing_requirements, 'r') as f:
|
| 1182 |
-
existing_content = f.read().strip()
|
| 1183 |
|
| 1184 |
-
|
| 1185 |
-
|
| 1186 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1187 |
|
| 1188 |
-
|
| 1189 |
-
|
| 1190 |
-
|
| 1191 |
-
|
| 1192 |
-
|
| 1193 |
-
|
| 1194 |
-
|
| 1195 |
-
|
| 1196 |
-
|
| 1197 |
-
|
| 1198 |
-
|
| 1199 |
-
|
| 1200 |
-
|
| 1201 |
-
|
| 1202 |
-
|
| 1203 |
-
|
| 1204 |
-
|
| 1205 |
-
|
| 1206 |
-
|
| 1207 |
-
|
| 1208 |
-
|
| 1209 |
-
|
| 1210 |
-
|
| 1211 |
-
|
| 1212 |
-
|
| 1213 |
-
|
| 1214 |
-
|
| 1215 |
-
|
| 1216 |
-
# Add anycoder tag to existing README
|
| 1217 |
-
add_anycoder_tag_to_readme(api, repo_id)
|
| 1218 |
|
| 1219 |
-
#
|
| 1220 |
-
|
| 1221 |
-
f.write(code)
|
| 1222 |
-
temp_path = f.name
|
| 1223 |
|
| 1224 |
-
|
| 1225 |
-
|
| 1226 |
-
|
| 1227 |
-
path_in_repo="src/streamlit_app.py",
|
| 1228 |
-
repo_id=repo_id,
|
| 1229 |
-
repo_type="space"
|
| 1230 |
-
)
|
| 1231 |
-
space_url = f"https://huggingface.co/spaces/{repo_id}"
|
| 1232 |
-
action_text = "Updated" if is_update else "Deployed"
|
| 1233 |
-
return gr.update(value=f"β
{action_text}! [Open your Space here]({space_url})", visible=True)
|
| 1234 |
-
except Exception as e:
|
| 1235 |
-
error_msg = str(e)
|
| 1236 |
-
if "403 Forbidden" in error_msg and "write token" in error_msg:
|
| 1237 |
-
return gr.update(value=f"Error: Permission denied. Please ensure you have write access to {repo_id} and your token has the correct permissions.", visible=True)
|
| 1238 |
-
else:
|
| 1239 |
-
return gr.update(value=f"Error uploading Streamlit app: {e}", visible=True)
|
| 1240 |
-
finally:
|
| 1241 |
-
import os
|
| 1242 |
-
os.unlink(temp_path)
|
| 1243 |
|
| 1244 |
except Exception as e:
|
| 1245 |
error_prefix = "Error duplicating Streamlit space" if not is_update else "Error updating Streamlit space"
|
|
|
|
| 1161 |
action_text = "Updated" if is_update else "Deployed"
|
| 1162 |
return gr.update(value=f"β
{action_text}! [Open your React Space here]({space_url})", visible=True)
|
| 1163 |
|
| 1164 |
+
# Streamlit logic - Parse multi-file structure
|
| 1165 |
+
files = parse_multi_file_python_output(code)
|
| 1166 |
+
if not files:
|
| 1167 |
+
return gr.update(value="Error: Could not parse Streamlit output. Please regenerate the code.", visible=True)
|
| 1168 |
+
|
| 1169 |
+
# Verify required files exist
|
| 1170 |
+
has_streamlit_app = 'streamlit_app.py' in files or 'app.py' in files
|
| 1171 |
+
has_requirements = 'requirements.txt' in files
|
| 1172 |
+
has_dockerfile = 'Dockerfile' in files
|
| 1173 |
+
|
| 1174 |
+
if not has_streamlit_app:
|
| 1175 |
+
return gr.update(value="Error: Missing streamlit_app.py. Please regenerate the code.", visible=True)
|
| 1176 |
|
| 1177 |
+
# If Dockerfile or requirements.txt is missing, generate them
|
| 1178 |
+
if not has_dockerfile:
|
| 1179 |
+
# Generate default Dockerfile
|
| 1180 |
+
files['Dockerfile'] = """FROM python:3.11-slim
|
| 1181 |
+
|
| 1182 |
+
# Set up user with ID 1000
|
| 1183 |
+
RUN useradd -m -u 1000 user
|
| 1184 |
+
USER user
|
| 1185 |
+
ENV HOME=/home/user \\
|
| 1186 |
+
PATH=/home/user/.local/bin:$PATH
|
| 1187 |
+
|
| 1188 |
+
# Set working directory
|
| 1189 |
+
WORKDIR $HOME/app
|
| 1190 |
+
|
| 1191 |
+
# Copy requirements file with proper ownership
|
| 1192 |
+
COPY --chown=user requirements.txt .
|
| 1193 |
+
|
| 1194 |
+
# Install dependencies
|
| 1195 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 1196 |
+
|
| 1197 |
+
# Copy application files with proper ownership
|
| 1198 |
+
COPY --chown=user . .
|
| 1199 |
+
|
| 1200 |
+
# Expose port 7860
|
| 1201 |
+
EXPOSE 7860
|
| 1202 |
+
|
| 1203 |
+
# Start Streamlit app
|
| 1204 |
+
CMD ["streamlit", "run", "streamlit_app.py", "--server.port=7860", "--server.address=0.0.0.0"]
|
| 1205 |
+
"""
|
| 1206 |
+
|
| 1207 |
+
if not has_requirements:
|
| 1208 |
+
# Generate requirements.txt from imports in the main app file
|
| 1209 |
+
main_app = files.get('streamlit_app.py') or files.get('app.py', '')
|
| 1210 |
+
import_statements = extract_import_statements(main_app)
|
| 1211 |
+
files['requirements.txt'] = generate_requirements_txt_with_llm(import_statements)
|
| 1212 |
+
|
| 1213 |
+
# Upload Streamlit files
|
| 1214 |
import tempfile
|
| 1215 |
+
import time
|
| 1216 |
|
| 1217 |
+
for file_name, file_content in files.items():
|
| 1218 |
+
if not file_content:
|
| 1219 |
+
continue
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1220 |
|
| 1221 |
+
success = False
|
| 1222 |
+
last_error = None
|
| 1223 |
+
max_attempts = 3
|
| 1224 |
+
|
| 1225 |
+
for attempt in range(max_attempts):
|
| 1226 |
+
try:
|
| 1227 |
+
# Determine file extension
|
| 1228 |
+
if file_name == 'Dockerfile':
|
| 1229 |
+
suffix = ''
|
| 1230 |
+
else:
|
| 1231 |
+
suffix = f".{file_name.split('.')[-1]}"
|
| 1232 |
|
| 1233 |
+
with tempfile.NamedTemporaryFile("w", suffix=suffix, delete=False) as f:
|
| 1234 |
+
f.write(file_content)
|
| 1235 |
+
temp_path = f.name
|
| 1236 |
+
|
| 1237 |
+
api.upload_file(
|
| 1238 |
+
path_or_fileobj=temp_path,
|
| 1239 |
+
path_in_repo=file_name,
|
| 1240 |
+
repo_id=repo_id,
|
| 1241 |
+
repo_type="space"
|
| 1242 |
+
)
|
| 1243 |
+
success = True
|
| 1244 |
+
break
|
| 1245 |
+
|
| 1246 |
+
except Exception as e:
|
| 1247 |
+
last_error = e
|
| 1248 |
+
error_msg = str(e)
|
| 1249 |
+
if "403 Forbidden" in error_msg and "write token" in error_msg:
|
| 1250 |
+
return gr.update(value=f"Error: Permission denied. Please ensure you have write access to {repo_id} and your token has the correct permissions.", visible=True)
|
| 1251 |
+
|
| 1252 |
+
if attempt < max_attempts - 1:
|
| 1253 |
+
time.sleep(2)
|
| 1254 |
+
finally:
|
| 1255 |
+
import os
|
| 1256 |
+
if 'temp_path' in locals():
|
| 1257 |
+
os.unlink(temp_path)
|
| 1258 |
+
|
| 1259 |
+
if not success:
|
| 1260 |
+
return gr.update(value=f"Error uploading {file_name}: {last_error}", visible=True)
|
|
|
|
|
|
|
| 1261 |
|
| 1262 |
+
# Add anycoder tag and app_port to existing README
|
| 1263 |
+
add_anycoder_tag_to_readme(api, repo_id, app_port=7860)
|
|
|
|
|
|
|
| 1264 |
|
| 1265 |
+
space_url = f"https://huggingface.co/spaces/{repo_id}"
|
| 1266 |
+
action_text = "Updated" if is_update else "Deployed"
|
| 1267 |
+
return gr.update(value=f"β
{action_text}! [Open your Streamlit Space here]({space_url})", visible=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1268 |
|
| 1269 |
except Exception as e:
|
| 1270 |
error_prefix = "Error duplicating Streamlit space" if not is_update else "Error updating Streamlit space"
|