Spaces:
Running
Running
File size: 6,787 Bytes
dfc5e93 4917053 cd13883 4917053 cd13883 4917053 cd13883 4917053 5f4f3c1 4917053 853d569 4917053 9376840 4917053 b752712 4917053 b752712 4917053 cd13883 4917053 58a5e73 cd13883 4917053 cd13883 4917053 cd13883 0950920 58a5e73 4917053 58a5e73 4917053 83207ef 4917053 dfc5e93 4917053 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
import gradio as gr
from huggingface_hub import InferenceClient
import os
# --- Configuration ---
# Use environment variable for token, fallback to default if not set
# For Spaces, set the HF_TOKEN secret
API_TOKEN = os.getenv("HF_TOKEN", None)
MODEL = "HuggingFaceH4/zephyr-7b-beta"
# --- Initialize Inference Client ---
try:
if API_TOKEN:
print("Using HF Token.")
client = InferenceClient(model=MODEL, token=API_TOKEN)
else:
print("HF Token not found. Running without token (may lead to rate limits).")
client = InferenceClient(model=MODEL)
except Exception as e:
print(f"Error initializing Inference Client: {e}")
# Optionally, raise the error or handle it gracefully
raise gr.Error(f"Failed to initialize the AI model client. Please check model name and token. Error: {e}")
# --- Core Code Generation Function ---
def generate_code(
prompt: str,
backend_choice: str,
file_structure: str,
max_tokens: int,
temperature: float,
top_p: float,
):
"""
Generates website code based on user prompt and choices.
Yields the code token by token for live updates.
"""
print(f"Received prompt: {prompt}")
print(f"Backend choice: {backend_choice}")
print(f"File structure: {file_structure}")
print(f"Max tokens: {max_tokens}, Temp: {temperature}, Top-p: {top_p}")
# --- System Message (Internal) ---
# This guides the AI's behavior. It's not user-editable in the UI.
system_message = (
"You are an expert frontend web developer AI. Your task is to generate HTML, CSS, and JavaScript code "
"for a website based on the user's description. \n"
"**Constraints:**\n"
"- ALWAYS generate a complete `index.html` file.\n"
"- ONLY output the raw code for the requested files.\n"
"- Do NOT include any explanations, comments about the code, or introductory sentences.\n"
"- Start the response *directly* with the code.\n"
"- If 'Multiple Files' is selected, structure the output clearly:\n"
" - Start the HTML section with a clear marker like `<!-- index.html -->`\n"
" - Start the CSS section with a clear marker like `/* style.css */`\n"
" - Start the JavaScript section (if needed) with `// script.js`\n"
" - Ensure each file's code follows its respective marker.\n"
"- If 'Single File' is selected, embed CSS within `<style>` tags in the `<head>` and JavaScript within `<script>` tags "
"at the end of the `<body>` of the `index.html` file.\n"
f"- Consider the user's choice of backend context ('{backend_choice}') when generating placeholders or structure, but focus on the frontend code.\n"
f"- Generate based on the file structure preference: '{file_structure}'."
)
# --- Construct the messages for the API ---
messages = [
{"role": "system", "content": system_message},
{"role": "user", "content": prompt}
]
# --- Stream the response from the API ---
response_stream = ""
try:
print("Sending request to API...")
for message in client.chat_completion(
messages=messages,
max_tokens=max_tokens,
stream=True,
temperature=temperature,
top_p=top_p,
stop_sequences=["<|endoftext|>", "<|im_end|>", "</s>"] # Add common stop tokens
):
token = message.choices[0].delta.content
# Basic check to ensure token is a string (it should be)
if isinstance(token, str):
response_stream += token
yield response_stream # Yield the cumulative response for live update
# Add a small safety break if generation seems stuck or too long (optional)
# if len(response_stream) > max_tokens * 5: # Heuristic limit
# print("Warning: Exceeded heuristic length limit, stopping generation.")
# break
print("API stream finished.")
except Exception as e:
print(f"Error during API call: {e}")
yield f"An error occurred while generating the code: {e}"
# --- Build Gradio Interface using Blocks ---
with gr.Blocks() as demo:
gr.Markdown("# Website Code Generator π")
gr.Markdown(
"Describe the website you want, choose your options, and the AI will generate the frontend code (HTML, CSS, JS). "
"The code will appear live in the text editor below."
)
with gr.Row():
with gr.Column(scale=2):
prompt_input = gr.Textbox(
label="Website Description",
placeholder="e.g., A simple portfolio website with a header, an 'About Me' section, a project grid, and a contact form.",
lines=4,
)
backend_radio = gr.Radio(
["Static", "Flask", "Node.js"],
label="Backend Context",
value="Static",
info="How should the AI structure the frontend (e.g., template placeholders for Flask)?",
)
file_structure_radio = gr.Radio(
["Single File", "Multiple Files"],
label="Output File Structure",
value="Multiple Files",
info="Generate everything in index.html or separate CSS/JS files?",
)
generate_button = gr.Button("Generate Website Code", variant="primary")
with gr.Column(scale=3):
code_output = gr.Code(
label="Generated Code",
language="html", # Start with html, might contain css/js too
lines=25,
interactive=False, # Read-only display
)
with gr.Accordion("Advanced Generation Settings", open=False):
max_tokens_slider = gr.Slider(
minimum=256, maximum=4096, value=1500, step=64, label="Max New Tokens"
)
temperature_slider = gr.Slider(
minimum=0.1, maximum=1.5, value=0.7, step=0.1, label="Temperature"
)
top_p_slider = gr.Slider(
minimum=0.1, maximum=1.0, value=0.95, step=0.05, label="Top-P (Nucleus Sampling)"
)
# --- Connect Inputs/Outputs to the Function ---
generate_button.click(
fn=generate_code,
inputs=[
prompt_input,
backend_radio,
file_structure_radio,
max_tokens_slider,
temperature_slider,
top_p_slider,
],
outputs=code_output,
api_name="generate_website_code" # Optional: for API usage
)
# --- Launch the App ---
if __name__ == "__main__":
demo.queue() # Enable queuing for handling multiple users
demo.launch(debug=True) # Set debug=False for production/Spaces |