Sanjoy Ghosh
Update app.py to provide separate review feedback and examples
8c4cf66
import os
import json
import streamlit as st
from streamlit_ace import st_ace
from typing_extensions import TypedDict
from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage
# ------------------------------------------
# 1. Define a TypedDict for review state
# ------------------------------------------
class CodeReviewState(TypedDict):
code_content: str
review_outcome: str
revised_code: str
similar_examples: str
# ------------------------------------------
# 2. LLM Classes for Analyzing & Proposing
# ------------------------------------------
class LLMAnalyzer:
"""Analyzes Python code snippet: 'Approved' or 'NeedsRevision'."""
def __init__(self, llm: ChatOpenAI) -> None:
self.llm = llm
def analyze(self, code_content: str) -> str:
prompt_text = f"""You are a senior Python reviewer.
Analyze the following code:
{code_content}
Respond with:
- "Approved" if the code is correct or good enough.
- "NeedsRevision" if changes or improvements are needed.
"""
# Use 'generate()' with a HumanMessage.
response = self.llm.generate([[HumanMessage(content=prompt_text)]])
outcome_text = response.generations[0][0].text.strip()
return outcome_text
class LLMProposer:
"""Proposes an improved version of the code."""
def __init__(self, llm: ChatOpenAI) -> None:
self.llm = llm
def propose(self, code_content: str) -> str:
prompt_text = f"""You are a senior Python reviewer.
Review the following code and provide an improved version, with any necessary fixes or best practices:
{code_content}
"""
response = self.llm.generate([[HumanMessage(content=prompt_text)]])
return response.generations[0][0].text.strip()
class LLMExampleGenerator:
"""Generates similar example snippets for educational purposes."""
def __init__(self, llm: ChatOpenAI) -> None:
self.llm = llm
def generate_examples(self, code_content: str) -> str:
prompt_text = f"""You are a senior Python mentor.
The user learned this Python snippet:
{code_content}
Now provide a few similar Python code examples or patterns with short explanations.
Show best practices and different variations so the user can learn and improve.
"""
response = self.llm.generate([[HumanMessage(content=prompt_text)]])
return response.generations[0][0].text.strip()
# ------------------------------------------
# 3. Streamlit Page Layout
# ------------------------------------------
st.set_page_config(page_title="Code Reviewer with AI", layout="wide")
st.title("Code Reviewer with suggested Examples")
# ------------------------------------------
# 4. Check for OpenAI API Key
# ------------------------------------------
openai_api_key = os.getenv("OPENAI_API_KEY")
if not openai_api_key:
st.error("Error: OPENAI_API_KEY not set. Please provide a valid API key.")
st.stop()
# ------------------------------------------
# 5. Initialize ChatOpenAI
# ------------------------------------------
# Make sure to have a compatible version: langchain>=0.0.300, openai>=1.0.0
llm = ChatOpenAI(
openai_api_key=openai_api_key,
model_name="gpt-4o-mini",
temperature=0.7
)
analyzer = LLMAnalyzer(llm)
proposer = LLMProposer(llm)
example_gen = LLMExampleGenerator(llm)
# ------------------------------------------
# 6. Initialize Session State
# ------------------------------------------
if "review_state" not in st.session_state:
st.session_state["review_state"] = CodeReviewState(
code_content="",
review_outcome="",
revised_code="",
similar_examples=""
)
# ------------------------------------------
# 7. ACE Editor for User Code
# ------------------------------------------
st.write("### Enter or modify your Python code:")
code_input = st_ace(
language="python",
#theme="monokai",
auto_update=True,
key="ace-editor",
height=250,
#value="def greet(name):\n print(f'Hello, {name}!')"
)
# ------------------------------------------
# 8. On Submit: Analyze, Propose (if needed), & Provide Examples
# ------------------------------------------
if st.button("Submit for Review"):
if not code_input.strip():
st.error("Please enter some code.")
else:
outcome = analyzer.analyze(code_input)
revised_snippet = ""
if outcome == "NeedsRevision":
revised_snippet = proposer.propose(code_input)
examples = example_gen.generate_examples(code_input)
# Update session state
st.session_state["review_state"]["code_content"] = code_input
st.session_state["review_state"]["review_outcome"] = outcome
st.session_state["review_state"]["revised_code"] = revised_snippet
st.session_state["review_state"]["similar_examples"] = examples
# ------------------------------------------
# 9. Display Output
# ------------------------------------------
review_state = st.session_state["review_state"]
if review_state["review_outcome"]:
if review_state["review_outcome"] == "Approved":
st.success("Your code is approved! Great job.")
else:
st.warning("Your code needs some revision based on best practices.")
st.markdown("**Proposed Fixes / Improved Version:**")
st.code(review_state["revised_code"], language="python")
st.markdown("---")
st.markdown("### Similar Examples to Learn & Improve")
st.write(review_state["similar_examples"])