ashritaa-chinnari123's picture
Upload 8 files
38b27cd verified
Raw
History Blame Contribute Delete
7.32 kB
"""
Streamlit UI for the Code Explainer + Bug Fixer.
Run:
pip install streamlit
streamlit run streamlit_app.py
"""
import streamlit as st
import torch
from transformers import AutoTokenizer, T5ForConditionalGeneration
from line_explainer import explain_line_by_line
from bug_checker import detect_bugs, check_style
st.set_page_config(page_title="Code Explainer & Bug Fixer", page_icon="πŸ› οΈ", layout="wide")
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
EXPLAIN_MODEL_NAME = "Salesforce/codet5-base-multi-sum"
@st.cache_resource(show_spinner="Loading explanation model... (first run only, this takes a minute)")
def load_explain_model():
explain_tokenizer = AutoTokenizer.from_pretrained(EXPLAIN_MODEL_NAME, use_fast=False)
explain_model = T5ForConditionalGeneration.from_pretrained(EXPLAIN_MODEL_NAME).to(DEVICE)
return explain_tokenizer, explain_model
explain_tokenizer, explain_model = load_explain_model()
def explain_code(code: str) -> str:
inputs = explain_tokenizer(code, return_tensors="pt", truncation=True, max_length=512).to(DEVICE)
output_ids = explain_model.generate(**inputs, max_length=64, num_beams=5, early_stopping=True)
return explain_tokenizer.decode(output_ids[0], skip_special_tokens=True)
# --------------------------- Language config ---------------------------
# codet5-base-multi-sum was trained on 6 languages for the EXPLANATION step.
# line_explainer.py and bug_checker.py are Python-only (built on Python's ast
# module), so those two features are gated to Python only below.
LANGUAGE_OPTIONS = {
"Python": {"extensions": ["py"], "st_lang": "python", "supports_static_analysis": True},
"Java": {"extensions": ["java"], "st_lang": "java", "supports_static_analysis": False},
"JavaScript": {"extensions": ["js"], "st_lang": "javascript", "supports_static_analysis": False},
"PHP": {"extensions": ["php"], "st_lang": "php", "supports_static_analysis": False},
"Ruby": {"extensions": ["rb"], "st_lang": "ruby", "supports_static_analysis": False},
"Go": {"extensions": ["go"], "st_lang": "go", "supports_static_analysis": False},
}
# --------------------------- UI ---------------------------
st.title("πŸ› οΈ Code Explainer & Bug Checker")
st.caption("Paste code or upload a file. It will be explained in plain English and checked for bugs/style issues.")
col_lang, col_upload = st.columns([1, 2])
with col_lang:
language = st.selectbox("Language:", list(LANGUAGE_OPTIONS.keys()))
with col_upload:
all_extensions = [ext for cfg in LANGUAGE_OPTIONS.values() for ext in cfg["extensions"]] + ["txt"]
uploaded_file = st.file_uploader("Or upload a code file:", type=all_extensions)
lang_cfg = LANGUAGE_OPTIONS[language]
if not lang_cfg["supports_static_analysis"]:
st.info(
f"Line-by-line breakdown and bug/style checking currently support Python only. "
f"For {language}, you'll get the AI explanation only."
)
default_code = """def add_numbers(a, b)
return a + b"""
if uploaded_file is not None:
file_bytes = uploaded_file.read()
try:
starter_code = file_bytes.decode("utf-8")
except UnicodeDecodeError:
st.error("Couldn't decode the uploaded file as text (UTF-8). Please upload a plain text code file.")
starter_code = default_code
else:
starter_code = default_code
code_input = st.text_area("Your code:", value=starter_code, height=250, placeholder="Paste your code here...")
col1, col2 = st.columns(2)
with col1:
run_explain = st.button("πŸ” Analyze Code", type="primary", use_container_width=True)
with col2:
clear = st.button("πŸ—‘οΈ Clear", use_container_width=True)
if clear:
st.rerun()
if run_explain:
if not code_input.strip():
st.warning("Please paste some code first.")
else:
report_sections = [] # collects (title, text) for the downloadable report
with st.spinner("Analyzing..."):
explanation = explain_code(code_input)
st.subheader("πŸ“ Explanation")
st.info(explanation)
report_sections.append(("Explanation", explanation))
if lang_cfg["supports_static_analysis"]:
st.subheader("πŸ“‹ Line-by-line breakdown")
ok, breakdown = explain_line_by_line(code_input)
if ok:
breakdown_text = "\n".join(breakdown)
st.code(breakdown_text, language="text")
report_sections.append(("Line-by-line breakdown", breakdown_text))
else:
st.warning(breakdown)
report_sections.append(("Line-by-line breakdown", breakdown))
bug_result = detect_bugs(code_input)
style_issues = check_style(code_input) if bug_result["syntax_valid"] else []
st.subheader("πŸ› Bug Check (static analysis)")
st.caption("Checks for real errors: syntax mistakes, undefined variables, unused imports. Based on Python's own parser + pyflakes β€” deterministic, not a guess.")
if not bug_result["syntax_valid"]:
st.error(bug_result["syntax_error"])
bug_report_text = bug_result["syntax_error"]
elif bug_result["has_bug"]:
st.error(bug_result["summary"])
for issue in bug_result["static_issues"]:
st.write(f"- {issue}")
bug_report_text = bug_result["summary"] + "\n" + "\n".join(f"- {i}" for i in bug_result["static_issues"])
else:
st.success(bug_result["summary"])
bug_report_text = bug_result["summary"]
report_sections.append(("Bug Check", bug_report_text))
st.subheader("🎨 Style Check (PEP8)")
st.caption("Checks formatting conventions (line length, spacing, naming) β€” not correctness. Code with style warnings can still run perfectly fine; this just flags deviations from Python's standard style guide.")
if style_issues:
st.warning(f"{len(style_issues)} style issue(s) found.")
for issue in style_issues:
st.write(f"- {issue}")
style_report_text = "\n".join(f"- {i}" for i in style_issues)
else:
st.success("No PEP8 style issues found.")
style_report_text = "No PEP8 style issues found."
report_sections.append(("Style Check (PEP8)", style_report_text))
# --------------------------- Build downloadable report ---------------------------
report_lines = [f"# Code Analysis Report\n", f"**Language:** {language}\n", "## Original Code\n", f"```{lang_cfg['st_lang']}\n{code_input}\n```\n"]
for title, text in report_sections:
report_lines.append(f"## {title}\n")
report_lines.append(f"{text}\n")
report_text = "\n".join(report_lines)
st.divider()
st.download_button(
label="⬇️ Download Full Report (.md)",
data=report_text,
file_name="code_analysis_report.md",
mime="text/markdown",
)
st.divider()
st.caption(
"Bug detection uses real static analysis (Python's ast parser + pyflakes), "
"so results are accurate and deterministic β€” not a model's guess."
)