scriptsledge commited on
Commit
f3e1db8
·
verified ·
1 Parent(s): fceb981

feat: initial deploy of Clarity backend using Transformers and Qwen 2.5 Coder 3B

Browse files
Files changed (4) hide show
  1. Dockerfile +2 -2
  2. main.py +10 -2
  3. model_service.py +92 -121
  4. 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 any needed packages specified in requirements.txt
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
- PATH=/home/user/.local/bin:$PATH
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
- corrected_code = correct_code_with_ai(snippet.code)
21
- return {"corrected_code": corrected_code}
 
 
 
 
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
- from transformers import pipeline, AutoModelForCausalLM, AutoTokenizer
 
 
2
 
3
- # Initialize the model pipeline.
4
- # We use 'Qwen/Qwen2.5-0.5B-Instruct' which is small, fast, and works natively.
5
- model_id = "Qwen/Qwen2.5-0.5B-Instruct"
6
- print(f"Loading AI model ({model_id})...")
 
 
 
 
 
 
 
7
 
8
- code_fixer = None
9
  try:
10
- # 1. Try loading from local cache first (offline mode)
11
- print("Attempting to load from local cache...")
12
- model = AutoModelForCausalLM.from_pretrained(model_id, trust_remote_code=True, local_files_only=True)
13
- tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True, local_files_only=True)
14
- code_fixer = pipeline("text-generation", model=model, tokenizer=tokenizer)
15
- print("Success: Loaded model from local cache.")
16
- except Exception as local_err:
17
- print(f"Local cache not found or incomplete: {local_err}")
18
- print("Attempting to download model from Hugging Face (requires internet)...")
19
- try:
20
- # 2. Fallback to downloading (online mode)
21
- code_fixer = pipeline("text-generation", model=model_id, trust_remote_code=True)
22
- print("Success: Model downloaded and loaded.")
23
- except Exception as remote_err:
24
- print(f"CRITICAL: Failed to load model. Error: {remote_err}")
25
- print("To run locally, ensure you have internet access for the first run to download the model.")
26
- code_fixer = None
 
 
 
 
 
 
 
 
 
 
 
27
 
28
- def correct_code_with_ai(code: str) -> str:
29
  """
30
- Takes a buggy code snippet and returns a corrected version using the Qwen model.
31
  """
32
- if not code_fixer:
33
- return "# Model failed to load. Check server logs."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
- "role": "system",
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
- # Generate the response
109
- outputs = code_fixer(messages, max_new_tokens=512)
 
 
 
 
110
 
111
- result = outputs[0]['generated_text']
 
112
 
113
- if isinstance(result, list):
114
- raw_response = result[-1]['content']
115
  else:
116
- raw_response = result
117
 
118
- # --- IDENTITY GUARDRAIL (Post-Processing) ---
119
- # Small models often hallucinate their training origin (e.g., "I am Qwen...").
120
- # We strictly sanitize this to ensure the user always sees the correct identity.
121
- forbidden_terms = ["Anthropic", "OpenAI", "Google", "Alibaba", "Qwen", "Claude", "Meta"]
122
- cleaned_response = raw_response
123
-
124
- # Simple text replacement if the model slips up
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 cleaned_response
 
 
 
136
 
137
  except Exception as e:
138
- print(f"An error occurred during AI correction: {e}")
139
- return f"# Unable to correct the code. Error: {str(e)}"
 
 
 
 
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