File size: 4,946 Bytes
aa6f369
 
 
8531a26
aa6f369
 
f5044d7
aa6f369
 
4d76afc
8531a26
aa6f369
4d76afc
 
338b431
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b647320
8941b06
338b431
 
38f5ac1
338b431
 
 
4d76afc
338b431
 
 
 
4d76afc
338b431
8531a26
4d76afc
aa6f369
 
8531a26
aa6f369
4d76afc
8531a26
338b431
38f5ac1
338b431
 
4d76afc
aa6f369
 
 
f5a64b7
aa6f369
 
 
 
b647320
aa6f369
 
 
8531a26
b647320
338b431
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e8a0246
aa6f369
38f5ac1
338b431
4d76afc
8531a26
 
338b431
4d76afc
aa6f369
 
338b431
 
8531a26
4d76afc
aa6f369
338b431
 
e3eee09
8531a26
338b431
 
 
e3eee09
aa6f369
4d76afc
8531a26
338b431
6541c57
f5a64b7
aa6f369
4d76afc
 
338b431
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
import gradio as gr
from huggingface_hub import InferenceClient
import os
import re

API_TOKEN = os.getenv("HF_TOKEN", None)
MODEL = "Qwen/Qwen3-32B"

try:
    print(f"Initializing Inference Client for model: {MODEL}")
    client = InferenceClient(model=MODEL, token=API_TOKEN) if API_TOKEN else InferenceClient(model=MODEL)
except Exception as e:
    raise gr.Error(f"Failed to initialize model client for {MODEL}. Error: {e}. Check HF_TOKEN and model availability.")

# Parse all ```filename.ext\n<code>``` blocks
def parse_code_blocks(response: str) -> list:
    pattern = r"```([^\n]+)\n(.*?)```"
    blocks = re.findall(pattern, response, re.DOTALL)
    files = []
    for filename, code in blocks:
        lang = None
        if filename.endswith(".py"):
            lang = "python"
        elif filename.endswith(".js"):
            lang = "javascript"
        elif filename.endswith(".html"):
            lang = "html"
        elif filename.endswith(".css"):
            lang = "css"
        files.append({
            "filename": filename.strip(),
            "language": lang,
            "code": code.strip()
        })
    return files

def strip_think_tags(text: str) -> str:
    return re.sub(r"<think>.*?</think>", "", text, flags=re.DOTALL)

def extract_thoughts(text: str) -> str:
    matches = re.findall(r"<think>(.*?)</think>", text, flags=re.DOTALL)
    return "\n".join(matches).strip()

system_message = (
    "You are an AI that generates website code using markdown-style code blocks. "
    "Each file should be output as: ```filename.ext\\n<code>\\n``` with no explanation."
)

def generate_code(prompt, backend_choice, max_tokens, temperature, top_p):
    user_prompt = f"USER_PROMPT = {prompt}\nUSER_BACKEND = {backend_choice}"

    messages = [
        {"role": "system", "content": system_message},
        {"role": "user", "content": user_prompt}
    ]

    full_response = ""
    current_thoughts = ""

    # Reset outputs: code file tabs and thinking box
    yield [], gr.update(visible=True, value="")

    try:
        stream = client.chat_completion(
            messages=messages,
            max_tokens=max_tokens,
            stream=True,
            temperature=temperature,
            top_p=top_p,
        )

        for message in stream:
            token = message.choices[0].delta.content
            if isinstance(token, str):
                full_response += token

                # Extract thinking chunks and show them
                thoughts = extract_thoughts(full_response)
                if thoughts != current_thoughts:
                    current_thoughts = thoughts
                    yield gr.update(visible=True, value=current_thoughts)

                cleaned = strip_think_tags(full_response)
                files = parse_code_blocks(cleaned)
                updates = []
                for f in files:
                    updates.append(gr.Code(value=f["code"], label=f["filename"], language=f["language"]))
                yield updates, gr.update(visible=True, value=current_thoughts)

        # Final clean state
        cleaned = strip_think_tags(full_response)
        files = parse_code_blocks(cleaned)
        final_updates = [gr.Code(value=f["code"], label=f["filename"], language=f["language"]) for f in files]
        yield final_updates, gr.update(visible=False)

    except Exception as e:
        print(f"ERROR during code generation stream: {e}")
        yield [gr.Markdown(f"**Error:** {e}")], gr.update(visible=False)

with gr.Blocks(css=".gradio-container { max-width: 90% !important; }") as demo:
    gr.Markdown("# ✨ Website Code Generator ✨")
    gr.Markdown("Describe the website you want. Multiple file tabs will be created automatically.")

    with gr.Row():
        with gr.Column(scale=2):
            prompt_input = gr.Textbox(label="Website Description", lines=6)
            backend_radio = gr.Radio(["Static", "Flask", "Node.js"], label="Backend Context", value="Static")
            generate_button = gr.Button("✨ Generate Website Code", variant="primary")

        with gr.Column(scale=3):
            file_outputs = gr.Group(update=lambda: [])
            thinking_box = gr.Textbox(label="Model is thinking...", visible=False, interactive=False)

    with gr.Accordion("Advanced Settings", open=False):
        max_tokens_slider = gr.Slider(512, 4096, value=3072, step=256, label="Max New Tokens")
        temperature_slider = gr.Slider(0.1, 1.2, value=0.7, step=0.1, label="Temperature")
        top_p_slider = gr.Slider(0.1, 1.0, value=0.9, step=0.05, label="Top-P")

    generate_button.click(
        fn=generate_code,
        inputs=[prompt_input, backend_radio, max_tokens_slider, temperature_slider, top_p_slider],
        outputs=[file_outputs, thinking_box],
    )

if __name__ == "__main__":
    if not API_TOKEN:
        print("Warning: HF_TOKEN environment variable not set. Using anonymous access.")
    demo.queue().launch()