Sumayyea/CodeExplainerBot
0
1import os2import streamlit as st3from openai import OpenAI4 5# ─────────────── Page setup ───────────────6st.set_page_config(page_title="Code Explainer Bot", page_icon="🤖")7st.title("🤖 Code Explainer Bot (Gemini via OpenRouter)")8st.write("Paste your code below for line-by-line explanations!")9 10# ─────────────── API configuration ───────────────11def get_api_key():12 """Read the key from an environment variable (Hugging Face secret) or Streamlit secrets."""13 key = os.getenv("OPENROUTER_API_KEY")14 if key:15 return key16 try:17 return st.secrets["OPENROUTER_API_KEY"]18 except Exception:19 return None20 21OPENROUTER_API_KEY = get_api_key()22if not OPENROUTER_API_KEY:23 st.error("❌ OPENROUTER_API_KEY not found. Add it to your Space secrets or .streamlit/secrets.toml.")24 st.stop()25 26client = OpenAI(base_url="https://openrouter.ai/api/v1", api_key=OPENROUTER_API_KEY)27MODEL_NAME = "google/gemini-2.5-flash"28EXTRA_HEADERS = {29 "HTTP-Referer": "https://huggingface.co/spaces", # replace with your Space URL30 "X-Title": "Code Explainer Bot",31}32 33# ─────────────── Input ───────────────34code = st.text_area("Enter your code:", height=250, placeholder="Your code here...")35 36def number_lines(code):37 """Add line numbers ourselves so the model's numbering matches the real code."""38 return "\n".join(f"{i:>3} | {line}" for i, line in enumerate(code.splitlines(), 1))39 40def generate_explanation(code):41 """Generate a line-by-line explanation with Gemini through OpenRouter."""42 prompt = f"""Explain this code line by line in plain English for beginners.43Each line is prefixed with its line number and a "|" separator.44 45Rules:46- Use this format: **Line N:** explanation47- Skip blank lines. Group closely related lines if it helps (e.g. **Lines 4-6:**).48- Keep each explanation short and simple.49- End with a 2-3 sentence summary of what the whole program does.50 51Code:52{number_lines(code)}53"""54 try:55 response = client.chat.completions.create(56 model=MODEL_NAME,57 extra_headers=EXTRA_HEADERS,58 messages=[{"role": "user", "content": prompt}],59 max_tokens=2000,60 temperature=0.2,61 )62 return response.choices[0].message.content63 except Exception as e:64 msg = str(e)65 if "401" in msg:66 return "❌ Invalid or expired API key. Check OPENROUTER_API_KEY in your secrets."67 if "402" in msg:68 return "❌ Not enough OpenRouter credits. Add credits or lower max_tokens."69 if "429" in msg:70 return "⏳ Rate limit reached. Please wait a moment and try again."71 return f"❌ Error generating explanation: {msg}"72 73# ─────────────── Explain button ───────────────74if st.button("Explain Code", type="primary"):75 if not code.strip():76 st.error("Please enter some code to explain.")77 else:78 with st.spinner("Analyzing code with Gemini..."):79 explanation = generate_explanation(code)80 81 st.subheader("Code Explanation")82 st.markdown("---")83 st.markdown(explanation)84 st.markdown("---")85 if not explanation.startswith(("❌", "⏳")):86 st.success("Analysis complete!")87 88# ─────────────── Footer ───────────────89st.markdown("---")90st.markdown("*Built with Streamlit, OpenRouter and Google Gemini*")