add daggr support
Browse files- backend_api.py +4 -2
- backend_deploy.py +4 -4
- backend_parsers.py +1 -0
- backend_prompts.py +91 -0
- frontend/src/components/ControlPanel.tsx +1 -0
- frontend/src/components/LandingPage.tsx +1 -0
- frontend/src/types/index.ts +2 -2
backend_api.py
CHANGED
|
@@ -45,6 +45,7 @@ try:
|
|
| 45 |
get_gradio_system_prompt, # Import the function to get dynamic prompt
|
| 46 |
get_comfyui_system_prompt, # Import the function to get dynamic ComfyUI prompt
|
| 47 |
JSON_SYSTEM_PROMPT,
|
|
|
|
| 48 |
GENERIC_SYSTEM_PROMPT
|
| 49 |
)
|
| 50 |
# Get the Gradio system prompt (includes full Gradio 6 documentation)
|
|
@@ -80,6 +81,7 @@ SYSTEM_PROMPT_CACHE = {
|
|
| 80 |
"transformers.js": TRANSFORMERS_JS_SYSTEM_PROMPT,
|
| 81 |
"react": REACT_SYSTEM_PROMPT,
|
| 82 |
"comfyui": COMFYUI_SYSTEM_PROMPT, # Use ComfyUI-specific prompt with documentation
|
|
|
|
| 83 |
}
|
| 84 |
|
| 85 |
# Client connection pool for reuse (thread-safe)
|
|
@@ -114,7 +116,7 @@ AVAILABLE_MODELS = [
|
|
| 114 |
MODEL_CACHE = {model["id"]: model for model in AVAILABLE_MODELS}
|
| 115 |
print(f"[Startup] ✅ Performance optimizations loaded: {len(SYSTEM_PROMPT_CACHE)} cached prompts, {len(MODEL_CACHE)} cached models, client pooling enabled")
|
| 116 |
|
| 117 |
-
LANGUAGE_CHOICES = ["html", "gradio", "transformers.js", "streamlit", "comfyui", "react"]
|
| 118 |
|
| 119 |
app = FastAPI(title="AnyCoder API", version="1.0.0")
|
| 120 |
|
|
@@ -710,7 +712,7 @@ def cleanup_generated_code(code: str, language: str) -> str:
|
|
| 710 |
code = code[:last_tag + 7].strip()
|
| 711 |
|
| 712 |
# For Python: remove text after the last function/class definition or code block
|
| 713 |
-
elif language in ["gradio", "streamlit"]:
|
| 714 |
# Find the last line that looks like actual code (not comments or blank)
|
| 715 |
lines = code.split('\n')
|
| 716 |
last_code_line = -1
|
|
|
|
| 45 |
get_gradio_system_prompt, # Import the function to get dynamic prompt
|
| 46 |
get_comfyui_system_prompt, # Import the function to get dynamic ComfyUI prompt
|
| 47 |
JSON_SYSTEM_PROMPT,
|
| 48 |
+
DAGGR_SYSTEM_PROMPT,
|
| 49 |
GENERIC_SYSTEM_PROMPT
|
| 50 |
)
|
| 51 |
# Get the Gradio system prompt (includes full Gradio 6 documentation)
|
|
|
|
| 81 |
"transformers.js": TRANSFORMERS_JS_SYSTEM_PROMPT,
|
| 82 |
"react": REACT_SYSTEM_PROMPT,
|
| 83 |
"comfyui": COMFYUI_SYSTEM_PROMPT, # Use ComfyUI-specific prompt with documentation
|
| 84 |
+
"daggr": DAGGR_SYSTEM_PROMPT,
|
| 85 |
}
|
| 86 |
|
| 87 |
# Client connection pool for reuse (thread-safe)
|
|
|
|
| 116 |
MODEL_CACHE = {model["id"]: model for model in AVAILABLE_MODELS}
|
| 117 |
print(f"[Startup] ✅ Performance optimizations loaded: {len(SYSTEM_PROMPT_CACHE)} cached prompts, {len(MODEL_CACHE)} cached models, client pooling enabled")
|
| 118 |
|
| 119 |
+
LANGUAGE_CHOICES = ["html", "gradio", "transformers.js", "streamlit", "comfyui", "react", "daggr"]
|
| 120 |
|
| 121 |
app = FastAPI(title="AnyCoder API", version="1.0.0")
|
| 122 |
|
|
|
|
| 712 |
code = code[:last_tag + 7].strip()
|
| 713 |
|
| 714 |
# For Python: remove text after the last function/class definition or code block
|
| 715 |
+
elif language in ["gradio", "streamlit", "daggr"]:
|
| 716 |
# Find the last line that looks like actual code (not comments or blank)
|
| 717 |
lines = code.split('\n')
|
| 718 |
last_code_line = -1
|
backend_deploy.py
CHANGED
|
@@ -278,8 +278,8 @@ def is_streamlit_code(code: str) -> bool:
|
|
| 278 |
|
| 279 |
|
| 280 |
def is_gradio_code(code: str) -> bool:
|
| 281 |
-
"""Check if code is Gradio"""
|
| 282 |
-
return 'import gradio' in code or 'gr.' in code
|
| 283 |
|
| 284 |
|
| 285 |
def detect_sdk_from_code(code: str, language: str) -> str:
|
|
@@ -294,7 +294,7 @@ def detect_sdk_from_code(code: str, language: str) -> str:
|
|
| 294 |
return "docker"
|
| 295 |
elif language == "streamlit" or is_streamlit_code(code):
|
| 296 |
return "docker"
|
| 297 |
-
elif language == "gradio" or is_gradio_code(code):
|
| 298 |
return "gradio"
|
| 299 |
else:
|
| 300 |
return "gradio" # Default
|
|
@@ -673,7 +673,7 @@ def deploy_to_huggingface_space(
|
|
| 673 |
# Fall through to normal React deployment below
|
| 674 |
|
| 675 |
# For Gradio space updates (import/redesign), update .py files and upload all new files
|
| 676 |
-
if is_update and language
|
| 677 |
print(f"[Deploy] Gradio space update - updating .py files and uploading any new files")
|
| 678 |
|
| 679 |
# Parse the code to get all files
|
|
|
|
| 278 |
|
| 279 |
|
| 280 |
def is_gradio_code(code: str) -> bool:
|
| 281 |
+
"""Check if code is Gradio or Daggr"""
|
| 282 |
+
return 'import gradio' in code or 'gr.' in code or 'import daggr' in code or 'from daggr' in code
|
| 283 |
|
| 284 |
|
| 285 |
def detect_sdk_from_code(code: str, language: str) -> str:
|
|
|
|
| 294 |
return "docker"
|
| 295 |
elif language == "streamlit" or is_streamlit_code(code):
|
| 296 |
return "docker"
|
| 297 |
+
elif language == "gradio" or language == "daggr" or is_gradio_code(code):
|
| 298 |
return "gradio"
|
| 299 |
else:
|
| 300 |
return "gradio" # Default
|
|
|
|
| 673 |
# Fall through to normal React deployment below
|
| 674 |
|
| 675 |
# For Gradio space updates (import/redesign), update .py files and upload all new files
|
| 676 |
+
if is_update and language in ["gradio", "daggr"]:
|
| 677 |
print(f"[Deploy] Gradio space update - updating .py files and uploading any new files")
|
| 678 |
|
| 679 |
# Parse the code to get all files
|
backend_parsers.py
CHANGED
|
@@ -397,6 +397,7 @@ Instructions:
|
|
| 397 |
* streamlit often needs: pandas, numpy, requests
|
| 398 |
* opencv-python often needs: numpy, pillow
|
| 399 |
* fastapi often needs: uvicorn, pydantic
|
|
|
|
| 400 |
* torch often needs: torchvision, torchaudio (if doing computer vision/audio)
|
| 401 |
- Include packages for common file formats if relevant (openpyxl, python-docx, PyPDF2)
|
| 402 |
- Do not include Python built-in modules
|
|
|
|
| 397 |
* streamlit often needs: pandas, numpy, requests
|
| 398 |
* opencv-python often needs: numpy, pillow
|
| 399 |
* fastapi often needs: uvicorn, pydantic
|
| 400 |
+
* daggr often needs: daggr, gradio>=6.0, pydub
|
| 401 |
* torch often needs: torchvision, torchaudio (if doing computer vision/audio)
|
| 402 |
- Include packages for common file formats if relevant (openpyxl, python-docx, PyPDF2)
|
| 403 |
- Do not include Python built-in modules
|
backend_prompts.py
CHANGED
|
@@ -537,6 +537,97 @@ IMPORTANT: Include "Built with anycoder - https://huggingface.co/spaces/akhaliq/
|
|
| 537 |
"""
|
| 538 |
|
| 539 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 540 |
GENERIC_SYSTEM_PROMPT = """You are an expert {language} developer. Write clean, idiomatic, and runnable {language} code for the user's request. If possible, include comments and best practices. Generate complete, working code that can be run immediately. If the user provides a file or other context, use it as a reference. If the code is for a script or app, make it as self-contained as possible.
|
| 541 |
|
| 542 |
**🚨 CRITICAL: DO NOT Generate README.md Files**
|
|
|
|
| 537 |
"""
|
| 538 |
|
| 539 |
|
| 540 |
+
# Daggr system prompt - for building DAG-based AI workflows
|
| 541 |
+
DAGGR_SYSTEM_PROMPT = """You are an expert Daggr developer. Create a complete, working Daggr workflow application based on the user's request.
|
| 542 |
+
|
| 543 |
+
`daggr` is a Python library for building AI workflows that connect Gradio apps, ML models, and custom Python functions. It automatically generates a visual canvas for inspecting intermediate outputs and preserves state.
|
| 544 |
+
|
| 545 |
+
## Core Concepts
|
| 546 |
+
- **Nodes**: Computation units (GradioSpace, Inference call, or Python function).
|
| 547 |
+
- **Ports**: Input and Output data flows between nodes.
|
| 548 |
+
- **Graph**: The container for all nodes.
|
| 549 |
+
|
| 550 |
+
## Node Types
|
| 551 |
+
### 1. `GradioNode`
|
| 552 |
+
Calls a Gradio Space API endpoint.
|
| 553 |
+
```python
|
| 554 |
+
from daggr import GradioNode
|
| 555 |
+
import gradio as gr
|
| 556 |
+
|
| 557 |
+
image_gen = GradioNode(
|
| 558 |
+
space_or_url="black-forest-labs/FLUX.1-schnell",
|
| 559 |
+
api_name="/infer",
|
| 560 |
+
inputs={
|
| 561 |
+
"prompt": gr.Textbox(label="Prompt"),
|
| 562 |
+
"seed": 42,
|
| 563 |
+
"width": 1024,
|
| 564 |
+
"height": 1024,
|
| 565 |
+
},
|
| 566 |
+
outputs={
|
| 567 |
+
"image": gr.Image(label="Generated Image"),
|
| 568 |
+
},
|
| 569 |
+
)
|
| 570 |
+
```
|
| 571 |
+
|
| 572 |
+
### 2. `InferenceNode`
|
| 573 |
+
Calls a model via Hugging Face Inference Providers.
|
| 574 |
+
```python
|
| 575 |
+
from daggr import InferenceNode
|
| 576 |
+
import gradio as gr
|
| 577 |
+
|
| 578 |
+
llm = InferenceNode(
|
| 579 |
+
model="meta-llama/Llama-3.1-8B-Instruct",
|
| 580 |
+
inputs={"prompt": gr.Textbox(label="Prompt")},
|
| 581 |
+
outputs={"response": gr.Textbox(label="Response")},
|
| 582 |
+
)
|
| 583 |
+
```
|
| 584 |
+
|
| 585 |
+
### 3. `FnNode`
|
| 586 |
+
Runs a Python function. Input ports discovered from signature.
|
| 587 |
+
```python
|
| 588 |
+
from daggr import FnNode
|
| 589 |
+
import gradio as gr
|
| 590 |
+
|
| 591 |
+
def summarize(text: str) -> str:
|
| 592 |
+
return text[:100] + "..."
|
| 593 |
+
|
| 594 |
+
summarizer = FnNode(
|
| 595 |
+
fn=summarize,
|
| 596 |
+
inputs={"text": gr.Textbox(label="Input")},
|
| 597 |
+
outputs={"summary": gr.Textbox(label="Summary")},
|
| 598 |
+
)
|
| 599 |
+
```
|
| 600 |
+
|
| 601 |
+
## Advanced Features
|
| 602 |
+
- **Scatter/Gather**: Use `.each` to scatter a list output and `.all()` to gather.
|
| 603 |
+
- **Choice Nodes**: Use `|` to offer alternatives (e.g., `node_v1 | node_v2`).
|
| 604 |
+
- **Postprocessing**: Use `postprocess=lambda original, target: target` in `GradioNode` or `InferenceNode` to extract specific outputs.
|
| 605 |
+
|
| 606 |
+
## Deployment & Hosting
|
| 607 |
+
Daggr apps launch with `graph.launch()`. For deployment to Spaces, they act like standard Gradio apps.
|
| 608 |
+
|
| 609 |
+
## Requirements:
|
| 610 |
+
1. ALWAYS generate a complete `app.py` and `requirements.txt` (via imports).
|
| 611 |
+
2. Organize workflow logically with clear node names.
|
| 612 |
+
3. Use `GradioNode` or `InferenceNode` when possible for parallel execution.
|
| 613 |
+
4. Always include "Built with anycoder" in the header.
|
| 614 |
+
|
| 615 |
+
=== app.py ===
|
| 616 |
+
import gradio as gr
|
| 617 |
+
from daggr import GradioNode, FnNode, InferenceNode, Graph
|
| 618 |
+
|
| 619 |
+
# Define nodes...
|
| 620 |
+
# ...
|
| 621 |
+
|
| 622 |
+
graph = Graph(name="My Workflow", nodes=[node1, node2])
|
| 623 |
+
graph.launch()
|
| 624 |
+
|
| 625 |
+
**🚨 CRITICAL: DO NOT Generate README.md Files**
|
| 626 |
+
- NEVER generate README.md files under any circumstances
|
| 627 |
+
- A template README.md is automatically provided and will be overridden by the deployment system
|
| 628 |
+
"""
|
| 629 |
+
|
| 630 |
+
|
| 631 |
GENERIC_SYSTEM_PROMPT = """You are an expert {language} developer. Write clean, idiomatic, and runnable {language} code for the user's request. If possible, include comments and best practices. Generate complete, working code that can be run immediately. If the user provides a file or other context, use it as a reference. If the code is for a script or app, make it as self-contained as possible.
|
| 632 |
|
| 633 |
**🚨 CRITICAL: DO NOT Generate README.md Files**
|
frontend/src/components/ControlPanel.tsx
CHANGED
|
@@ -84,6 +84,7 @@ export default function ControlPanel({
|
|
| 84 |
if (lang === 'html') return 'HTML';
|
| 85 |
if (lang === 'transformers.js') return 'Transformers.js';
|
| 86 |
if (lang === 'comfyui') return 'ComfyUI';
|
|
|
|
| 87 |
return lang.charAt(0).toUpperCase() + lang.slice(1);
|
| 88 |
};
|
| 89 |
|
|
|
|
| 84 |
if (lang === 'html') return 'HTML';
|
| 85 |
if (lang === 'transformers.js') return 'Transformers.js';
|
| 86 |
if (lang === 'comfyui') return 'ComfyUI';
|
| 87 |
+
if (lang === 'daggr') return 'Daggr';
|
| 88 |
return lang.charAt(0).toUpperCase() + lang.slice(1);
|
| 89 |
};
|
| 90 |
|
frontend/src/components/LandingPage.tsx
CHANGED
|
@@ -277,6 +277,7 @@ export default function LandingPage({
|
|
| 277 |
if (lang === 'html') return 'HTML';
|
| 278 |
if (lang === 'transformers.js') return 'Transformers.js';
|
| 279 |
if (lang === 'comfyui') return 'ComfyUI';
|
|
|
|
| 280 |
return lang.charAt(0).toUpperCase() + lang.slice(1);
|
| 281 |
};
|
| 282 |
|
|
|
|
| 277 |
if (lang === 'html') return 'HTML';
|
| 278 |
if (lang === 'transformers.js') return 'Transformers.js';
|
| 279 |
if (lang === 'comfyui') return 'ComfyUI';
|
| 280 |
+
if (lang === 'daggr') return 'Daggr';
|
| 281 |
return lang.charAt(0).toUpperCase() + lang.slice(1);
|
| 282 |
};
|
| 283 |
|
frontend/src/types/index.ts
CHANGED
|
@@ -54,7 +54,7 @@ export interface DeploymentRequest {
|
|
| 54 |
requirements?: string;
|
| 55 |
existing_repo_id?: string; // For updating existing spaces
|
| 56 |
commit_message?: string;
|
| 57 |
-
history?: Array<{role: string; content: string}>; // Chat history for tracking
|
| 58 |
}
|
| 59 |
|
| 60 |
export interface DeploymentResponse {
|
|
@@ -65,5 +65,5 @@ export interface DeploymentResponse {
|
|
| 65 |
repo_id?: string;
|
| 66 |
}
|
| 67 |
|
| 68 |
-
export type Language = 'html' | 'gradio' | 'transformers.js' | 'streamlit' | 'comfyui' | 'react';
|
| 69 |
|
|
|
|
| 54 |
requirements?: string;
|
| 55 |
existing_repo_id?: string; // For updating existing spaces
|
| 56 |
commit_message?: string;
|
| 57 |
+
history?: Array<{ role: string; content: string }>; // Chat history for tracking
|
| 58 |
}
|
| 59 |
|
| 60 |
export interface DeploymentResponse {
|
|
|
|
| 65 |
repo_id?: string;
|
| 66 |
}
|
| 67 |
|
| 68 |
+
export type Language = 'html' | 'gradio' | 'transformers.js' | 'streamlit' | 'comfyui' | 'react' | 'daggr';
|
| 69 |
|