neuralgeekroot's picture
Updated the code for automated Code peer review
b119084
import os
from dotenv import load_dotenv
from langgraph.graph import StateGraph, START, END
from typing_extensions import TypedDict
from enum import Enum
from langchain_groq import ChatGroq
from langchain_core.prompts import PromptTemplate
import streamlit as st
import langsmith
# Load environment variables
load_dotenv()
os.environ['GROQ_API_KEY'] = os.getenv('GROQ_API_KEY')
os.environ['LANGCHAIN_API_KEY'] = os.getenv('LANGCHAIN_API_KEY')
os.environ['LANGSMITH_TRACING_V2'] = 'true'
os.environ['LANGCHAIN_PROJECT_NAME'] = os.getenv('LANGCHAIN_PROJECT_NAME')
class Step(Enum):
INPUT = "input"
REVIEW = "review"
IMPROVISATION = "improvisation"
APPROVAL = "approval"
APPROVED = "approved"
# Define the state structure
class CodingState(TypedDict):
code: str
step: Step
# Define prompts in a configuration dictionary
PROMPTS = {
"coder": "Create a code as per the {code} provided",
"peer": "Review the code provided by the coder: {code}. "
"If correction is needed, return 'improvisation'. "
"If suggestions are needed, return 'approval'. "
"If the code is correct, return 'approved'.",
"manager": "Add necessary docstrings to the following code and approve it: {code}"
}
# Initialize the LLM
llm = ChatGroq(model="qwen-2.5-32b")
# Define the coder node
def coder(state):
"""Based on the input message the code is created by the coder."""
print("Coder Node: Generating code...")
try:
prompt = PromptTemplate.from_template(PROMPTS["coder"])
chain = prompt | llm
result = chain.invoke({'code': state['code']})
print(f"Coder Node: Generated code: {result.content}")
return {'code': result.content, 'step': Step.REVIEW}
except Exception as e:
print(f"Coder Node: Error generating code - {e}")
return {'code': state['code'], 'step': Step.IMPROVISATION}
# Define the peer node
def peer(state):
"""Reviewing the code provided by the coder and determining the next step."""
print("Peer Node: Reviewing code...")
try:
prompt = PromptTemplate.from_template(PROMPTS["peer"])
chain = prompt | llm
result = chain.invoke({'code': state['code']})
# Extract the decision step from result
decision = result.content.strip().lower()
# Validate decision
valid_decisions = [Step.IMPROVISATION.value, Step.APPROVAL.value, Step.APPROVED.value]
if decision not in valid_decisions:
print(f"Peer Node: Invalid decision '{decision}'. Defaulting to 'approval'.")
decision = Step.APPROVAL.value # Default fallback
return {"code": state["code"], "step": Step(decision)}
except Exception as e:
print(f"Peer Node: Error reviewing code - {e}")
return {"code": state["code"], "step": Step.IMPROVISATION}
def manager(state):
"""Add docstrings to the code and approve it."""
print("Manager Node: Adding docstrings and approving code...")
try:
prompt = PromptTemplate.from_template(PROMPTS["manager"])
chain = prompt | llm
result = chain.invoke({'code': state['code']})
print(f"Manager Node: Approved code: {result.content}")
return {'code': result.content, 'step': Step.APPROVED}
except Exception as e:
print(f"Manager Node: Error approving code - {e}")
return {'code': state['code'], 'step': Step.APPROVAL}
# Define the code validity function
def code_validity(state):
"""Determine the next step based on the current state."""
print(f"Code Validity: Current step: {state['step'].value}")
if state['step'] == Step.IMPROVISATION:
return "coder"
elif state['step'] == Step.APPROVAL:
return "manager"
elif state['step'] == Step.APPROVED:
return END
# Build the workflow
builder = StateGraph(CodingState)
# Add nodes
builder.add_node("coder", coder)
builder.add_node("peer", peer)
builder.add_node("manager", manager)
# Add edges
builder.add_edge(START, "coder")
builder.add_edge("coder", "peer")
builder.add_conditional_edges("peer", code_validity, {"coder": "coder", "manager": "manager", END: END})
builder.add_edge("manager", END)
# Compile the workflow
workflow = builder.compile()
# Streamlit frontend
st.title("Automated Code Peer Review")
st.write("Submit your code for an automated peer review using an open-source LLM.")
# Text area for code input
code = st.text_area("Paste your code here:", height=300)
if st.button("Generate Code"):
if code.strip() == "":
st.error("Please paste some code to review.")
else:
with st.spinner("Generating review..."):
try:
# Invoke the workflow
result = workflow.invoke({"code": code, 'step': Step.INPUT})
st.success("Review Generated!")
st.write("### Code Review Feedback")
st.write(result['code'])
except Exception as e:
st.error(f"An error occurred: {e}")