Manish Kumar commited on
Commit
42a745c
·
1 Parent(s): d363e47

new model fix

Browse files
Files changed (4) hide show
  1. backend/app/llm/manager.py +33 -0
  2. backend/app/main.py +7 -4
  3. railway.json +1 -1
  4. render.yaml +7 -19
backend/app/llm/manager.py CHANGED
@@ -1,17 +1,49 @@
1
  import os
2
  import logging
 
3
  from typing import AsyncIterator, Dict, Any, Optional
4
  from backend.app.llm.base import BaseLLMProvider
5
  from backend.app.llm.local import LocalLLMProvider
 
6
 
7
  logger = logging.getLogger(__name__)
8
 
 
 
 
 
9
  class LLMManager:
10
  def __init__(self):
11
  self.provider: Optional[BaseLLMProvider] = None
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  async def setup_provider(self):
14
  logger.info("Initializing local provider...")
 
15
  local = LocalLLMProvider()
16
  await local.initialize()
17
  self.provider = local
@@ -34,4 +66,5 @@ class LLMManager:
34
  p = await self.get_active_provider()
35
  return p.get_info()
36
 
 
37
  llm_manager = LLMManager()
 
1
  import os
2
  import logging
3
+ import asyncio
4
  from typing import AsyncIterator, Dict, Any, Optional
5
  from backend.app.llm.base import BaseLLMProvider
6
  from backend.app.llm.local import LocalLLMProvider
7
+ from backend.app.config import settings
8
 
9
  logger = logging.getLogger(__name__)
10
 
11
+ MODEL_REPO = "bartowski/SmolLM2-360M-Instruct-GGUF"
12
+ MODEL_FILE = "SmolLM2-360M-Instruct-Q4_K_M.gguf"
13
+
14
+
15
  class LLMManager:
16
  def __init__(self):
17
  self.provider: Optional[BaseLLMProvider] = None
18
 
19
+ async def ensure_model_downloaded(self) -> bool:
20
+ model_path = os.path.abspath(settings.LOCAL_MODEL_PATH)
21
+ if os.path.exists(model_path):
22
+ logger.info(f"Model found at {model_path}")
23
+ return True
24
+
25
+ os.makedirs(os.path.dirname(model_path), exist_ok=True)
26
+ logger.info(f"Downloading {MODEL_FILE} (~180MB) from {MODEL_REPO}...")
27
+ try:
28
+ from huggingface_hub import hf_hub_download
29
+
30
+ def download():
31
+ return hf_hub_download(
32
+ repo_id=MODEL_REPO, filename=MODEL_FILE,
33
+ local_dir=os.path.dirname(model_path),
34
+ local_dir_use_symlinks=False,
35
+ )
36
+
37
+ await asyncio.to_thread(download)
38
+ logger.info("Model download complete!")
39
+ return True
40
+ except Exception as e:
41
+ logger.error(f"Model download failed: {e}")
42
+ return False
43
+
44
  async def setup_provider(self):
45
  logger.info("Initializing local provider...")
46
+ await self.ensure_model_downloaded()
47
  local = LocalLLMProvider()
48
  await local.initialize()
49
  self.provider = local
 
66
  p = await self.get_active_provider()
67
  return p.get_info()
68
 
69
+
70
  llm_manager = LLMManager()
backend/app/main.py CHANGED
@@ -6,7 +6,7 @@ import asyncio
6
  from contextlib import asynccontextmanager
7
  from typing import AsyncGenerator, Dict, Any
8
 
9
- from fastapi import FastAPI, HTTPException, status
10
  from fastapi.middleware.cors import CORSMiddleware
11
  from fastapi.responses import StreamingResponse
12
  from fastapi.staticfiles import StaticFiles
@@ -37,6 +37,7 @@ async def lifespan(app: FastAPI):
37
 
38
 
39
  app = FastAPI(title="Levi AI Coder", version="1.0.0", lifespan=lifespan)
 
40
 
41
  app.add_middleware(LoggingMiddleware)
42
  app.add_middleware(
@@ -109,7 +110,7 @@ async def run_standard(
109
  raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e))
110
 
111
 
112
- @app.post("/chat")
113
  async def chat(request: ChatRequest):
114
  msgs = [m.model_dump() for m in request.messages]
115
  system_prompt = None
@@ -138,7 +139,7 @@ async def chat(request: ChatRequest):
138
  )
139
 
140
 
141
- @app.post("/complete")
142
  async def complete(request: CompletionRequest):
143
  prompt = get_completion_prompt(request.prefix, request.suffix, request.language or "python")
144
  if request.stream:
@@ -151,7 +152,7 @@ async def complete(request: CompletionRequest):
151
  max_tokens=request.max_tokens or 128)
152
 
153
 
154
- @app.get("/health")
155
  async def health():
156
  info = await llm_manager.get_status_info()
157
  return {
@@ -160,6 +161,8 @@ async def health():
160
  }
161
 
162
 
 
 
163
  frontend_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "frontend", "dist"))
164
  if os.path.exists(frontend_dir):
165
  app.mount("/", StaticFiles(directory=frontend_dir, html=True), name="frontend")
 
6
  from contextlib import asynccontextmanager
7
  from typing import AsyncGenerator, Dict, Any
8
 
9
+ from fastapi import FastAPI, HTTPException, status, APIRouter
10
  from fastapi.middleware.cors import CORSMiddleware
11
  from fastapi.responses import StreamingResponse
12
  from fastapi.staticfiles import StaticFiles
 
37
 
38
 
39
  app = FastAPI(title="Levi AI Coder", version="1.0.0", lifespan=lifespan)
40
+ api = APIRouter(prefix="/api")
41
 
42
  app.add_middleware(LoggingMiddleware)
43
  app.add_middleware(
 
110
  raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e))
111
 
112
 
113
+ @api.post("/chat")
114
  async def chat(request: ChatRequest):
115
  msgs = [m.model_dump() for m in request.messages]
116
  system_prompt = None
 
139
  )
140
 
141
 
142
+ @api.post("/complete")
143
  async def complete(request: CompletionRequest):
144
  prompt = get_completion_prompt(request.prefix, request.suffix, request.language or "python")
145
  if request.stream:
 
152
  max_tokens=request.max_tokens or 128)
153
 
154
 
155
+ @api.get("/health")
156
  async def health():
157
  info = await llm_manager.get_status_info()
158
  return {
 
161
  }
162
 
163
 
164
+ app.include_router(api)
165
+
166
  frontend_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "frontend", "dist"))
167
  if os.path.exists(frontend_dir):
168
  app.mount("/", StaticFiles(directory=frontend_dir, html=True), name="frontend")
railway.json CHANGED
@@ -7,7 +7,7 @@
7
  "deploy": {
8
  "numReplicas": 1,
9
  "restartPolicyType": "ON_FAILURE",
10
- "healthcheckPath": "/health",
11
  "healthcheckTimeout": 120
12
  }
13
  }
 
7
  "deploy": {
8
  "numReplicas": 1,
9
  "restartPolicyType": "ON_FAILURE",
10
+ "healthcheckPath": "/api/health",
11
  "healthcheckTimeout": 120
12
  }
13
  }
render.yaml CHANGED
@@ -1,31 +1,19 @@
1
  services:
2
  - type: web
3
- name: antigravity-ai-coder
4
  env: docker
5
  dockerfilePath: Dockerfile
6
- plan: free # Can be upgraded for RAM/volumes
7
  envVars:
8
  - key: PORT
9
  value: 8000
10
- - key: HOST
11
- value: 0.0.0.0
12
- - key: INFERENCE_MODE
13
- value: auto
14
  - key: LOCAL_MODEL_PATH
15
- value: models/Qwen2.5-Coder-0.5B-Instruct-Q4_K_M.gguf
16
- - key: HF_MODEL_ID
17
- value: Qwen/Qwen2.5-Coder-0.5B-Instruct
18
- - key: DEFAULT_TEMPERATURE
19
- value: 0.7
20
  - key: DEFAULT_MAX_TOKENS
21
- value: 1024
22
- - key: RATE_LIMIT_PER_MINUTE
23
- value: 60
24
- - key: SECRET_KEY
25
- generateValue: true
26
- - key: HF_API_TOKEN
27
- sync: false # Set in Render UI
28
  disk:
29
  name: models-storage
30
  mountPath: /app/models
31
- sizeGB: 10
 
1
  services:
2
  - type: web
3
+ name: levi-ai-coder
4
  env: docker
5
  dockerfilePath: Dockerfile
6
+ plan: free
7
  envVars:
8
  - key: PORT
9
  value: 8000
 
 
 
 
10
  - key: LOCAL_MODEL_PATH
11
+ value: models/SmolLM2-360M-Instruct-Q4_K_M.gguf
12
+ - key: DEFAULT_CONTEXT_LENGTH
13
+ value: 512
 
 
14
  - key: DEFAULT_MAX_TOKENS
15
+ value: 512
 
 
 
 
 
 
16
  disk:
17
  name: models-storage
18
  mountPath: /app/models
19
+ sizeGB: 2