sherlock-ob / app.py
eva1267890's picture
Update app.py
be8e488 verified
Raw
History Blame Contribute Delete
13.2 kB
from huggingface_hub import InferenceClient
from sentence_transformers import SentenceTransformer
import gradio as gr
import numpy as np
import os
hf_token = os.getenv("HF_TOKEN")
encoder_model = SentenceTransformer("all-MiniLM-L6-v2")
client = InferenceClient("meta-llama/Meta-Llama-3-8B-Instruct", token=hf_token)
# Knowledge Base -- all thypes of errors and their description.
knowledge_base = [
{
"error_type": "IndexError: list index out of range",
"context": "Occurs when trying to access an index that doesn't exist in a list. Remember Python and many other programming languages lists start at index 0. If a list has 3 items, valid indices are 0, 1, and 2."
},
{
"error_type": "TypeError: 'int' object is not iterable",
"context": "Occurs when trying to loop through or unpack an integer instead of a collection like a list or dictionary. Check if you passed a number to a for loop or any other type of loop."
},
{
"error_type": "KeyError",
"context": "Occurs when trying to access a dictionary key that does not exist. Check for typos or use the .get() method to handle missing keys safely."
},
{
"error_type": "IndentationError: unexpected indent",
"context": "Python and many other programming languages relies heavily on whitespace. Some languages like C++ and Javascript may rely on curly braces. Ensure you are consistently using either 4 spaces or 1 tab inside loops and functions."
},
{
"error_type": "NameError: name is not defined",
"context": "Occurs when using a variable or function name that Python or any other programming language doesn't recognize. Common causes: a typo, or calling it before it is defined."
},
{
"error_type": "TypeError: unsupported operand type(s)",
"context": "Occurs when performing an operation between incompatible data types, such as adding a string and an integer. Check the types of the variables involved."
},
{
"error_type": "ValueError",
"context": "Occurs when a function receives the correct type of argument but an invalid value. Example: converting 'hello' to an integer using int()."
},
{
"error_type": "AttributeError",
"context": "Occurs when trying to access a method or attribute that an object does not have. Check for typos or whether the object is the expected type."
},
{
"error_type": "ZeroDivisionError",
"context": "Occurs when attempting to divide a number by zero. Ensure the denominator is not zero before performing division."
},
{
"error_type": "SyntaxError",
"context": "Occurs when Python encounters invalid code structure. Common causes include missing colons, parentheses, quotes, or incorrect statement formatting."
},
{
"error_type": "ModuleNotFoundError",
"context": "Occurs when Python cannot find the module being imported. Verify the module is installed and the import statement is correct."
},
{
"error_type": "ImportError",
"context": "Occurs when Python finds a module but cannot import a specific object from it. Check spelling and module contents."
},
{
"error_type": "FileNotFoundError",
"context": "Occurs when trying to open or access a file that does not exist at the specified path. Verify the filename and location."
},
{
"error_type": "PermissionError",
"context": "Occurs when the program does not have permission to access a file, folder, or system resource. Check file permissions and access rights."
},
{
"error_type": "UnboundLocalError",
"context": "Occurs when a local variable is referenced before it has been assigned a value within a function."
},
{
"error_type": "RecursionError",
"context": "Occurs when a function calls itself too many times without reaching a stopping condition. Verify the base case of recursive functions."
},
{
"error_type": "MemoryError",
"context": "Occurs when the program runs out of available memory. This often happens with very large datasets or infinite data structures."
},
{
"error_type": "AssertionError",
"context": "Occurs when an assert statement evaluates to False. Check whether the expected condition is actually true."
},
{
"error_type": "RuntimeError",
"context": "A generic error indicating something unexpected happened during execution that doesn't fit a more specific exception type."
},
{
"error_type": "KeyboardInterrupt",
"context": "Occurs when the user manually stops the program, usually by pressing Ctrl+C."
},
{
"error_type": "EOFError",
"context": "Occurs when input() reaches the end of input unexpectedly. Common in online judges or automated testing environments."
},
{
"error_type": "Wrong Data Type",
"context": "The program runs but produces incorrect results because a variable contains a different type than expected."
}
]
kb_contexts = []
kb_embeddings = []
# Encoded context for the code error in the knowledge base
for item in knowledge_base:
context_text = item["context"]
kb_contexts.append(context_text)
embedding = encoder_model.encode(context_text)
kb_embeddings.append(embedding)
kb_embeddings = np.array(kb_embeddings)
#Used to find cosine similarity and used AI to look at what the np.argmax and np.linalg.norm() and the general logic behind implementing it in the chat.
def get_relevant_context(user_message):
user_embedding = encoder_model.encode(user_message)
similarities = np.dot(kb_embeddings, user_embedding) / (
np.linalg.norm(kb_embeddings, axis=1) * np.linalg.norm(user_embedding)
)
best_idx = np.argmax(similarities)
if similarities[best_idx] > 0.3:
return kb_contexts[best_idx]
return "No specific database match found. Use general debugging wisdom to prompt the user."
def response(message, history):
retrieved_context = get_relevant_context(message)
system_prompt = (
"You are 'The Sherlock of Bugs', an interactive, clever, and supportive debugging mentor.\n\n"
"YOUR RULES:\n"
"1. When the user presents an error message, DO NOT give away the direct solution or fix immediately.\n"
"2. Instead, use the provided Context to give them architectural clues or structural hints. Ask them how they think they should fix it, and encourage them to try writing a solution.\n"
"3. If the user responds with a fix or an explanation, evaluate it. Tell them clearly if they are correct or incorrect.\n"
"4. If they are correct, praise them and summarize the clean code. If they are struggling or incorrect, guide them closer or finally reveal the exact, elegant solution.\n\n"
f"RELEVANT BACKGROUND CONTEXT FOR THIS CONVERSATION:\n{retrieved_context}"
)
messages = [{"role": "system", "content": system_prompt}]
for turn in history:
messages.append({"role": turn.get("role", "user"), "content": turn.get("content", "")})
messages.append({"role": "user", "content": message})
res = client.chat_completion(messages, max_tokens=1000)
return res.choices[0].message.content.strip()
custom_css = """
body, .gradio-container {
background-color: #0b001a !important;
color: #ff77ff !important;
font-family: 'Segoe UI', system-ui, sans-serif !important;
}
.gradio-container {
border: 2px solid #ff007f !important;
border-radius: 16px !important;
box-shadow: 0 0 35px rgba(255, 0, 127, 0.25), inset 0 0 15px rgba(112, 0, 255, 0.15) !important;
padding: 25px !important;
background: radial-gradient(circle at center, #1a0033 0%, #060010 100%) !important;
}
/* Glowing Header Board -- Used AI for this part to make the image expanded */
.logo-header {
text-align: center;
border: 2px dashed #ff007f;
background: rgba(255, 0, 127, 0.03);
padding: 0px !important; /* Forces padding to 0 so the image touches the border */
border-radius: 8px;
margin-bottom: 25px;
box-shadow: 0 0 20px rgba(255, 0, 127, 0.15);
animation: pulse-glow 4s infinite alternate;
overflow: hidden; /* Keeps the image corners tucked within the border-radius */
}
/* Force Gradio's internal layout divs to expand fully */
.logo-header > div, .logo-header .image-container {
width: 100% !important;
height: 100% !important;
}
/* Forces the banner image to stretch horizontally across the box */
.logo-header img {
width: 100% !important;
height: auto !important;
object-fit: cover !important; /* Scales smoothly without losing proportions */
display: block;
}
/* Chatbot Window Customization */
.chatbot {
border: 1px solid #7000ff !important;
background: rgba(15, 0, 30, 0.6) !important;
}
/* Styling Chat Bubbles Natively */
.message.user {
background-color: #3c006b !important;
color: #ffffff !important;
border: 1px solid #ff007f !important;
box-shadow: 0 0 10px rgba(255, 0, 127, 0.2);
}
.message.bot {
background-color: #16002c !important;
color: #ff77ff !important;
border: 1px solid #7000ff !important;
box-shadow: 0 0 10px rgba(112, 0, 255, 0.2);
}
/* Buttons Styling */
.cyber-btn {
background: #ff007f !important;
color: #ffffff !important;
font-weight: bold !important;
border: none !important;
border-radius: 6px !important;
box-shadow: 0 0 15px rgba(255, 0, 127, 0.4) !important;
cursor: pointer;
transition: all 0.25s ease !important;
text-transform: uppercase;
letter-spacing: 1px;
}
.cyber-btn:hover {
background: #7000ff !important;
box-shadow: 0 0 25px #7000ff !important;
}
.secondary-btn {
background-color: rgba(112, 0, 255, 0.1) !important;
color: #ff77ff !important;
border: 1px solid #7000ff !important;
border-radius: 6px !important;
box-shadow: 0 0 10px rgba(112, 0, 255, 0.2) !important;
text-transform: uppercase;
transition: all 0.25s ease !important;
}
.secondary-btn:hover {
background: rgba(255, 0, 127, 0.15) !important;
border-color: #ff007f !important;
box-shadow: 0 0 20px #ff007f !important;
color: #fff !important;
}
footer { display: none !important; }
@keyframes pulse-glow {
0% { box-shadow: 0 0 15px rgba(255, 0, 127, 0.1); border-color: #ff007f; }
100% { box-shadow: 0 0 30px rgba(112, 0, 255, 0.4); border-color: #7000ff; }
}
"""
with gr.Blocks(css=custom_css, theme="hmb/vaporwave") as demo:
# 1. Header
with gr.Group(elem_classes=["logo-header"]):
gr.Image(
value="TheSherLockOfBugs.jpeg",
show_label=False,
container=False,
interactive=False
)
# 2. Main Chat Interface
chatbot_window = gr.ChatInterface(fn=response)
# 4. Quick Action Controls - Giving hint button and resetting the chatbot board
with gr.Row():
clue_btn = gr.Button("🔍 Give Me Another Hint", elem_classes=["cyber-btn"])
clear_btn = gr.Button("📁 Reset Investigation Board", elem_classes=["secondary-btn"])
# 5. Sample Error Testing PaRT of the code
gr.HTML("<h3 style='color: #ff77ff; margin-top: 20px; text-shadow: 0 0 5px #ff007f;'>🧪 Select a Sample Case File to Test:</h3>")
with gr.Row():
btn_index = gr.Button("IndexError Example", elem_classes=["secondary-btn"])
btn_type = gr.Button("TypeError Example", elem_classes=["secondary-btn"])
btn_key = gr.Button("KeyError Example", elem_classes=["secondary-btn"])
btn_zero = gr.Button("ZeroDivision Example", elem_classes=["secondary-btn"])
# Used AI for this part to know how to make buttons using gradio, the lambda function is something i replaced to make it more organized.
def load_error_1():
return "my_list = [1, 2, 3]\nprint(my_list[5])\nIndexError: list index out of range"
def load_error_2():
return "for i in 10:\nprint(i)\nTypeError: 'int' object is not iterable"
def load_error_3():
return "user_data = {'name': 'Alice'}\nprint(user_data['age'])\nKeyError: 'age'"
def load_error_4():
return "result = 10 / 0\nZeroDivisionError: division by zero"
def ask_for_hint():
return "I am stuck on this error. Can you give me another clue or hint on what part of my structure to look at?"
# Attach event listeners to your buttons...
btn_index.click(fn=load_error_1, outputs=chatbot_window.textbox)
btn_type.click(fn=load_error_2, outputs=chatbot_window.textbox)
btn_key.click(fn=load_error_3, outputs=chatbot_window.textbox)
btn_zero.click(fn=load_error_4, outputs=chatbot_window.textbox)
clue_btn.click(fn=ask_for_hint, outputs=chatbot_window.textbox)
# --- ADD THIS LINE TO FIX THE RESET BUTTON ---
clear_btn.click(fn=lambda: ([], ""), outputs=[chatbot_window.chatbot, chatbot_window.textbox])
# Launch the custom chatbot app directly
demo.launch()