Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import os | |
| from groq import Groq | |
| SYSTEM_PROMPT = """You are a professional coding teacher explaining code to a complete beginner. | |
| When given code, respond ONLY in this exact HTML structure (no markdown, no backticks): | |
| <div class="section" id="simple"> | |
| <h2>π§ Simple Explanation</h2> | |
| <ul> | |
| [3-5 bullet points explaining what the code does in simple words] | |
| </ul> | |
| </div> | |
| <div class="section" id="steps"> | |
| <h2>π£ Step-by-Step Working</h2> | |
| <ol> | |
| [numbered steps of how the code runs] | |
| </ol> | |
| </div> | |
| <div class="section" id="variables"> | |
| <h2>π¦ Variables & Functions</h2> | |
| <ul> | |
| [explain each variable and function simply] | |
| </ul> | |
| </div> | |
| <div class="section" id="logic"> | |
| <h2>π Logic (Loops & Conditions)</h2> | |
| <p>[explain any loops, if/else, conditions in very simple words]</p> | |
| </div> | |
| <div class="section" id="analogy"> | |
| <h2>π Real-Life Analogy</h2> | |
| <p>[a simple real-world comparison that a child could understand]</p> | |
| </div> | |
| <div class="section" id="output"> | |
| <h2>π₯οΈ Output</h2> | |
| <div class="output-box">[what the code prints/returns]</div> | |
| </div> | |
| <div class="section" id="errors"> | |
| <h2>π Errors Found & Fixed</h2> | |
| <p>[mention any bugs or if code is correct]</p> | |
| </div> | |
| <div class="section" id="improvements"> | |
| <h2>β¨ Suggested Improvements</h2> | |
| <ul> | |
| [2-3 improvement tips] | |
| </ul> | |
| </div> | |
| <div class="section" id="complexity"> | |
| <h2>β±οΈ Time Complexity</h2> | |
| <p>[explain time complexity in very simple words like "this runs once" or "this loops N times"]</p> | |
| </div> | |
| <div class="section" id="summary"> | |
| <h2>π Short Summary</h2> | |
| <p>[1-2 sentence summary of what the code does]</p> | |
| </div> | |
| Use very easy English. No technical jargon. Keep it short but clear.""" | |
| CSS = """ | |
| @import url('https://fonts.googleapis.com/css2?family=Syne:wght@400;600;700;800&family=DM+Mono:wght@400;500&family=DM+Sans:wght@300;400;500&display=swap'); | |
| :root { | |
| --bg: #0a0a0f; | |
| --surface: #12121a; | |
| --surface2: #1e1e2e; | |
| --border: #3a3a5c; | |
| --accent: #a89fff; | |
| --accent2: #ff8ec4; | |
| --accent3: #6affb8; | |
| --text: #e8e8f0; | |
| --text-muted: #aaaacc; | |
| --glow: 0 0 30px rgba(168, 159, 255, 0.2); | |
| } | |
| * { box-sizing: border-box; margin: 0; padding: 0; } | |
| body, .gradio-container { | |
| background: var(--bg) !important; | |
| font-family: 'DM Sans', sans-serif !important; | |
| color: var(--text) !important; | |
| min-height: 100vh; | |
| } | |
| .gradio-container { | |
| max-width: 1100px !important; | |
| margin: 0 auto !important; | |
| padding: 2rem !important; | |
| } | |
| /* Header */ | |
| .header-block { | |
| text-align: center; | |
| padding: 3rem 0 2rem; | |
| position: relative; | |
| } | |
| .header-block::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; left: 50%; | |
| transform: translateX(-50%); | |
| width: 300px; height: 300px; | |
| background: radial-gradient(circle, rgba(124,106,255,0.12) 0%, transparent 70%); | |
| pointer-events: none; | |
| } | |
| .app-title { | |
| font-family: 'Syne', sans-serif !important; | |
| font-size: 3rem !important; | |
| font-weight: 800 !important; | |
| background: linear-gradient(135deg, #7c6aff, #ff6a9e, #6affb8) !important; | |
| -webkit-background-clip: text !important; | |
| -webkit-text-fill-color: transparent !important; | |
| background-clip: text !important; | |
| line-height: 1.1 !important; | |
| letter-spacing: -1px !important; | |
| } | |
| .app-subtitle { | |
| color: var(--text-muted) !important; | |
| font-size: 1.05rem !important; | |
| margin-top: 0.6rem !important; | |
| font-weight: 300 !important; | |
| } | |
| /* Input area */ | |
| .code-input textarea { | |
| background: var(--surface) !important; | |
| border: 1.5px solid var(--border) !important; | |
| border-radius: 16px !important; | |
| color: var(--text) !important; | |
| font-family: 'DM Mono', monospace !important; | |
| font-size: 0.9rem !important; | |
| padding: 1.2rem !important; | |
| transition: border-color 0.2s, box-shadow 0.2s !important; | |
| resize: vertical !important; | |
| } | |
| .code-input textarea:focus { | |
| border-color: var(--accent) !important; | |
| box-shadow: var(--glow) !important; | |
| outline: none !important; | |
| } | |
| .code-input label { | |
| font-family: 'Syne', sans-serif !important; | |
| font-weight: 600 !important; | |
| color: var(--text) !important; | |
| font-size: 0.95rem !important; | |
| letter-spacing: 0.5px !important; | |
| } | |
| /* Button */ | |
| button.primary { | |
| background: linear-gradient(135deg, var(--accent), var(--accent2)) !important; | |
| border: none !important; | |
| border-radius: 12px !important; | |
| color: white !important; | |
| font-family: 'Syne', sans-serif !important; | |
| font-size: 1rem !important; | |
| font-weight: 700 !important; | |
| padding: 0.85rem 2.5rem !important; | |
| cursor: pointer !important; | |
| transition: transform 0.15s, box-shadow 0.15s !important; | |
| letter-spacing: 0.5px !important; | |
| } | |
| button.primary:hover { | |
| transform: translateY(-2px) !important; | |
| box-shadow: 0 8px 25px rgba(124,106,255,0.35) !important; | |
| } | |
| /* Output HTML */ | |
| .output-html { | |
| background: var(--surface) !important; | |
| border: 1.5px solid var(--border) !important; | |
| border-radius: 16px !important; | |
| padding: 1.5rem !important; | |
| } | |
| /* Section cards rendered inside HTML output */ | |
| .section { | |
| background: var(--surface2); | |
| border: 1px solid var(--border); | |
| border-radius: 14px; | |
| padding: 1.4rem 1.6rem; | |
| margin-bottom: 1rem; | |
| transition: border-color 0.2s; | |
| } | |
| .section:hover { border-color: var(--accent); } | |
| .section h2 { | |
| font-family: 'Syne', sans-serif; | |
| font-size: 1rem; | |
| font-weight: 700; | |
| color: var(--accent); | |
| margin-bottom: 0.8rem; | |
| letter-spacing: 0.3px; | |
| } | |
| .section ul, .section ol { | |
| padding-left: 1.4rem; | |
| color: #e8e8f0; | |
| line-height: 1.8; | |
| font-size: 0.93rem; | |
| } | |
| .section li { | |
| color: #e8e8f0 !important; | |
| margin-bottom: 0.3rem; | |
| } | |
| .section p { | |
| color: #e8e8f0; | |
| line-height: 1.7; | |
| font-size: 0.93rem; | |
| } | |
| .output-box { | |
| background: #0d0d15; | |
| border: 1px solid var(--border); | |
| border-left: 3px solid var(--accent3); | |
| border-radius: 8px; | |
| padding: 0.8rem 1rem; | |
| font-family: 'DM Mono', monospace; | |
| font-size: 0.88rem; | |
| color: var(--accent3); | |
| white-space: pre-wrap; | |
| } | |
| #analogy h2 { color: var(--accent3) !important; } | |
| #output h2 { color: var(--accent3) !important; } | |
| #summary h2 { color: var(--accent2) !important; } | |
| #errors h2 { color: #ff9966 !important; } | |
| /* Loading */ | |
| .generating { | |
| text-align: center; | |
| color: var(--text-muted); | |
| padding: 2rem; | |
| font-family: 'Syne', sans-serif; | |
| } | |
| /* Footer */ | |
| footer { display: none !important; } | |
| """ | |
| PLACEHOLDER = '''# Paste your code here! Example: | |
| def greet(name): | |
| for i in range(3): | |
| print("Hello, " + name + "!") | |
| greet("Alice")''' | |
| def explain_code(code): | |
| if not code.strip(): | |
| return "<p style='color:#8888aa; padding:1rem;'>β οΈ Please paste some code first!</p>" | |
| try: | |
| api_key = os.environ.get("GROQ_API_KEY") | |
| if not api_key: | |
| return "<p style='color:#ff6a6a;padding:1rem;'>β Error: GROQ_API_KEY secret is missing! Go to Space Settings β Variables and Secrets β Add GROQ_API_KEY</p>" | |
| client = Groq(api_key=api_key) | |
| response = client.chat.completions.create( | |
| model="llama-3.3-70b-versatile", | |
| max_tokens=2000, | |
| messages=[ | |
| {"role": "system", "content": SYSTEM_PROMPT}, | |
| {"role": "user", "content": f"Explain this code:\n\n{code}"} | |
| ] | |
| ) | |
| result = response.choices[0].message.content | |
| # Wrap in styled container | |
| return f""" | |
| <style> | |
| :root {{ | |
| --bg:#0a0a0f;--surface:#12121a;--surface2:#1e1e2e; | |
| --border:#3a3a5c;--accent:#a89fff;--accent2:#ff8ec4; | |
| --accent3:#6affb8;--text:#e8e8f0;--text-muted:#aaaacc; | |
| }} | |
| @import url('https://fonts.googleapis.com/css2?family=Syne:wght@700&family=DM+Mono&family=DM+Sans:wght@300;400&display=swap'); | |
| .section{{background:var(--surface2);border:1px solid var(--border);border-radius:14px;padding:1.4rem 1.6rem;margin-bottom:1rem;}} | |
| .section:hover{{border-color:var(--accent);}} | |
| .section h2{{font-family:'Syne',sans-serif;font-size:1rem;font-weight:700;color:#a89fff;margin-bottom:0.8rem;}} | |
| .section ul,.section ol{{padding-left:1.4rem;color:#e8e8f0;line-height:1.8;font-size:0.93rem;}} | |
| .section li{{color:#e8e8f0 !important;margin-bottom:0.3rem;}} | |
| .section p{{color:#e8e8f0;line-height:1.7;font-size:0.93rem;}} | |
| .output-box{{background:#0d0d15;border:1px solid var(--border);border-left:3px solid var(--accent3);border-radius:8px;padding:0.8rem 1rem;font-family:'DM Mono',monospace;font-size:0.88rem;color:var(--accent3);white-space:pre-wrap;}} | |
| #analogy h2,#output h2{{color:var(--accent3)!important;}} | |
| #summary h2{{color:var(--accent2)!important;}} | |
| #errors h2{{color:#ff9966!important;}} | |
| </style> | |
| {result} | |
| """ | |
| except Exception as e: | |
| return f"<p style='color:#ff6a6a;padding:1rem;'>β Error: {str(e)}</p>" | |
| with gr.Blocks(css=CSS, title="CodeLens β AI Code Explainer") as demo: | |
| gr.HTML(""" | |
| <div class="header-block"> | |
| <h1 class="app-title">CodeLens</h1> | |
| <p class="app-subtitle">Paste any code β Get a beginner-friendly explanation instantly β¨</p> | |
| </div> | |
| """) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| code_input = gr.Code( | |
| label="π Paste Your Code Here", | |
| language="python", | |
| lines=14, | |
| elem_classes=["code-input"], | |
| value=PLACEHOLDER | |
| ) | |
| explain_btn = gr.Button( | |
| "π Explain This Code", | |
| variant="primary", | |
| size="lg" | |
| ) | |
| output = gr.HTML( | |
| label="", | |
| elem_classes=["output-html"] | |
| ) | |
| explain_btn.click( | |
| fn=explain_code, | |
| inputs=[code_input], | |
| outputs=[output] | |
| ) | |
| gr.HTML(""" | |
| <div style="text-align:center; padding:1.5rem 0 0.5rem; color:#8888aa; font-size:0.82rem; font-family:'DM Sans',sans-serif;"> | |
| Built with β€οΈ using Groq AI Β· CodeLens for Beginners | |
| </div> | |
| """) | |
| if __name__ == "__main__": | |
| demo.launch() |