File size: 8,866 Bytes
20ef2f4
 
562244c
83207a8
 
 
 
8f6e00b
463e3b1
 
f3a3f2c
 
 
463e3b1
 
 
f3a3f2c
463e3b1
 
41870ef
 
463e3b1
 
 
fe8f804
38f07ec
f3a3f2c
fe8f804
f3a3f2c
 
fe8f804
 
83207a8
f3a3f2c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fe8f804
f3a3f2c
 
 
fe8f804
f3a3f2c
fe8f804
 
 
 
38f07ec
 
 
fe8f804
f3a3f2c
 
 
 
fe8f804
 
38f07ec
 
c1c0904
38f07ec
 
 
 
 
 
 
 
fe8f804
 
83207a8
f3a3f2c
83207a8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f3a3f2c
7f42b00
f3a3f2c
83207a8
f3a3f2c
 
83207a8
f3a3f2c
 
83207a8
f3a3f2c
 
7f42b00
f3a3f2c
 
83207a8
 
 
 
 
 
 
f3a3f2c
 
 
 
 
 
 
 
 
 
 
83207a8
 
 
 
 
 
 
 
 
 
 
 
 
4cc132c
83207a8
 
 
 
 
 
 
 
 
 
 
 
f3a3f2c
83207a8
f3a3f2c
 
 
fe8f804
 
f3a3f2c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fe8f804
f3a3f2c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83207a8
 
f3a3f2c
 
 
7f42b00
83207a8
4cc132c
83207a8
f3a3f2c
 
 
 
7f42b00
fe8f804
 
 
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# -*- coding: utf-8 -*-
import os
import warnings
import io
import zipfile
import tempfile
from pathlib import Path

import gradio as gr

# ----------------------------------------------------------------------
# Suppress noisy warnings in the Space environment
# ----------------------------------------------------------------------
warnings.filterwarnings("ignore", category=UserWarning)

# ----------------------------------------------------------------------
# Groq client initialization (reads API key from environment)
# ----------------------------------------------------------------------
groq_api_key = os.getenv("GROQ_API_KEY")
groq_client = None

if groq_api_key:
    try:
        from groq import Groq
        groq_client = Groq(api_key=groq_api_key)
    except Exception as e:
        print(f"Failed to import or initialise Groq client: {e}")
        groq_client = None
else:
    print("GROQ_API_KEY not set. The app will work in demo mode with placeholder messages.")

# ----------------------------------------------------------------------
# Supported languages (common set)
# ----------------------------------------------------------------------
SUPPORTED_LANGUAGES = [
    "Python",
    "JavaScript",
    "Java",
    "C++",
    "C#",
    "Go",
    "Ruby",
    "PHP",
    "TypeScript",
    "HTML",
    "CSS",
    "Swift",
    "Kotlin",
    "Rust",
    "Scala",
    "Perl",
    "R",
    "Shell",
]

# ----------------------------------------------------------------------
# Function: improve existing code
# ----------------------------------------------------------------------
def improve_code(original_code: str, language: str) -> str:
    """
    Sends the original code to the LLM and returns an improved version.
    """
    if not original_code.strip():
        return "Please provide some code to improve."

    if not groq_client:
        return "No Groq API key configured. Set the GROQ_API_KEY environment variable."

    prompt = (
        f"You are a senior software engineer. Improve the following {language} code for "
        "readability, efficiency and best practices. Return only the improved code "
        "without any explanation.\n\n"
        f"Original code:\n{original_code}"
    )

    try:
        response = groq_client.chat.completions.create(
            model="llama-3.3-70b-versatile",
            messages=[{"role": "user", "content": prompt}],
            temperature=0.2,
            max_tokens=2000,
        )
        improved = response.choices[0].message.content
        return improved.strip() if improved else "No content returned from Groq."
    except Exception as e:
        return f"Error communicating with Groq: {e}"

# ----------------------------------------------------------------------
# Helper: create a zip file with given files
# ----------------------------------------------------------------------
def _create_zip(file_dict: dict) -> str:
    """
    file_dict: mapping of relative file path -> file content (string)
    Returns the path to the created zip file.
    """
    tmp_dir = tempfile.mkdtemp()
    zip_path = Path(tmp_dir) / "generated_project.zip"

    with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zipf:
        for rel_path, content in file_dict.items():
            zipf.writestr(rel_path, content)

    return str(zip_path)

# ----------------------------------------------------------------------
# Function: generate full web project from an idea
# ----------------------------------------------------------------------
def generate_web_code(idea: str, language: str):
    """
    Generates a complete web project (HTML/CSS/JS or a single-file script)
    based on the user's idea and the selected language.
    Returns a tuple: (preview_text, zip_file_path)
    """
    if not idea.strip():
        return ("Please describe the web idea you want to build.", None)

    if not groq_client:
        return ("No Groq API key configured. Set the GROQ_API_KEY environment variable.", None)

    prompt = (
        f"You are a senior full-stack developer. Based on the following description, "
        f"write a complete, runnable {language} web application. Include all necessary "
        "files (HTML, CSS, JavaScript, or a single script) and comment the code. "
        "Also provide a minimal requirements.txt, a README.md explaining how to run the project, "
        "and a Dockerfile that builds and runs the app. Return the files in the following format:\n"
        "=== filename ===\n"
        "<file content>\n"
        "=== filename ===\n"
        "<file content>\n"
        "Do not add any extra explanation.\n\n"
        f"Description:\n{idea}"
    )

    try:
        response = groq_client.chat.completions.create(
            model="llama-3.3-70b-versatile",
            messages=[{"role": "user", "content": prompt}],
            temperature=0.3,
            max_tokens=4000,
        )
        generated = response.choices[0].message.content
        if not generated:
            return ("No content returned from Groq.", None)

        # Parse the generated sections
        sections = {}
        current_file = None
        for line in generated.splitlines():
            if line.startswith("=== ") and line.endswith(" ==="):
                current_file = line.strip("= ").strip()
                sections[current_file] = ""
            elif current_file:
                sections[current_file] += line + "\n"

        # Determine a preview file (HTML, Python or JS if present)
        preview_key = None
        for key in sections:
            if key.lower().endswith((".html", ".py", ".js")):
                preview_key = key
                break
        preview_text = sections.get(preview_key, "Generated files:\n" + "\n".join(sections.keys()))

        # Create zip with all files
        zip_path = _create_zip(sections)

        return (preview_text, zip_path)

    except Exception as e:
        return (f"Error communicating with Groq: {e}", None)

# ----------------------------------------------------------------------
# Gradio UI
# ----------------------------------------------------------------------
with gr.Blocks() as demo:
    gr.Markdown("# Code Improver & Web Generator")

    with gr.Tabs():
        # --------------------------------------------------------------
        # Tab 1: Improve existing code
        # --------------------------------------------------------------
        with gr.TabItem("Improve Code"):
            with gr.Row():
                with gr.Column():
                    lang_select_improve = gr.Dropdown(
                        choices=SUPPORTED_LANGUAGES,
                        label="Language",
                        value="Python",
                    )
                    code_input = gr.Textbox(
                        label="Original Code",
                        placeholder="Paste your code here",
                        lines=15,
                    )
                with gr.Column():
                    improved_output = gr.Textbox(
                        label="Improved Code",
                        placeholder="Improved code will appear here",
                        lines=15,
                    )
            improve_btn = gr.Button("Improve")
            improve_btn.click(
                fn=improve_code,
                inputs=[code_input, lang_select_improve],
                outputs=improved_output,
            )

        # --------------------------------------------------------------
        # Tab 2: Generate web project from idea
        # --------------------------------------------------------------
        with gr.TabItem("Generate Web"):
            with gr.Row():
                with gr.Column():
                    lang_select_generate = gr.Dropdown(
                        choices=SUPPORTED_LANGUAGES,
                        label="Target Language",
                        value="HTML",
                    )
                    idea_input = gr.Textbox(
                        label="Web Idea",
                        placeholder="Describe the web page or app you want",
                        lines=12,
                    )
                with gr.Column():
                    generated_preview = gr.Textbox(
                        label="Generated Files Preview",
                        placeholder="The generated code will appear here",
                        lines=12,
                    )
                    download_file = gr.File(
                        label="Download Project Zip",
                        type="filepath",
                    )
            generate_btn = gr.Button("Generate")
            generate_btn.click(
                fn=generate_web_code,
                inputs=[idea_input, lang_select_generate],
                outputs=[generated_preview, download_file],
            )

demo.launch()