CodeCommunity commited on
Commit
4541812
·
verified ·
1 Parent(s): 014a36c

Update app/main.py

Browse files
Files changed (1) hide show
  1. app/main.py +7 -38
app/main.py CHANGED
@@ -7,31 +7,23 @@ import asyncio
7
  from typing import List, Optional, Dict
8
  from concurrent.futures import ThreadPoolExecutor
9
  from dotenv import load_dotenv
10
-
11
  from fastapi import FastAPI, HTTPException, status
12
  from pydantic import BaseModel
13
  import uvicorn
14
 
15
- # Load environment variables
16
  load_dotenv()
17
 
18
- # Import internal services
19
  from app.predictor import classifier, guide_generator, reviewer
20
  from app.core.model_loader import llm_engine
21
 
22
- # 1. Setup Logging
23
  logging.basicConfig(level=logging.INFO)
24
  logger = logging.getLogger(__name__)
25
 
26
- # 2. Initialize FastAPI
27
  app = FastAPI(title="GitGud AI Service")
28
 
29
- # Global embedding cache
30
  REPO_CACHE: Dict[str, Dict[str, List[float]]] = {}
 
31
 
32
- executor = ThreadPoolExecutor(max_workers=4)
33
-
34
- # 3. Data Models
35
  class FileRequest(BaseModel):
36
  fileName: str
37
  content: Optional[str] = None
@@ -54,7 +46,6 @@ class ChatRequest(BaseModel):
54
  context: List[Dict[str, str]]
55
  repoName: str
56
 
57
- # 4. Core Logic Helpers
58
  def calculate_repo_health(total_vulns: int, avg_maint: float) -> int:
59
  base_score = avg_maint * 10
60
  penalty = total_vulns * 8
@@ -62,25 +53,17 @@ def calculate_repo_health(total_vulns: int, avg_maint: float) -> int:
62
 
63
  def sync_review_worker(file_list: List[FileRequest]):
64
  logger.info(f"--- [DEBUG] Processing {len(file_list)} files for code review ---")
65
- for f in file_list:
66
- content_len = len(f.content or "")
67
- logger.info(f"File: {f.fileName} | Content length: {content_len} chars")
68
-
69
  try:
70
  results = reviewer.service.review_batch_code(file_list)
71
- logger.info(f"--- [DEBUG] Reviewer Output: {results} ---")
72
  return results
73
  except Exception as e:
74
  logger.error(f"--- [ERROR] Exception during review processing: {e} ---", exc_info=True)
75
  raise e
76
 
77
  def parse_tree_to_list(raw_tree: str):
78
- """Parses text tree into JSON objects for Compose LazyColumn"""
79
  nodes = []
80
  for line in raw_tree.strip().split('\n'):
81
- # Detect depth based on tree characters
82
  level = line.count('|') + (line.count(' ') // 2)
83
- # Clean the name
84
  name = re.sub(r'[|└├─]', '', line).strip()
85
  if name:
86
  nodes.append({
@@ -90,8 +73,6 @@ def parse_tree_to_list(raw_tree: str):
90
  })
91
  return nodes
92
 
93
- # 5. Endpoints
94
-
95
  @app.get("/")
96
  def health_check():
97
  return {
@@ -113,7 +94,6 @@ async def classify_file(request: FileRequest):
113
  if request.repoName not in REPO_CACHE:
114
  REPO_CACHE[request.repoName] = {}
115
  REPO_CACHE[request.repoName][request.fileName] = result["embedding"]
116
-
117
  return {
118
  "fileName": request.fileName,
119
  "layer": result["label"],
@@ -151,7 +131,6 @@ async def get_dashboard_stats(request: BatchReviewRequest):
151
  for i, current_review in enumerate(raw_reviews):
152
  vulns = current_review.get("vulnerabilities", [])
153
  total_vulns += len(vulns)
154
-
155
  m_score = current_review.get("metrics", {}).get("maintainability", 8.0)
156
  maint_scores.append(m_score)
157
 
@@ -184,7 +163,6 @@ async def analyze_file(request: FileRequest):
184
  result = classifier.predict(request.fileName, request.content)
185
  summary = classifier.generate_file_summary(request.content, request.fileName)
186
  tags = classifier.extract_tags(request.content, request.fileName)
187
-
188
  return {
189
  "fileName": request.fileName,
190
  "layer": result["label"],
@@ -214,35 +192,27 @@ async def semantic_search(request: SearchRequest):
214
 
215
  @app.post("/chat")
216
  async def chat(request: ChatRequest):
217
- start_time = time.time()
218
  try:
219
  context_str = ""
220
  for item in request.context:
221
  context_str += f"--- FILE: {item['fileName']} ---\n{item['content']}\n\n"
222
-
223
- prompt = f"""
224
- You are "GitGud AI", an expert software architect.
225
- Repository: "{request.repoName}"
226
- CONTEXT: {context_str if request.context else "(NO CODE PROVIDED)"}
227
- USER QUESTION: {request.query}
228
- """
229
  response = llm_engine.generate_text(prompt)
230
  return {"response": response, "status": "success"}
231
  except Exception as e:
232
  if "429" in str(e):
233
- # Return a structured error so Compose can show a nice UI
234
  return {"response": "⚠️ Daily limit reached. Try again in a bit!", "status": "quota_error"}
235
  raise HTTPException(status_code=500, detail=str(e))
236
 
237
  @app.post("/generate-guide")
238
  async def generate_guide(request: GuideRequest):
239
- """
240
- FIXED: Now parses the messy tree text into JSON for your Compose UI.
241
- """
242
  try:
243
  markdown = guide_generator.generate_markdown(request.repoName, request.filePaths)
244
-
245
- # Extract the messy tree part and clean it
246
  tree_match = re.search(r"Project Structure\n\n(.*?)(?=\n\n|$)", markdown, re.S)
247
  structured_tree = []
248
  if tree_match:
@@ -258,7 +228,6 @@ async def generate_guide(request: GuideRequest):
258
  raise HTTPException(status_code=429, detail="AI Quota Exceeded")
259
  raise HTTPException(status_code=500, detail=str(e))
260
 
261
- # 6. Application Entry Point
262
  if __name__ == "__main__":
263
  port = int(os.environ.get("PORT", 7860))
264
  uvicorn.run(app, host="0.0.0.0", port=port)
 
7
  from typing import List, Optional, Dict
8
  from concurrent.futures import ThreadPoolExecutor
9
  from dotenv import load_dotenv
 
10
  from fastapi import FastAPI, HTTPException, status
11
  from pydantic import BaseModel
12
  import uvicorn
13
 
 
14
  load_dotenv()
15
 
 
16
  from app.predictor import classifier, guide_generator, reviewer
17
  from app.core.model_loader import llm_engine
18
 
 
19
  logging.basicConfig(level=logging.INFO)
20
  logger = logging.getLogger(__name__)
21
 
 
22
  app = FastAPI(title="GitGud AI Service")
23
 
 
24
  REPO_CACHE: Dict[str, Dict[str, List[float]]] = {}
25
+ executor = ThreadPoolExecutor(max_workers=8)
26
 
 
 
 
27
  class FileRequest(BaseModel):
28
  fileName: str
29
  content: Optional[str] = None
 
46
  context: List[Dict[str, str]]
47
  repoName: str
48
 
 
49
  def calculate_repo_health(total_vulns: int, avg_maint: float) -> int:
50
  base_score = avg_maint * 10
51
  penalty = total_vulns * 8
 
53
 
54
  def sync_review_worker(file_list: List[FileRequest]):
55
  logger.info(f"--- [DEBUG] Processing {len(file_list)} files for code review ---")
 
 
 
 
56
  try:
57
  results = reviewer.service.review_batch_code(file_list)
 
58
  return results
59
  except Exception as e:
60
  logger.error(f"--- [ERROR] Exception during review processing: {e} ---", exc_info=True)
61
  raise e
62
 
63
  def parse_tree_to_list(raw_tree: str):
 
64
  nodes = []
65
  for line in raw_tree.strip().split('\n'):
 
66
  level = line.count('|') + (line.count(' ') // 2)
 
67
  name = re.sub(r'[|└├─]', '', line).strip()
68
  if name:
69
  nodes.append({
 
73
  })
74
  return nodes
75
 
 
 
76
  @app.get("/")
77
  def health_check():
78
  return {
 
94
  if request.repoName not in REPO_CACHE:
95
  REPO_CACHE[request.repoName] = {}
96
  REPO_CACHE[request.repoName][request.fileName] = result["embedding"]
 
97
  return {
98
  "fileName": request.fileName,
99
  "layer": result["label"],
 
131
  for i, current_review in enumerate(raw_reviews):
132
  vulns = current_review.get("vulnerabilities", [])
133
  total_vulns += len(vulns)
 
134
  m_score = current_review.get("metrics", {}).get("maintainability", 8.0)
135
  maint_scores.append(m_score)
136
 
 
163
  result = classifier.predict(request.fileName, request.content)
164
  summary = classifier.generate_file_summary(request.content, request.fileName)
165
  tags = classifier.extract_tags(request.content, request.fileName)
 
166
  return {
167
  "fileName": request.fileName,
168
  "layer": result["label"],
 
192
 
193
  @app.post("/chat")
194
  async def chat(request: ChatRequest):
 
195
  try:
196
  context_str = ""
197
  for item in request.context:
198
  context_str += f"--- FILE: {item['fileName']} ---\n{item['content']}\n\n"
199
+
200
+ prompt = f"""You are "GitGud AI", an expert software architect.
201
+ Repository: "{request.repoName}"
202
+ CONTEXT: {context_str if request.context else "(NO CODE PROVIDED)"}
203
+ USER QUESTION: {request.query}"""
204
+
 
205
  response = llm_engine.generate_text(prompt)
206
  return {"response": response, "status": "success"}
207
  except Exception as e:
208
  if "429" in str(e):
 
209
  return {"response": "⚠️ Daily limit reached. Try again in a bit!", "status": "quota_error"}
210
  raise HTTPException(status_code=500, detail=str(e))
211
 
212
  @app.post("/generate-guide")
213
  async def generate_guide(request: GuideRequest):
 
 
 
214
  try:
215
  markdown = guide_generator.generate_markdown(request.repoName, request.filePaths)
 
 
216
  tree_match = re.search(r"Project Structure\n\n(.*?)(?=\n\n|$)", markdown, re.S)
217
  structured_tree = []
218
  if tree_match:
 
228
  raise HTTPException(status_code=429, detail="AI Quota Exceeded")
229
  raise HTTPException(status_code=500, detail=str(e))
230
 
 
231
  if __name__ == "__main__":
232
  port = int(os.environ.get("PORT", 7860))
233
  uvicorn.run(app, host="0.0.0.0", port=port)