Abhay557 commited on
Commit
58b43fd
Β·
verified Β·
1 Parent(s): e8e4809

Upload 4 files

Browse files
Files changed (4) hide show
  1. Dockerfile +15 -0
  2. README.md +13 -11
  3. app.py +155 -0
  4. requirements.txt +4 -0
Dockerfile ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim
2
+
3
+ WORKDIR /app
4
+
5
+ COPY requirements.txt .
6
+ RUN pip install --no-cache-dir --prefer-binary -r requirements.txt
7
+
8
+ COPY app.py .
9
+
10
+ # Download model at build time so startup is instant
11
+ RUN python -c "from huggingface_hub import hf_hub_download; hf_hub_download('Qwen/Qwen2.5-Coder-0.5B-Instruct-GGUF', 'qwen2.5-coder-0.5b-instruct-q4_k_m.gguf')"
12
+
13
+ EXPOSE 7860
14
+
15
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
README.md CHANGED
@@ -1,11 +1,13 @@
1
- ---
2
- title: Code Collab
3
- emoji: πŸ†
4
- colorFrom: yellow
5
- colorTo: yellow
6
- sdk: docker
7
- pinned: false
8
- license: mit
9
- ---
10
-
11
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
1
+ ---
2
+ title: Code Collab AI Backend
3
+ emoji: πŸš€
4
+ colorFrom: purple
5
+ colorTo: indigo
6
+ sdk: docker
7
+ app_port: 7860
8
+ ---
9
+
10
+ # Code Collab AI Backend
11
+
12
+ Fast code generation API using Qwen 2.5 Coder 0.5B (GGUF).
13
+ Generates HTML, CSS, and JavaScript from natural language prompts.
app.py ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Code Collab AI Backend β€” Fast code generation API
3
+ Uses Qwen 2.5 Coder 0.5B GGUF for low-latency HTML/CSS/JS generation.
4
+ """
5
+
6
+ import os
7
+ import re
8
+ import time
9
+ from contextlib import asynccontextmanager
10
+
11
+ from fastapi import FastAPI, HTTPException
12
+ from fastapi.middleware.cors import CORSMiddleware
13
+ from pydantic import BaseModel
14
+ from huggingface_hub import hf_hub_download
15
+ from llama_cpp import Llama
16
+
17
+ # ─── Config ────────────────────────────────────────────────────────────
18
+ MODEL_REPO = "Qwen/Qwen2.5-Coder-0.5B-Instruct-GGUF"
19
+ MODEL_FILE = "qwen2.5-coder-0.5b-instruct-q4_k_m.gguf"
20
+ N_CTX = 1536 # Smaller context = faster (free tier)
21
+ N_THREADS = 2 # HF free tier has 2 vCPU
22
+ MAX_TOKENS = 512 # Keep output short for speed
23
+ TEMPERATURE = 0.5 # Lower = faster + more deterministic
24
+
25
+ # ─── System prompt (optimized for structured output) ───────────────────
26
+ SYSTEM_PROMPT = """You are a web code generator. Given a user request, output ONLY three fenced code blocks:
27
+
28
+ ```html
29
+ (body content only, no html/head/body tags)
30
+ ```
31
+
32
+ ```css
33
+ (complete styles)
34
+ ```
35
+
36
+ ```js
37
+ (complete JavaScript)
38
+ ```
39
+
40
+ Rules:
41
+ - No explanations, no markdown text outside code blocks
42
+ - If a section is not needed, output an empty code block for it
43
+ - Write clean, modern code"""
44
+
45
+ # ─── Global model reference ───────────────────────────────────────────
46
+ llm = None
47
+
48
+
49
+ @asynccontextmanager
50
+ async def lifespan(app: FastAPI):
51
+ """Load model once at startup, keep in memory for fast inference."""
52
+ global llm
53
+ print("⬇️ Downloading model...")
54
+ model_path = hf_hub_download(repo_id=MODEL_REPO, filename=MODEL_FILE)
55
+ print(f"βœ… Model downloaded: {model_path}")
56
+
57
+ print("πŸ”„ Loading model into memory...")
58
+ llm = Llama(
59
+ model_path=model_path,
60
+ n_ctx=N_CTX,
61
+ n_threads=N_THREADS,
62
+ n_gpu_layers=0, # CPU only (free HF Spaces)
63
+ verbose=False,
64
+ )
65
+ print("πŸš€ Model loaded and ready!")
66
+ yield
67
+ llm = None
68
+
69
+
70
+ # ─── FastAPI App ───────────────────────────────────────────────────────
71
+ app = FastAPI(title="Code Collab AI", lifespan=lifespan)
72
+
73
+ app.add_middleware(
74
+ CORSMiddleware,
75
+ allow_origins=["*"],
76
+ allow_methods=["*"],
77
+ allow_headers=["*"],
78
+ )
79
+
80
+
81
+ class GenerateRequest(BaseModel):
82
+ prompt: str
83
+ max_tokens: int = MAX_TOKENS
84
+ temperature: float = TEMPERATURE
85
+
86
+
87
+ class GenerateResponse(BaseModel):
88
+ html: str
89
+ css: str
90
+ js: str
91
+ raw: str
92
+ time_ms: int
93
+
94
+
95
+ def parse_code_blocks(text: str) -> dict:
96
+ """Extract HTML, CSS, JS from fenced code blocks."""
97
+ result = {"html": "", "css": "", "js": ""}
98
+
99
+ for match in re.finditer(r"```(\w+)\s*\n([\s\S]*?)```", text):
100
+ lang = match.group(1).lower()
101
+ code = match.group(2).strip()
102
+
103
+ if lang in ("html", "xml"):
104
+ result["html"] = code
105
+ elif lang == "css":
106
+ result["css"] = code
107
+ elif lang in ("js", "javascript"):
108
+ result["js"] = code
109
+
110
+ # Fallback: if no blocks found, treat as HTML
111
+ if not any(result.values()):
112
+ result["html"] = text.strip()
113
+
114
+ return result
115
+
116
+
117
+ # ─── API Endpoints ─────────────────────────────────────────────────────
118
+
119
+ @app.get("/")
120
+ def health():
121
+ return {"status": "ok", "model": MODEL_REPO}
122
+
123
+
124
+ @app.post("/generate", response_model=GenerateResponse)
125
+ def generate(req: GenerateRequest):
126
+ if llm is None:
127
+ raise HTTPException(503, "Model not loaded yet")
128
+
129
+ if not req.prompt.strip():
130
+ raise HTTPException(400, "Prompt cannot be empty")
131
+
132
+ start = time.time()
133
+
134
+ output = llm.create_chat_completion(
135
+ messages=[
136
+ {"role": "system", "content": SYSTEM_PROMPT},
137
+ {"role": "user", "content": req.prompt},
138
+ ],
139
+ max_tokens=req.max_tokens,
140
+ temperature=req.temperature,
141
+ stop=["```\n\n", "---"], # Stop early if model rambles
142
+ )
143
+
144
+ raw_text = output["choices"][0]["message"]["content"]
145
+ elapsed_ms = int((time.time() - start) * 1000)
146
+
147
+ parsed = parse_code_blocks(raw_text)
148
+
149
+ return GenerateResponse(
150
+ html=parsed["html"],
151
+ css=parsed["css"],
152
+ js=parsed["js"],
153
+ raw=raw_text,
154
+ time_ms=elapsed_ms,
155
+ )
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ fastapi==0.115.0
2
+ uvicorn[standard]==0.30.0
3
+ llama-cpp-python==0.2.82
4
+ huggingface-hub==0.27.0