DS DevShelfHub Projects · AI tools

AI Coding Pair Programmer: Explain, Debug, Convert, and Review Code

Beginner

By DevShelfHub

Paste code or pseudocode and choose an action: step-by-step explanation, bug detection with fixes, pseudocode-to-working-code conversion, or a scored code review—Python, Streamlit, and Groq.

Python Streamlit Groq API

View on GitHub

AI Coding Pair Programmer — explain, debug, convert, and review code

AI Coding Pair Programmer is a beginner-friendly project that gives you four distinct coding assistants in a single Streamlit app. Paste code or pseudocode, pick a language, and choose an action: step-by-step explanation, bug detection with a corrected copy, pseudocode-to-working-code conversion, or a scored code review.

Each action uses a dedicated system prompt that forces structured output — the debugger produces a bug report plus a complete corrected file; the reviewer scores the code 1–10 across quality, performance, and security; the converter outputs runnable code with setup instructions. Nothing is hardcoded to one language: a selectbox lets you switch between 15 languages and the prompt adapts.

Built with Python, Streamlit, and the Groq API, this project is a practical introduction to multi-action prompt design and two-column Streamlit layouts.

Purpose: practice writing separate system prompts for distinct tasks that share the same raw input — a pattern that appears in almost every real AI product.

Typical use: paste a function with an obvious bug, click “Find Bugs & Fix,” copy the corrected snippet back to your editor.

Key ideas you will touch:

  • Multi-action layout — four buttons sharing one code input, each triggering a different system prompt and output format.
  • Language-aware prompting — the language selection is injected into every system message so advice is specific to that ecosystem.
  • Structured output enforcement — each system message names every section heading so the model cannot produce free-form prose.
  • Download generated codest.download_button lets users save converted code without copying from the UI.

Overall flow

User selects language + pastes code or pseudocode
      ↓
Clicks one of four action buttons
      ↓
Explain Code      Find Bugs & Fix     Convert Pseudocode     Code Review
      ↓                  ↓                     ↓                    ↓
Step-by-step       Bug report +          Working code +        Score 1–10 +
walkthrough        fixed code            run instructions      refactored snippet

Demo


Step-by-Step Implementation

  1. Set up the project
    • Install Python 3.10+, create a folder and virtual environment
  2. Install dependencies
    • streamlit, groq, httpx, truststore
  3. Build the two-column layout
    • Left column: language selector, code text area, optional context field, four buttons
    • Right column: output area that starts with an info message until an action is clicked
  4. Write four system prompts
    • Explain: What it does → Step-by-step walkthrough → Key concepts → Gotchas
    • Debug: Bug report → Issues found (with line refs) → Fixed code → Explanation of fixes
    • Convert: Working implementation → How to run → Notes on assumptions
    • Review: Overall score → Quality → Performance → Security → Best practices → Refactored snippet
  5. Inject language into every prompt
    • Include f"You are an expert {lang} developer…" in every system message so suggestions match the ecosystem
  6. Add download for converted code
    • After conversion, offer st.download_button so the user can save the file without manually copying

Code implementation

python

# AI Coding Pair Programmer — Streamlit + Groq
# Save as app.py, add GROQ_API_KEY to .streamlit/secrets.toml, then: streamlit run app.py

import ssl

import httpx
import streamlit as st
import truststore

MAX_CODE_CHARS = 8000

st.set_page_config(page_title="AI Coding Pair Programmer", layout="wide")
st.title("AI Coding Pair Programmer")
st.caption(
    "Paste your code or pseudocode and get step-by-step explanations, bug detection, "
    "fixes, or a fully converted working implementation."
)

_ssl_ctx = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)


@st.cache_resource
def _groq_client():
    import groq

    return groq.Groq(
        api_key=st.secrets["GROQ_API_KEY"],
        http_client=httpx.Client(verify=_ssl_ctx),
    )


_MODEL = "llama-3.3-70b-versatile"

LANGUAGES = [
    "Python", "JavaScript", "TypeScript", "Java", "C++", "C#", "Go",
    "Rust", "Ruby", "PHP", "Swift", "Kotlin", "SQL", "Bash", "Other",
]

# ── Input panel ────────────────────────────────────────────────────────────────
col_input, col_output = st.columns([1, 1], gap="large")

with col_input:
    st.subheader("Your Code")
    lang = st.selectbox("Language", LANGUAGES)
    code_input = st.text_area(
        "Paste code or pseudocode",
        height=350,
        placeholder="def fibonacci(n):\n    # TODO: implement\n    pass",
    )
    context = st.text_input(
        "Additional context (optional)",
        placeholder="e.g. This is part of a web scraper, focus on performance",
    )

    st.divider()
    col_b1, col_b2 = st.columns(2)
    do_explain = col_b1.button("Explain Code", type="primary", use_container_width=True)
    do_debug = col_b2.button("Find Bugs & Fix", use_container_width=True)
    col_b3, col_b4 = st.columns(2)
    do_convert = col_b3.button("Convert Pseudocode", use_container_width=True)
    do_review = col_b4.button("Code Review", use_container_width=True)

with col_output:
    st.subheader("Result")

    if not any([do_explain, do_debug, do_convert, do_review]):
        st.info("Choose an action on the left to get started.")

    if any([do_explain, do_debug, do_convert, do_review]):
        if not code_input.strip():
            st.warning("Please paste some code first.")
            st.stop()

    # ── Explain ────────────────────────────────────────────────────────────────
    if do_explain:
        system_msg = (
            f"You are an expert {lang} developer and patient teacher. "
            "Explain the provided code step-by-step in simple terms. "
            "Use this format:\n\n"
            "## What This Code Does\n[1-2 sentence overview]\n\n"
            "## Step-by-Step Walkthrough\n[number each logical step]\n\n"
            "## Key Concepts Used\n[bullet list of concepts with brief explanations]\n\n"
            "## Potential Gotchas\n[anything a beginner might miss]"
        )
        user_msg = f"Language: {lang}\n\nCode:\n```{lang.lower()}\n{code_input[:MAX_CODE_CHARS]}\n```"
        if context.strip():
            user_msg += f"\n\nContext: {context}"

        with st.spinner("Analyzing code…"):
            try:
                resp = _groq_client().chat.completions.create(
                    model=_MODEL,
                    messages=[
                        {"role": "system", "content": system_msg},
                        {"role": "user", "content": user_msg},
                    ],
                )
                st.markdown(resp.choices[0].message.content)
            except Exception as exc:
                st.error(f"Error: {exc}")

    # ── Debug ──────────────────────────────────────────────────────────────────
    if do_debug:
        system_msg = (
            f"You are a senior {lang} developer specializing in code review and debugging. "
            "Analyze the code for bugs, errors, and issues. Respond in this format:\n\n"
            "## Bug Report\n[Summary of issues found, or 'No bugs found' if clean]\n\n"
            "## Issues Found\n[List each bug with line reference and explanation]\n\n"
            "## Fixed Code\n```\n[Complete corrected code]\n```\n\n"
            "## Explanation of Fixes\n[What was changed and why]"
        )
        user_msg = f"Language: {lang}\n\nCode to debug:\n```{lang.lower()}\n{code_input[:MAX_CODE_CHARS]}\n```"
        if context.strip():
            user_msg += f"\n\nContext: {context}"

        with st.spinner("Debugging code…"):
            try:
                resp = _groq_client().chat.completions.create(
                    model=_MODEL,
                    messages=[
                        {"role": "system", "content": system_msg},
                        {"role": "user", "content": user_msg},
                    ],
                )
                st.markdown(resp.choices[0].message.content)
            except Exception as exc:
                st.error(f"Error: {exc}")

    # ── Convert pseudocode ─────────────────────────────────────────────────────
    if do_convert:
        system_msg = (
            f"You are an expert {lang} developer. Convert the pseudocode or description "
            f"into complete, working, production-quality {lang} code. "
            "Include all necessary imports. Add brief comments only where the logic is non-obvious. "
            "Respond in this format:\n\n"
            f"## {lang} Implementation\n```{lang.lower()}\n[complete working code]\n```\n\n"
            "## How to Run\n[brief setup and run instructions]\n\n"
            "## Notes\n[any assumptions made or alternative approaches]"
        )
        user_msg = f"Target language: {lang}\n\nPseudocode / description:\n{code_input[:MAX_CODE_CHARS]}"
        if context.strip():
            user_msg += f"\n\nAdditional context: {context}"

        with st.spinner("Converting to working code…"):
            try:
                resp = _groq_client().chat.completions.create(
                    model=_MODEL,
                    messages=[
                        {"role": "system", "content": system_msg},
                        {"role": "user", "content": user_msg},
                    ],
                )
                result = resp.choices[0].message.content
                st.markdown(result)
                st.download_button(
                    "Download Code",
                    data=result,
                    file_name=f"generated_code.{lang.lower()[:2]}",
                    mime="text/plain",
                )
            except Exception as exc:
                st.error(f"Error: {exc}")

    # ── Code review ────────────────────────────────────────────────────────────
    if do_review:
        system_msg = (
            f"You are a senior {lang} engineer conducting a thorough code review. "
            "Evaluate the code across multiple dimensions. Use this format:\n\n"
            "## Overall Score: [1-10]/10\n\n"
            "## Code Quality\n[readability, naming, structure]\n\n"
            "## Performance\n[time/space complexity, bottlenecks]\n\n"
            "## Security\n[any security concerns]\n\n"
            "## Best Practices\n[what follows best practices, what doesn't]\n\n"
            "## Refactored Snippet\n```\n[Show a key improvement as a code example]\n```"
        )
        user_msg = f"Language: {lang}\n\nCode:\n```{lang.lower()}\n{code_input[:MAX_CODE_CHARS]}\n```"
        if context.strip():
            user_msg += f"\n\nContext: {context}"

        with st.spinner("Reviewing code…"):
            try:
                resp = _groq_client().chat.completions.create(
                    model=_MODEL,
                    messages=[
                        {"role": "system", "content": system_msg},
                        {"role": "user", "content": user_msg},
                    ],
                )
                st.markdown(resp.choices[0].message.content)
            except Exception as exc:
                st.error(f"Error: {exc}")

Complete code Project link (GitHub)


📖 How the Code Works (Step-by-Step)


1. Two-column UI

  • Input lives in the left column and result in the right, so users can compare code and output without scrolling.
  • The right column starts with st.info() as a placeholder; once any button is clicked and code is validated, the output overwrites it.

2. Shared empty-code guard

  • A single if any([...]): block checks whether any button was clicked, then validates the code area once — preventing four duplicate warning checks.

3. Language-aware prompts

  • Every system message opens with f"You are an expert {lang} developer…" so the model gives language-specific advice instead of generic code comments.
  • The user message wraps the code in a fenced block (```python…```) to hint the model toward syntax-aware reasoning.

4. Structured output sections

  • Each system message names every section heading (e.g., ## Bug Report, ## Fixed Code) so st.markdown() renders consistent headings regardless of what the model chooses to say.

Tips & Production Considerations

Manage context-window limits with large codebases

Most models cap out between 8k and 128k tokens. Instead of pasting an entire repository, isolate the smallest self-contained unit that reproduces the problem—one function, one class, or one module. Include only the imports and type signatures the model needs to reason about the code; strip logging, comments, and unrelated helpers before sending.

Never blindly trust AI-generated code

Treat every suggestion as a junior developer’s first draft. Run the code locally, check edge cases the model did not mention, and confirm that existing tests still pass. Models hallucinate standard-library functions, invent non-existent API parameters, and silently drop error handling—automated tests catch these mistakes before they ship.

Provide multi-file context deliberately

When a bug spans two files—say a caller and a callee—paste both with clear file-path headers (### src/auth.py) so the model can trace the data flow. Without cross-file context the model will guess at function signatures and return plausible but wrong fixes.

Use different prompt patterns for debugging vs. generation

For debugging, lead with the error message and stack trace, then the code—this anchors the model on the failure. For generation, lead with a clear specification of inputs, outputs, and constraints before any sample code. Mixing the two styles in a single prompt often produces unfocused answers.

Review AI suggestions for security implications

Models routinely suggest eval(), unparameterised SQL queries, disabled TLS verification, and overly broad CORS headers because those patterns appear in tutorials. Before merging any AI-generated code, run a quick mental checklist: injection risk, secrets exposure, authentication bypass, and dependency pinning. A five-second review here prevents a production incident later.


AI Coding Pair Programmer FAQ

What is the AI Coding Pair Programmer?

The AI Coding Pair Programmer is a beginner-friendly Streamlit project that gives four code-helper modes—step-by-step explanation, bug detection with fixes, pseudocode-to-code conversion, and a scored code review—using the Groq API.

Is the AI Coding Pair Programmer free to use?

The source code is free and open on GitHub. You only pay for Groq API usage, and most code-helper requests cost a fraction of a cent because the snippets are short.

What tech stack does the AI Coding Pair Programmer use?

Python and Streamlit for the UI, plus the Groq Python client for chat completions. Each mode is driven by a focused system prompt—there is no static analysis library, vector store, or build step required.

How does the scored code review work in the AI Coding Pair Programmer?

The review mode asks the model to evaluate the snippet on readability, correctness, and idiomatic use of the language, then return a numeric score plus a bullet list of specific improvements. Treat the score as a directional signal, not a substitute for tests.

What languages does the AI Coding Pair Programmer support?

Any language the underlying LLM handles—Python, JavaScript, TypeScript, Go, Java, SQL, and shell scripting all work well. Language is detected from the pasted snippet, so you don't need to set it manually.

What are alternatives to the AI Coding Pair Programmer?

For chat-style Q&A over your own notes and READMEs, see the Notes Q&A Bot. For framework-driven debugging of decisions instead of code, see the Mental Model & Learning Coach.

Browse all →