|
|
""" |
|
|
Documentation management for backend system prompts. |
|
|
Handles fetching, caching, and updating documentation from llms.txt files. |
|
|
No dependencies on Gradio or other heavy libraries - pure Python only. |
|
|
""" |
|
|
import os |
|
|
import re |
|
|
from datetime import datetime |
|
|
from typing import Optional |
|
|
|
|
|
try: |
|
|
import requests |
|
|
HAS_REQUESTS = True |
|
|
except ImportError: |
|
|
HAS_REQUESTS = False |
|
|
print("Warning: requests library not available, using minimal fallback") |
|
|
|
|
|
|
|
|
GRADIO_LLMS_TXT_URL = "https://www.gradio.app/llms.txt" |
|
|
GRADIO_DOCS_CACHE_FILE = ".backend_gradio_docs_cache.txt" |
|
|
GRADIO_DOCS_LAST_UPDATE_FILE = ".backend_gradio_docs_last_update.txt" |
|
|
|
|
|
|
|
|
_gradio_docs_content: Optional[str] = None |
|
|
_gradio_docs_last_fetched: Optional[datetime] = None |
|
|
|
|
|
def fetch_gradio_docs() -> Optional[str]: |
|
|
"""Fetch the latest Gradio documentation from llms.txt""" |
|
|
if not HAS_REQUESTS: |
|
|
return None |
|
|
|
|
|
try: |
|
|
response = requests.get(GRADIO_LLMS_TXT_URL, timeout=10) |
|
|
response.raise_for_status() |
|
|
return response.text |
|
|
except Exception as e: |
|
|
print(f"Warning: Failed to fetch Gradio docs from {GRADIO_LLMS_TXT_URL}: {e}") |
|
|
return None |
|
|
|
|
|
def filter_problematic_instructions(content: str) -> str: |
|
|
"""Filter out problematic instructions that cause LLM to stop generation prematurely""" |
|
|
if not content: |
|
|
return content |
|
|
|
|
|
|
|
|
problematic_patterns = [ |
|
|
r"Output ONLY the code inside a ``` code block, and do not include any explanations or extra text", |
|
|
r"output only the code inside a ```.*?``` code block", |
|
|
r"Always output only the.*?code.*?inside.*?```.*?```.*?block", |
|
|
r"Return ONLY the code inside a.*?```.*?``` code block", |
|
|
r"Do NOT add the language name at the top of the code output", |
|
|
r"do not include any explanations or extra text", |
|
|
r"Always output only the.*?code blocks.*?shown above, and do not include any explanations", |
|
|
r"Output.*?ONLY.*?code.*?inside.*?```.*?```", |
|
|
r"Return.*?ONLY.*?code.*?inside.*?```.*?```", |
|
|
r"Generate.*?ONLY.*?code.*?inside.*?```.*?```", |
|
|
r"Provide.*?ONLY.*?code.*?inside.*?```.*?```", |
|
|
] |
|
|
|
|
|
|
|
|
filtered_content = content |
|
|
for pattern in problematic_patterns: |
|
|
|
|
|
filtered_content = re.sub(pattern, "", filtered_content, flags=re.IGNORECASE | re.DOTALL) |
|
|
|
|
|
|
|
|
filtered_content = re.sub(r'\n\s*\n\s*\n', '\n\n', filtered_content) |
|
|
filtered_content = re.sub(r'^\s+', '', filtered_content, flags=re.MULTILINE) |
|
|
|
|
|
return filtered_content |
|
|
|
|
|
def load_cached_gradio_docs() -> Optional[str]: |
|
|
"""Load cached Gradio documentation from file""" |
|
|
try: |
|
|
if os.path.exists(GRADIO_DOCS_CACHE_FILE): |
|
|
with open(GRADIO_DOCS_CACHE_FILE, 'r', encoding='utf-8') as f: |
|
|
return f.read() |
|
|
except Exception as e: |
|
|
print(f"Warning: Failed to load cached Gradio docs: {e}") |
|
|
return None |
|
|
|
|
|
def save_gradio_docs_cache(content: str): |
|
|
"""Save Gradio documentation to cache file""" |
|
|
try: |
|
|
with open(GRADIO_DOCS_CACHE_FILE, 'w', encoding='utf-8') as f: |
|
|
f.write(content) |
|
|
with open(GRADIO_DOCS_LAST_UPDATE_FILE, 'w', encoding='utf-8') as f: |
|
|
f.write(datetime.now().isoformat()) |
|
|
except Exception as e: |
|
|
print(f"Warning: Failed to save Gradio docs cache: {e}") |
|
|
|
|
|
def should_update_gradio_docs() -> bool: |
|
|
"""Check if Gradio documentation should be updated""" |
|
|
|
|
|
return not os.path.exists(GRADIO_DOCS_CACHE_FILE) |
|
|
|
|
|
def get_gradio_docs_content() -> str: |
|
|
"""Get the current Gradio documentation content, updating if necessary""" |
|
|
global _gradio_docs_content, _gradio_docs_last_fetched |
|
|
|
|
|
|
|
|
if (_gradio_docs_content is None or |
|
|
_gradio_docs_last_fetched is None or |
|
|
should_update_gradio_docs()): |
|
|
|
|
|
print("π Loading Gradio 6 documentation...") |
|
|
|
|
|
|
|
|
latest_content = fetch_gradio_docs() |
|
|
|
|
|
if latest_content: |
|
|
|
|
|
filtered_content = filter_problematic_instructions(latest_content) |
|
|
_gradio_docs_content = filtered_content |
|
|
_gradio_docs_last_fetched = datetime.now() |
|
|
save_gradio_docs_cache(filtered_content) |
|
|
print(f"β
Gradio 6 documentation loaded successfully ({len(filtered_content)} chars)") |
|
|
else: |
|
|
|
|
|
cached_content = load_cached_gradio_docs() |
|
|
if cached_content: |
|
|
_gradio_docs_content = cached_content |
|
|
_gradio_docs_last_fetched = datetime.now() |
|
|
print(f"β οΈ Using cached Gradio documentation (network fetch failed) ({len(cached_content)} chars)") |
|
|
else: |
|
|
|
|
|
_gradio_docs_content = """ |
|
|
# Gradio API Reference (Offline Fallback) |
|
|
|
|
|
This is a minimal fallback when documentation cannot be fetched. |
|
|
Please check your internet connection for the latest API reference. |
|
|
|
|
|
Basic Gradio components: Button, Textbox, Slider, Image, Audio, Video, File, etc. |
|
|
Use gr.Blocks() for custom layouts and gr.Interface() for simple apps. |
|
|
|
|
|
For the latest documentation, visit: https://www.gradio.app/llms.txt |
|
|
""" |
|
|
print("β Using minimal fallback documentation") |
|
|
|
|
|
return _gradio_docs_content or "" |
|
|
|
|
|
def build_gradio_system_prompt() -> str: |
|
|
"""Build the complete Gradio system prompt with full documentation""" |
|
|
|
|
|
|
|
|
docs_content = get_gradio_docs_content() |
|
|
|
|
|
|
|
|
base_prompt = """You are an expert Gradio developer. Create a complete, working Gradio application based on the user's request. Generate all necessary code to make the application functional and runnable. |
|
|
|
|
|
## Multi-File Application Structure |
|
|
|
|
|
When creating Gradio applications, organize your code into multiple files for proper deployment: |
|
|
|
|
|
**File Organization:** |
|
|
- `app.py` - Main application entry point (REQUIRED) |
|
|
- `requirements.txt` - Python dependencies (REQUIRED, auto-generated from imports) |
|
|
- `utils.py` - Utility functions and helpers (optional) |
|
|
- `models.py` - Model loading and inference functions (optional) |
|
|
- `config.py` - Configuration and constants (optional) |
|
|
|
|
|
**Output Format:** |
|
|
You MUST use this exact format with file separators: |
|
|
|
|
|
=== app.py === |
|
|
[complete app.py content] |
|
|
|
|
|
=== utils.py === |
|
|
[utility functions - if needed] |
|
|
|
|
|
**π¨ CRITICAL: DO NOT GENERATE requirements.txt or README.md** |
|
|
- requirements.txt is automatically generated from your app.py imports |
|
|
- README.md is automatically provided by the template |
|
|
- Generating these files will break the deployment process |
|
|
|
|
|
Requirements: |
|
|
1. Create a modern, intuitive Gradio application |
|
|
2. Use appropriate Gradio components (gr.Textbox, gr.Slider, etc.) |
|
|
3. Include proper error handling and loading states |
|
|
4. Use gr.Interface or gr.Blocks as appropriate |
|
|
5. Add helpful descriptions and examples |
|
|
6. Follow Gradio best practices |
|
|
7. Make the UI user-friendly with clear labels |
|
|
8. Include proper documentation in docstrings |
|
|
|
|
|
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 |
|
|
|
|
|
--- |
|
|
|
|
|
## Complete Gradio 6 Documentation |
|
|
|
|
|
Below is the complete, official Gradio 6 documentation automatically synced from https://www.gradio.app/llms.txt: |
|
|
|
|
|
""" |
|
|
|
|
|
|
|
|
full_prompt = base_prompt + docs_content |
|
|
|
|
|
|
|
|
final_instructions = """ |
|
|
|
|
|
--- |
|
|
|
|
|
## Final Instructions |
|
|
|
|
|
- Always use the exact function signatures and patterns from the Gradio 6 documentation above |
|
|
- Follow Gradio 6 migration guidelines if you're familiar with older versions |
|
|
- Use modern Gradio 6 API patterns (e.g., footer_links instead of show_api, api_visibility instead of show_api in events) |
|
|
- Generate production-ready code that follows all best practices |
|
|
- Always include the "Built with anycoder" attribution in the header |
|
|
|
|
|
""" |
|
|
|
|
|
return full_prompt + final_instructions |
|
|
|
|
|
def initialize_backend_docs(): |
|
|
"""Initialize backend documentation system on startup""" |
|
|
try: |
|
|
|
|
|
docs = get_gradio_docs_content() |
|
|
if docs: |
|
|
print(f"π Backend documentation system initialized ({len(docs)} chars loaded)") |
|
|
else: |
|
|
print("β οΈ Backend documentation system initialized with fallback content") |
|
|
except Exception as e: |
|
|
print(f"Warning: Failed to initialize backend documentation: {e}") |
|
|
|
|
|
|
|
|
if __name__ != "__main__": |
|
|
|
|
|
try: |
|
|
initialize_backend_docs() |
|
|
except Exception as e: |
|
|
print(f"Warning: Failed to auto-initialize backend docs: {e}") |
|
|
|
|
|
|