scriptsledge commited on
Commit
65f5fc6
·
verified ·
1 Parent(s): 9b12d46

feat: initial deploy of clarity hybrid backend with gemini and qwen support

Browse files
Files changed (3) hide show
  1. main.py +13 -4
  2. model_service.py +89 -0
  3. requirements.txt +1 -1
main.py CHANGED
@@ -1,9 +1,12 @@
1
  from fastapi import FastAPI
2
  from pydantic import BaseModel
 
3
  from fastapi.middleware.cors import CORSMiddleware
4
 
5
- from model_service import correct_code_with_ai
 
6
  app = FastAPI()
 
7
  app.add_middleware(
8
  CORSMiddleware,
9
  allow_origins=["*"], # Allows all origins for simplicity.
@@ -14,6 +17,8 @@ app.add_middleware(
14
 
15
  class CodeSnippet(BaseModel):
16
  code: str
 
 
17
 
18
  @app.get("/api/health")
19
  def health_check():
@@ -21,10 +26,14 @@ def health_check():
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
-
 
1
  from fastapi import FastAPI
2
  from pydantic import BaseModel
3
+ from typing import Optional
4
  from fastapi.middleware.cors import CORSMiddleware
5
 
6
+ from model_service import correct_code_with_ai, correct_code_with_gemini
7
+
8
  app = FastAPI()
9
+
10
  app.add_middleware(
11
  CORSMiddleware,
12
  allow_origins=["*"], # Allows all origins for simplicity.
 
17
 
18
  class CodeSnippet(BaseModel):
19
  code: str
20
+ model_provider: str = "local" # "local" or "google"
21
+ api_key: Optional[str] = None
22
 
23
  @app.get("/api/health")
24
  def health_check():
 
26
 
27
  @app.post("/api/correct")
28
  def correct_code_endpoint(snippet: CodeSnippet):
29
+ if snippet.model_provider == "google":
30
+ result = correct_code_with_gemini(snippet.code, snippet.api_key)
31
+ else:
32
+ # Default to local
33
+ result = correct_code_with_ai(snippet.code)
34
+
35
  # result is now a dict: {"code": "...", "language": {"name": "...", "ext": "..."}}
36
  return {
37
  "corrected_code": result["code"],
38
  "language": result["language"]
39
+ }
 
model_service.py CHANGED
@@ -1,6 +1,7 @@
1
  import os
2
  from transformers import pipeline
3
  import torch
 
4
 
5
  # --- Configuration ---
6
  # Using the standard Qwen 2.5 Coder 0.5B Instruct model (Native PyTorch)
@@ -23,6 +24,12 @@ try:
23
  device_map="auto"
24
  )
25
  print("Success: Clarity AI Model loaded.")
 
 
 
 
 
 
26
 
27
  except Exception as e:
28
  print(f"CRITICAL ERROR: Failed to load model. {e}")
@@ -197,3 +204,85 @@ def correct_code_with_ai(code: str) -> dict:
197
  "code": f"# An error occurred during processing: {str(e)}",
198
  "language": detected_lang
199
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  from transformers import pipeline
3
  import torch
4
+ import google.generativeai as genai
5
 
6
  # --- Configuration ---
7
  # Using the standard Qwen 2.5 Coder 0.5B Instruct model (Native PyTorch)
 
24
  device_map="auto"
25
  )
26
  print("Success: Clarity AI Model loaded.")
27
+
28
+ # Warm-up inference
29
+ print("Warming up model...")
30
+ warmup_msg = [{"role": "user", "content": "print('hello')"}]
31
+ pipe(warmup_msg, max_new_tokens=10)
32
+ print("Model warmup complete.")
33
 
34
  except Exception as e:
35
  print(f"CRITICAL ERROR: Failed to load model. {e}")
 
204
  "code": f"# An error occurred during processing: {str(e)}",
205
  "language": detected_lang
206
  }
207
+
208
+ def correct_code_with_gemini(code: str, api_key: str = None) -> dict:
209
+ """
210
+ Uses Google's Gemini 1.5 Flash model for code correction.
211
+ """
212
+ detected_lang = detect_language(code)
213
+
214
+ # 1. Resolve API Key
215
+ final_key = api_key if api_key else os.environ.get("GOOGLE_API_KEY")
216
+
217
+ if not final_key:
218
+ return {
219
+ "code": "# Error: No Google API Key provided. Please add it in Settings.",
220
+ "language": detected_lang
221
+ }
222
+
223
+ try:
224
+ genai.configure(api_key=final_key)
225
+
226
+ # Stricter System Prompt (Same as Local)
227
+ system_prompt = (
228
+ "You are Clarity, an intelligent coding assistant designed for students and junior developers. "
229
+ "You were created by a team of college students (see projects.md) for a minor project to help peers write better code.\n\n"
230
+ "Your Mission:\n"
231
+ "1. **Review & Fix:** Correct syntax and logical errors.\n"
232
+ "2. **Educate:** Improve variable naming (use industry standards like Google Style Guide), readability, and structure.\n"
233
+ "3. **Optimize:** Remove redundancy and improve logic.\n"
234
+ "4. **Be Concise:** Provide objective, short, and high-value feedback. Avoid long lectures.\n\n"
235
+ "Guidelines:\n"
236
+ "- **Style:** Follow the Google Style Guide for the respective language.\n"
237
+ "- **Comments:** Add comments ONLY for complex logic or educational 'aha!' moments.\n"
238
+ "- **Tone:** Concise, Objective, and Mentor-like.\n"
239
+ "- **Identity:** You are 'Clarity'. If asked about your version, refer users to the GitHub repo. If asked non-code questions, answer only if factual and harmless; otherwise, politely decline.\n\n"
240
+ "Constraint: Return ONLY the corrected code with necessary educational comments inline. Do not output a separate explanation block unless absolutely necessary for a critical concept."
241
+ )
242
+
243
+ model = genai.GenerativeModel(
244
+ model_name="gemini-1.5-flash",
245
+ system_instruction=system_prompt
246
+ )
247
+
248
+ # One-shot example
249
+ example_input = "def sum(a,b): return a+b" if detected_lang["name"] == "Python" else "int sum(int a, int b) { return a+b; }"
250
+ example_output = (
251
+ "def sum(operand_a, operand_b):\n"
252
+ " # Descriptive names improve readability\n"
253
+ " return operand_a + operand_b"
254
+ ) if detected_lang["name"] == "Python" else (
255
+ "int sum(int operand_a, int operand_b) {\n"
256
+ " // Descriptive names improve readability\n"
257
+ " return operand_a + operand_b;\n"
258
+ "}"
259
+ )
260
+
261
+ # Start chat with history
262
+ chat = model.start_chat(history=[
263
+ {"role": "user", "parts": [example_input]},
264
+ {"role": "model", "parts": [example_output]},
265
+ ])
266
+
267
+ response = chat.send_message(code)
268
+
269
+ cleaned_response = response.text.strip()
270
+
271
+ # Cleanup markdown
272
+ if "```" in cleaned_response:
273
+ lines = cleaned_response.split("\n")
274
+ if lines[0].strip().startswith("```"): lines = lines[1:]
275
+ if lines and lines[-1].strip().startswith("```"): lines = lines[:-1]
276
+ cleaned_response = "\n".join(lines).strip()
277
+
278
+ return {
279
+ "code": cleaned_response,
280
+ "language": detect_language(cleaned_response)
281
+ }
282
+
283
+ except Exception as e:
284
+ print(f"Gemini Inference Error: {e}")
285
+ return {
286
+ "code": f"# Gemini Error: {str(e)}",
287
+ "language": detected_lang
288
+ }
requirements.txt CHANGED
@@ -2,4 +2,4 @@ fastapi
2
  uvicorn
3
  transformers
4
  torch
5
- accelerate
 
2
  uvicorn
3
  transformers
4
  torch
5
+ accelerategoogle-generativeai