Anupam007's picture
Update app.py
51820e8 verified
import gradio as gr
import google.generativeai as genai
import zipfile
import os
import re
import toml # Import the toml library
# Load secrets from secrets.toml
try:
# Use os.path.join to ensure correct path
secrets_path = os.path.join(os.path.dirname(__file__), "secrets.toml")
secrets = toml.load(secrets_path)
GEMINI_API_KEY = secrets["AIzaSyC_MFgpk5t3woYooMIPkIA5-Kzaon13-m0"] # Corrected Line! Access the key *by name*
except FileNotFoundError:
print("Error: secrets.toml not found. Make sure it exists in the same directory.")
GEMINI_API_KEY = None # Or some default value
except KeyError:
print("Error: GEMINI_API_KEY not found in secrets.toml.")
GEMINI_API_KEY = None
# Step 3: Configure Gemini API
if GEMINI_API_KEY:
genai.configure(api_key=GEMINI_API_KEY)
model = genai.GenerativeModel("gemini-1.5-pro")
else:
print("Gemini API key not found. The app will not function correctly.")
model = None
# Step 4: Define enhanced prompts for Firebase integration
FIREBASE_SETUP_PROMPT = """
Add detailed Firebase setup instructions including:
1. How to create a Firebase project if not already done
2. How to add the Firebase SDK to the project
3. Proper configuration with environment variables or config files
4. Security best practices
"""
FIREBASE_AUTH_PROMPT = """
Include complete Firebase Authentication implementation with:
1. User sign-up functionality
2. Login functionality
3. Password reset capabilities
4. Session management
5. Protected routes
"""
FIREBASE_DATABASE_PROMPT = """
Include Firebase Realtime Database or Firestore implementation with:
1. Data structure design
2. CRUD operations
3. Real-time listeners
4. Security rules
"""
FIREBASE_HOSTING_PROMPT = """
Include Firebase Hosting implementation instructions:
1. Project structure for hosting
2. Configuration files
3. Deployment commands
4. Custom domain setup (if needed)
"""
# Step 5: Define the Web Development Agent function
def web_dev_agent(prompt, task_type, use_firebase, include_auth, include_database, include_hosting):
try:
if model is None:
return "Error: Gemini API key not configured.", None, "<html><body><p>Gemini API key not configured. Check the logs.</p></body></html>"
# Base prompt
full_prompt = f"You are an expert web development agent. Generate detailed, production-ready {task_type} code for the following task: {prompt}.\n\n"
# Add Firebase-specific instructions if requested
if use_firebase:
full_prompt += f"{FIREBASE_SETUP_PROMPT}\n\n"
if include_auth:
full_prompt += f"{FIREBASE_AUTH_PROMPT}\n\n"
if include_database:
full_prompt += f"{FIREBASE_DATABASE_PROMPT}\n\n"
if include_hosting:
full_prompt += f"{FIREBASE_HOSTING_PROMPT}\n\n"
# Add specific instructions based on task type
if task_type.lower() == "frontend":
full_prompt += "Focus on responsive design, clean UI, and modern frameworks like React, Vue, or Angular as appropriate. Include HTML, CSS, and JavaScript.\n\n"
else:
full_prompt += "Focus on secure, scalable backend architecture. Include proper error handling, logging, and API documentation.\n\n"
# Add final instruction for code quality
full_prompt += "Provide complete, well-commented code with clear instructions on how to implement it. Include package.json or similar configuration files where appropriate."
# Generate content using Gemini API
response = model.generate_content(full_prompt)
code = response.text
# Extract and organize code files from the response
files = extract_code_files(code, task_type.lower())
# Create output directory
os.makedirs("web_output", exist_ok=True)
# Create individual files
for filename, content in files.items():
file_path = os.path.join("web_output", filename)
os.makedirs(os.path.dirname(file_path), exist_ok=True)
with open(file_path, "w") as f:
f.write(content)
# Create a README file
readme_content = f"# Web Development Project\n\n## Description\n{prompt}\n\n## Task Type\n{task_type}\n\n"
if use_firebase:
readme_content += "## Firebase Features\n"
if include_auth:
readme_content += "- Authentication\n"
if include_database:
readme_content += "- Database\n"
if include_hosting:
readme_content += "- Hosting\n"
with open(os.path.join("web_output", "README.md"), "w") as f:
f.write(readme_content)
# Create a zip file
zip_path = "web_output/code.zip"
with zipfile.ZipFile(zip_path, 'w') as zipf:
for root, _, files in os.walk("web_output"):
for file in files:
if file != "code.zip":
file_path = os.path.join(root, file)
arcname = os.path.relpath(file_path, "web_output")
zipf.write(file_path, arcname=arcname)
# Create preview HTML for frontend tasks
if task_type.lower() == "frontend":
# Try to find an index.html or main HTML file
html_content = files.get("index.html", "")
if not html_content:
for filename, content in files.items():
if filename.endswith(".html"):
html_content = content
break
# If no HTML file found, create a simple preview of the code
if not html_content:
html_content = f"<html><body><h2>Code Preview</h2><pre>{code}</pre></body></html>"
preview_html = html_content
else:
# For backend, show a formatted version of the code
preview_html = f"<html><body><h2>Backend Code Preview</h2><pre>{code}</pre></body></html>"
# Return the full code, zip path, and preview
return code, zip_path, preview_html
except Exception as e:
return f"Error: {str(e)}", None, f"<html><body><p>Error occurred: {str(e)}</p></body></html>"
# Helper function to extract code files from the response
def extract_code_files(code_text, task_type):
files = {}
# Try to extract code blocks with filename specifications
file_pattern = r"```[\w\s]*\n?(.+?)\n```"
filename_pattern = r"[`\s]*([\w\-\.\/]+\.\w+)[`\s]*[:]*"
# Look for filename specifications followed by code blocks
filename_matches = re.finditer(filename_pattern, code_text, re.MULTILINE)
for match in filename_matches:
filename = match.group(1)
start_pos = match.end()
# Look for the next code block after the filename
code_block_match = re.search(r"```[\w\s]*\n(.*?)```", code_text[start_pos:], re.DOTALL)
if code_block_match:
content = code_block_match.group(1).strip()
files[filename] = content
# If no files were extracted using the above method, try another approach
if not files:
# Extract all code blocks and try to infer filenames
code_blocks = re.finditer(r"```([\w\s]*)\n(.*?)```", code_text, re.DOTALL)
file_counter = {
"html": 0,
"css": 0,
"js": 0,
"jsx": 0,
"tsx": 0,
"py": 0,
"json": 0,
}
for i, match in enumerate(code_blocks):
lang = match.group(1).strip().lower()
content = match.group(2).strip()
# Try to infer filename from language or context
if lang == "html":
filename = "index.html" if file_counter["html"] == 0 else f"page{file_counter['html']}.html"
file_counter["html"] += 1
elif lang == "css":
filename = "styles.css" if file_counter["css"] == 0 else f"styles{file_counter['css']}.css"
file_counter["css"] += 1
elif lang == "javascript" or lang == "js":
filename = "script.js" if file_counter["js"] == 0 else f"script{file_counter['js']}.js"
file_counter["js"] += 1
elif lang == "jsx":
filename = "App.jsx" if file_counter["jsx"] == 0 else f"Component{file_counter['jsx']}.jsx"
file_counter["jsx"] += 1
elif lang == "tsx":
filename = "App.tsx" if file_counter["tsx"] == 0 else f"Component{file_counter['tsx']}.tsx"
file_counter["tsx"] += 1
elif lang == "python" or lang == "py":
filename = "app.py" if file_counter["py"] == 0 else f"module{file_counter['py']}.py"
file_counter["py"] += 1
elif lang == "json":
filename = "package.json" if file_counter["json"] == 0 else f"config{file_counter['json']}.json"
file_counter["json"] += 1
else:
# If language can't be determined, use a generic filename
filename = f"file{i}.txt"
files[filename] = content
# If we still don't have any files, just create a single file with the entire response
if not files:
if task_type == "frontend":
files["index.html"] = code_text
else:
files["app.js"] = code_text
return files
# Step 6: Create the Gradio UI
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown("# Gemini 2.0 Web Development Agent with Firebase Integration")
with gr.Row():
with gr.Column(scale=2):
prompt = gr.Textbox(
lines=5,
placeholder="Describe your web development task in detail. Example: 'Create a responsive blog homepage with a navigation bar, featured posts section, and footer'",
label="Describe your frontend/backend task"
)
with gr.Column(scale=1):
task_type = gr.Radio(
["Frontend", "Backend", "Full-Stack"],
value="Frontend",
label="Task Type"
)
use_firebase = gr.Checkbox(
label="Include Firebase Integration",
value=False
)
with gr.Group(visible=False) as firebase_options:
include_auth = gr.Checkbox(label="Authentication (Sign up/Login)", value=True)
include_database = gr.Checkbox(label="Database (Realtime or Firestore)", value=True)
include_hosting = gr.Checkbox(label="Hosting", value=True)
submit_btn = gr.Button("Generate Code", variant="primary")
# Make Firebase options visible only when Firebase integration is checked
use_firebase.change(
fn=lambda x: gr.Group(visible=x),
inputs=[use_firebase],
outputs=[firebase_options]
)
with gr.Tabs():
with gr.TabItem("Code"):
output_code = gr.Code(language="html", label="Generated Code")
with gr.TabItem("Preview"):
preview = gr.HTML(label="Preview (for Frontend only)")
with gr.TabItem("Download"):
gr.Markdown("### Download your code")
download_btn = gr.File(label="Download Code (.zip)")
# Connect the function to the button
submit_btn.click(
fn=web_dev_agent,
inputs=[prompt, task_type, use_firebase, include_auth, include_database, include_hosting],
outputs=[output_code, download_btn, preview]
)
gr.Markdown("""
## How to Use
1. Enter a detailed description of your web development task
2. Select the task type (Frontend, Backend, or Full-Stack)
3. Check "Include Firebase Integration" if you want Firebase features
4. Select which Firebase features you want to include
5. Click "Generate Code"
6. View the generated code in the "Code" tab
7. See a preview in the "Preview" tab (for Frontend code)
8. Download the code as a zip file from the "Download" tab
## Firebase Setup
After downloading the code:
1. Create a Firebase project at [Firebase Console](https://console.firebase.google.com/)
2. Follow the setup instructions in the generated code
3. Deploy your application using Firebase CLI
""")
# Launch the Gradio app - DO NOT INCLUDE THIS LINE FOR HUGGING FACE
#demo.launch(debug=True)