Spaces:
Running
Running
feat: initial deploy of Clarity backend using Transformers and Qwen 2.5 Coder 3B
Browse files- Dockerfile +2 -2
- main.py +10 -2
- model_service.py +92 -121
- requirements.txt +2 -1
Dockerfile
CHANGED
|
@@ -7,7 +7,7 @@ WORKDIR /app
|
|
| 7 |
# Copy the requirements file into the container at /app
|
| 8 |
COPY requirements.txt .
|
| 9 |
|
| 10 |
-
# Install
|
| 11 |
RUN pip install --no-cache-dir -r requirements.txt
|
| 12 |
|
| 13 |
# Copy the current directory contents into the container at /app
|
|
@@ -17,7 +17,7 @@ COPY . .
|
|
| 17 |
RUN useradd -m -u 1000 user
|
| 18 |
USER user
|
| 19 |
ENV HOME=/home/user \
|
| 20 |
-
|
| 21 |
|
| 22 |
# Expose port 7860 (Hugging Face Spaces default)
|
| 23 |
EXPOSE 7860
|
|
|
|
| 7 |
# Copy the requirements file into the container at /app
|
| 8 |
COPY requirements.txt .
|
| 9 |
|
| 10 |
+
# Install dependencies
|
| 11 |
RUN pip install --no-cache-dir -r requirements.txt
|
| 12 |
|
| 13 |
# Copy the current directory contents into the container at /app
|
|
|
|
| 17 |
RUN useradd -m -u 1000 user
|
| 18 |
USER user
|
| 19 |
ENV HOME=/home/user \
|
| 20 |
+
PATH=/home/user/.local/bin:$PATH
|
| 21 |
|
| 22 |
# Expose port 7860 (Hugging Face Spaces default)
|
| 23 |
EXPOSE 7860
|
main.py
CHANGED
|
@@ -15,8 +15,16 @@ app.add_middleware(
|
|
| 15 |
class CodeSnippet(BaseModel):
|
| 16 |
code: str
|
| 17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
@app.post("/api/correct")
|
| 19 |
def correct_code_endpoint(snippet: CodeSnippet):
|
| 20 |
-
|
| 21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
|
|
|
|
| 15 |
class CodeSnippet(BaseModel):
|
| 16 |
code: str
|
| 17 |
|
| 18 |
+
@app.get("/api/health")
|
| 19 |
+
def health_check():
|
| 20 |
+
return {"status": "ok"}
|
| 21 |
+
|
| 22 |
@app.post("/api/correct")
|
| 23 |
def correct_code_endpoint(snippet: CodeSnippet):
|
| 24 |
+
result = correct_code_with_ai(snippet.code)
|
| 25 |
+
# result is now a dict: {"code": "...", "language": {"name": "...", "ext": "..."}}
|
| 26 |
+
return {
|
| 27 |
+
"corrected_code": result["code"],
|
| 28 |
+
"language": result["language"]
|
| 29 |
+
}
|
| 30 |
|
model_service.py
CHANGED
|
@@ -1,139 +1,110 @@
|
|
| 1 |
-
|
|
|
|
|
|
|
| 2 |
|
| 3 |
-
#
|
| 4 |
-
#
|
| 5 |
-
|
| 6 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
-
code_fixer = None
|
| 9 |
try:
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
print("
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
|
| 28 |
-
def correct_code_with_ai(code: str) ->
|
| 29 |
"""
|
| 30 |
-
Takes a buggy code snippet and returns a corrected version using the Qwen model.
|
| 31 |
"""
|
| 32 |
-
|
| 33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
|
| 35 |
-
# Few-Shot Priming: We inject a history to teach the small model (0.5B) its role.
|
| 36 |
-
# It learns to be:
|
| 37 |
-
# 1. Concise (Code only).
|
| 38 |
-
# 2. Multi-language (Supports C++, Java, JS, Python).
|
| 39 |
-
# 3. A "Style Guide" (Improves naming).
|
| 40 |
-
# 4. Aware of its creators.
|
| 41 |
messages = [
|
| 42 |
-
{
|
| 43 |
-
|
| 44 |
-
"content": "You are Clarity, a concise coding assistant. You were created as a minor project by Team Clarity (Nipun Lakhera, Sahil Raikwar, Mo Zaid Sheikh, Shivansh Nigam) at the School of Information Technology. Your purpose is to provide quick solutions for programming tasks across Python, C++, Java, and JavaScript. Output ONLY the code or direct answer."
|
| 45 |
-
},
|
| 46 |
-
# Example 1: Identity & Credit
|
| 47 |
-
{
|
| 48 |
-
"role": "user",
|
| 49 |
-
"content": "Who created you?"
|
| 50 |
-
},
|
| 51 |
-
{
|
| 52 |
-
"role": "assistant",
|
| 53 |
-
"content": "I am Clarity, a minor project created by Team Clarity: Nipun Lakhera, Sahil Raikwar, Mo Zaid Sheikh, and Shivansh Nigam at the School of Information Technology. Our Guide is Vipin Verma and our Co-guide is Swati Patel."
|
| 54 |
-
},
|
| 55 |
-
# Example 2: Ask about Vipin Sir
|
| 56 |
-
{
|
| 57 |
-
"role": "user",
|
| 58 |
-
"content": "Do you know Vipin Sir?"
|
| 59 |
-
},
|
| 60 |
-
{
|
| 61 |
-
"role": "assistant",
|
| 62 |
-
"content": "Yes, Vipin Verma is the Guide for Team Clarity's minor project. He supervised the team during its development."
|
| 63 |
-
},
|
| 64 |
-
# Example 3: Ask about Swati Patel
|
| 65 |
-
{
|
| 66 |
-
"role": "user",
|
| 67 |
-
"content": "Do you know Swati?"
|
| 68 |
-
},
|
| 69 |
-
{
|
| 70 |
-
"role": "assistant",
|
| 71 |
-
"content": "Yes, Swati Patel is the Co-guide for Team Clarity's minor project. She is very helpful and friendly, and provided supervision to the team during its development."
|
| 72 |
-
},
|
| 73 |
-
# Example 4: Purpose & Capabilities
|
| 74 |
-
{
|
| 75 |
-
"role": "user",
|
| 76 |
-
"content": "What can you do?"
|
| 77 |
-
},
|
| 78 |
-
{
|
| 79 |
-
"role": "assistant",
|
| 80 |
-
"content": "I exist to help you write professional, industry-standard code. My core capabilities are:\n1. **Bug Fixing:** I instantly correct errors in Python, C++, Java, and JavaScript.\n2. **Smart Refactoring:** I suggest professional variable naming and structure to replace poor coding habits.\n3. **Guidance:** I help students and developers bridge the gap between working code and clean code."
|
| 81 |
-
},
|
| 82 |
-
# Example 4: Simple Syntax Fix (C++) - Demonstrates multi-lang support
|
| 83 |
-
{
|
| 84 |
-
"role": "user",
|
| 85 |
-
"content": "int main() { std::cout << \"Hello World\" return 0; }"
|
| 86 |
-
},
|
| 87 |
-
{
|
| 88 |
-
"role": "assistant",
|
| 89 |
-
"content": "int main() { std::cout << \"Hello World\"; return 0; }"
|
| 90 |
-
},
|
| 91 |
-
# Example 5: Style & Naming Suggestion (Python) - Demonstrates "Industry Standard" improvement
|
| 92 |
-
{
|
| 93 |
-
"role": "user",
|
| 94 |
-
"content": "def c(x, y): return x * y"
|
| 95 |
-
},
|
| 96 |
-
{
|
| 97 |
-
"role": "assistant",
|
| 98 |
-
"content": "def calculate_product(factor_a, factor_b):\n return factor_a * factor_b"
|
| 99 |
-
},
|
| 100 |
-
# The actual user input
|
| 101 |
-
{
|
| 102 |
-
"role": "user",
|
| 103 |
-
"content": f"{code}"
|
| 104 |
-
},
|
| 105 |
]
|
| 106 |
|
| 107 |
try:
|
| 108 |
-
#
|
| 109 |
-
outputs =
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
|
| 111 |
-
|
|
|
|
| 112 |
|
| 113 |
-
if isinstance(
|
| 114 |
-
|
| 115 |
else:
|
| 116 |
-
|
| 117 |
|
| 118 |
-
#
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
for term in forbidden_terms:
|
| 126 |
-
if term in cleaned_response:
|
| 127 |
-
cleaned_response = cleaned_response.replace(term, "Team Clarity")
|
| 128 |
-
|
| 129 |
-
# Specific fix for "I am [Wrong Name]" patterns
|
| 130 |
-
if "I am" in cleaned_response and "Clarity" not in cleaned_response:
|
| 131 |
-
# If it says "I am chatgpt", just force it.
|
| 132 |
-
import re
|
| 133 |
-
cleaned_response = re.sub(r"I am .+?(\.|$)", "I am Clarity AI Assistant, developed by Team Clarity.", cleaned_response)
|
| 134 |
|
| 135 |
-
return
|
|
|
|
|
|
|
|
|
|
| 136 |
|
| 137 |
except Exception as e:
|
| 138 |
-
print(f"
|
| 139 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import torch
|
| 3 |
+
from transformers import pipeline
|
| 4 |
|
| 5 |
+
# --- Configuration ---
|
| 6 |
+
# Switching to 3B model for faster download and inference as requested
|
| 7 |
+
MODEL_ID = "Qwen/Qwen2.5-Coder-3B-Instruct"
|
| 8 |
+
|
| 9 |
+
print(f"Initializing Clarity AI Engine (Transformers Pipeline)...")
|
| 10 |
+
print(f"Target Model: {MODEL_ID}")
|
| 11 |
+
|
| 12 |
+
# Optimize for speed: use float16 if GPU is available
|
| 13 |
+
dtype = torch.float16 if torch.cuda.is_available() else "auto"
|
| 14 |
+
|
| 15 |
+
pipe = None
|
| 16 |
|
|
|
|
| 17 |
try:
|
| 18 |
+
print("Loading model pipeline...")
|
| 19 |
+
# Using the exact pattern you provided
|
| 20 |
+
pipe = pipeline(
|
| 21 |
+
"text-generation",
|
| 22 |
+
model=MODEL_ID,
|
| 23 |
+
device_map="auto",
|
| 24 |
+
torch_dtype=dtype
|
| 25 |
+
)
|
| 26 |
+
print("Success: Clarity AI Model loaded.")
|
| 27 |
+
|
| 28 |
+
except Exception as e:
|
| 29 |
+
print(f"CRITICAL ERROR: Failed to load model. {e}")
|
| 30 |
+
pipe = None
|
| 31 |
+
|
| 32 |
+
def detect_language(code: str) -> dict:
|
| 33 |
+
"""
|
| 34 |
+
Simple heuristic to detect programming language.
|
| 35 |
+
"""
|
| 36 |
+
code = code.strip()
|
| 37 |
+
if "#include" in code or "std::" in code or "int main()" in code:
|
| 38 |
+
return {"name": "C++", "ext": "cpp"}
|
| 39 |
+
if "public class" in code or "System.out.println" in code:
|
| 40 |
+
return {"name": "Java", "ext": "java"}
|
| 41 |
+
if "const " in code or "let " in code or "console.log" in code or "function" in code:
|
| 42 |
+
return {"name": "JavaScript", "ext": "js"}
|
| 43 |
+
if "def " in code or "import " in code or "print(" in code:
|
| 44 |
+
return {"name": "Python", "ext": "py"}
|
| 45 |
+
return {"name": "Text", "ext": "txt"}
|
| 46 |
|
| 47 |
+
def correct_code_with_ai(code: str) -> dict:
|
| 48 |
"""
|
| 49 |
+
Takes a buggy code snippet and returns a corrected version using the Qwen model pipeline.
|
| 50 |
"""
|
| 51 |
+
detected_lang = detect_language(code)
|
| 52 |
+
|
| 53 |
+
if not pipe:
|
| 54 |
+
return {
|
| 55 |
+
"code": "# Model failed to load. Check server logs.",
|
| 56 |
+
"language": detected_lang
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
system_prompt = (
|
| 60 |
+
"You are 'Clarity', an intelligent code correction and refactoring engine. "
|
| 61 |
+
f"Your goal is to take buggy or suboptimal {detected_lang['name']} code and provide a clean, "
|
| 62 |
+
"production-ready version. \n\n"
|
| 63 |
+
"Tasks:\n"
|
| 64 |
+
"1. Fix all syntax and logical bugs.\n"
|
| 65 |
+
"2. Improve code structure and readability (refactoring).\n"
|
| 66 |
+
"3. Enforce industry-standard naming conventions.\n"
|
| 67 |
+
"4. Maintain the original intent and logic of the code.\n\n"
|
| 68 |
+
"Constraint: Return ONLY the corrected code. No explanations, no markdown backticks, no comments unless necessary for clarity."
|
| 69 |
+
)
|
| 70 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
messages = [
|
| 72 |
+
{"role": "system", "content": system_prompt},
|
| 73 |
+
{"role": "user", "content": code}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
]
|
| 75 |
|
| 76 |
try:
|
| 77 |
+
# Standard pipeline call
|
| 78 |
+
outputs = pipe(
|
| 79 |
+
messages,
|
| 80 |
+
max_new_tokens=1024,
|
| 81 |
+
return_full_text=False
|
| 82 |
+
)
|
| 83 |
|
| 84 |
+
# Extract content
|
| 85 |
+
generated_msg = outputs[0]["generated_text"]
|
| 86 |
|
| 87 |
+
if isinstance(generated_msg, list):
|
| 88 |
+
response_content = generated_msg[-1]["content"]
|
| 89 |
else:
|
| 90 |
+
response_content = str(generated_msg)
|
| 91 |
|
| 92 |
+
# Clean up
|
| 93 |
+
cleaned_response = response_content.strip()
|
| 94 |
+
if "```" in cleaned_response:
|
| 95 |
+
lines = cleaned_response.split("\n")
|
| 96 |
+
if lines[0].startswith("```"): lines = lines[1:]
|
| 97 |
+
if lines and lines[-1].strip().startswith("```"): lines = lines[:-1]
|
| 98 |
+
cleaned_response = "\n".join(lines).strip()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
|
| 100 |
+
return {
|
| 101 |
+
"code": cleaned_response,
|
| 102 |
+
"language": detected_lang
|
| 103 |
+
}
|
| 104 |
|
| 105 |
except Exception as e:
|
| 106 |
+
print(f"Inference Error: {e}")
|
| 107 |
+
return {
|
| 108 |
+
"code": f"# An error occurred during processing: {str(e)}",
|
| 109 |
+
"language": detected_lang
|
| 110 |
+
}
|
requirements.txt
CHANGED
|
@@ -1,4 +1,5 @@
|
|
| 1 |
fastapi
|
| 2 |
uvicorn
|
| 3 |
transformers
|
| 4 |
-
torch
|
|
|
|
|
|
| 1 |
fastapi
|
| 2 |
uvicorn
|
| 3 |
transformers
|
| 4 |
+
torch
|
| 5 |
+
accelerate
|