Spaces:
Sleeping
Sleeping
swayamshetkar commited on
Commit ·
889453a
1
Parent(s): 327898f
latest
Browse files- Dockerfile +25 -0
- app.py +39 -40
- prompt_templates.py +36 -30
- requirements.txt +7 -5
Dockerfile
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.10-slim
|
| 2 |
+
|
| 3 |
+
WORKDIR /code
|
| 4 |
+
|
| 5 |
+
# Install system dependencies
|
| 6 |
+
RUN apt-get update && apt-get install -y \
|
| 7 |
+
build-essential \
|
| 8 |
+
curl \
|
| 9 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 10 |
+
|
| 11 |
+
# Copy requirements first for better caching
|
| 12 |
+
COPY requirements.txt .
|
| 13 |
+
|
| 14 |
+
# Install Python dependencies
|
| 15 |
+
RUN pip install --no-cache-dir --upgrade pip && \
|
| 16 |
+
pip install --no-cache-dir -r requirements.txt
|
| 17 |
+
|
| 18 |
+
# Copy application code
|
| 19 |
+
COPY . .
|
| 20 |
+
|
| 21 |
+
# Expose port
|
| 22 |
+
EXPOSE 7860
|
| 23 |
+
|
| 24 |
+
# Run the application
|
| 25 |
+
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
|
app.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
| 1 |
from fastapi import FastAPI
|
| 2 |
from pydantic import BaseModel
|
| 3 |
-
from model_loader import
|
| 4 |
from prompt_templates import MAIN_PROMPT_TEMPLATE, DETAIL_PROMPT_TEMPLATE
|
| 5 |
-
import torch
|
| 6 |
import json
|
| 7 |
import re
|
|
|
|
| 8 |
|
| 9 |
app = FastAPI()
|
| 10 |
|
|
@@ -15,54 +15,53 @@ class DetailRequest(BaseModel):
|
|
| 15 |
idea_id: int
|
| 16 |
idea_title: str
|
| 17 |
|
| 18 |
-
|
| 19 |
-
@app.get("/")
|
| 20 |
-
def home():
|
| 21 |
-
return {"status": "Local GPT-2 Backend Running", "endpoints": ["/generate", "/details"]}
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
def run_gpt2(prompt: str):
|
| 25 |
-
inputs = tokenizer.encode(prompt, return_tensors="pt")
|
| 26 |
-
outputs = model.generate(
|
| 27 |
-
inputs,
|
| 28 |
-
max_new_tokens=500,
|
| 29 |
-
temperature=0.8,
|
| 30 |
-
top_p=0.9,
|
| 31 |
-
do_sample=True
|
| 32 |
-
)
|
| 33 |
-
return tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 34 |
-
|
| 35 |
-
|
| 36 |
def extract_json(text):
|
| 37 |
try:
|
| 38 |
-
|
| 39 |
-
if match:
|
| 40 |
-
return json.loads(match.group())
|
| 41 |
except:
|
| 42 |
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
return {"error": "JSON parsing failed", "raw_output": text}
|
| 44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
|
| 46 |
-
# -----------------------
|
| 47 |
-
# STEP 1 → GENERATE IDEAS
|
| 48 |
-
# -----------------------
|
| 49 |
@app.post("/generate")
|
| 50 |
def generate(req: GenerateRequest):
|
| 51 |
-
prompt = MAIN_PROMPT_TEMPLATE.
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
return json_data
|
| 55 |
-
|
| 56 |
|
| 57 |
-
# -----------------------
|
| 58 |
-
# STEP 2 → IDEA DETAILS
|
| 59 |
-
# -----------------------
|
| 60 |
@app.post("/details")
|
| 61 |
def details(req: DetailRequest):
|
| 62 |
-
prompt =
|
| 63 |
-
|
| 64 |
-
|
|
|
|
| 65 |
)
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
return json_data
|
|
|
|
| 1 |
from fastapi import FastAPI
|
| 2 |
from pydantic import BaseModel
|
| 3 |
+
from model_loader import model, tokenizer
|
| 4 |
from prompt_templates import MAIN_PROMPT_TEMPLATE, DETAIL_PROMPT_TEMPLATE
|
|
|
|
| 5 |
import json
|
| 6 |
import re
|
| 7 |
+
import torch
|
| 8 |
|
| 9 |
app = FastAPI()
|
| 10 |
|
|
|
|
| 15 |
idea_id: int
|
| 16 |
idea_title: str
|
| 17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
def extract_json(text):
|
| 19 |
try:
|
| 20 |
+
return json.loads(text)
|
|
|
|
|
|
|
| 21 |
except:
|
| 22 |
pass
|
| 23 |
+
|
| 24 |
+
m = re.search(r"\{[\s\S]*\}", text)
|
| 25 |
+
if m:
|
| 26 |
+
try:
|
| 27 |
+
return json.loads(m.group())
|
| 28 |
+
except:
|
| 29 |
+
pass
|
| 30 |
+
|
| 31 |
return {"error": "JSON parsing failed", "raw_output": text}
|
| 32 |
|
| 33 |
+
def run_model(prompt: str):
|
| 34 |
+
inputs = tokenizer(prompt, return_tensors="pt", truncation=True, max_length=512).to("cpu")
|
| 35 |
+
with torch.no_grad():
|
| 36 |
+
outputs = model.generate(
|
| 37 |
+
**inputs,
|
| 38 |
+
max_new_tokens=512,
|
| 39 |
+
do_sample=False,
|
| 40 |
+
temperature=1.0
|
| 41 |
+
)
|
| 42 |
+
text = tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 43 |
+
return text
|
| 44 |
+
|
| 45 |
+
@app.get("/")
|
| 46 |
+
def home():
|
| 47 |
+
return {
|
| 48 |
+
"status": "FLAN-T5 Backend Running",
|
| 49 |
+
"endpoints": ["/generate", "/details"],
|
| 50 |
+
"model": "google/flan-t5-base"
|
| 51 |
+
}
|
| 52 |
|
|
|
|
|
|
|
|
|
|
| 53 |
@app.post("/generate")
|
| 54 |
def generate(req: GenerateRequest):
|
| 55 |
+
prompt = MAIN_PROMPT_TEMPLATE.replace("{CUSTOM_PROMPT}", req.custom_prompt)
|
| 56 |
+
raw = run_model(prompt)
|
| 57 |
+
return extract_json(raw)
|
|
|
|
|
|
|
| 58 |
|
|
|
|
|
|
|
|
|
|
| 59 |
@app.post("/details")
|
| 60 |
def details(req: DetailRequest):
|
| 61 |
+
prompt = (
|
| 62 |
+
DETAIL_PROMPT_TEMPLATE
|
| 63 |
+
.replace("{IDEA_ID}", str(req.idea_id))
|
| 64 |
+
.replace("{IDEA_TITLE}", req.idea_title)
|
| 65 |
)
|
| 66 |
+
raw = run_model(prompt)
|
| 67 |
+
return extract_json(raw)
|
|
|
prompt_templates.py
CHANGED
|
@@ -1,53 +1,65 @@
|
|
| 1 |
MAIN_PROMPT_TEMPLATE = """
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
Return ONLY
|
| 6 |
-
|
| 7 |
{
|
| 8 |
"ideas": [
|
| 9 |
{
|
| 10 |
-
"id":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
"title": "<string>",
|
| 12 |
"elevator": "<string>",
|
| 13 |
"overview": "<string>",
|
| 14 |
-
"primary_tech_stack": ["<string>"
|
| 15 |
"difficulty": "<Easy|Medium|Hard>",
|
| 16 |
"time_estimate_hours": <number>
|
| 17 |
}
|
| 18 |
],
|
| 19 |
-
"best_pick_id": <
|
| 20 |
"best_pick_reason": "<string>"
|
| 21 |
}
|
| 22 |
-
|
| 23 |
-
Constraints:
|
| 24 |
-
- Return exactly 3 ideas.
|
| 25 |
-
- Keep all text concise for UI cards.
|
| 26 |
""".strip()
|
| 27 |
|
| 28 |
-
|
| 29 |
DETAIL_PROMPT_TEMPLATE = """
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
{
|
| 35 |
"id": {IDEA_ID},
|
| 36 |
"title": "{IDEA_TITLE}",
|
| 37 |
-
"mermaid_architecture": "
|
| 38 |
"phases": [
|
| 39 |
{
|
| 40 |
"name": "<MVP|Polish|Demo>",
|
| 41 |
"time_hours": <number>,
|
| 42 |
-
"tasks": ["<string>", "
|
| 43 |
-
"deliverables": ["<string>", "
|
| 44 |
}
|
| 45 |
],
|
| 46 |
"critical_code_snippets": [
|
| 47 |
{
|
| 48 |
"title": "<string>",
|
| 49 |
-
"language": "javascript
|
| 50 |
-
"code": "<
|
| 51 |
}
|
| 52 |
],
|
| 53 |
"ui_components": [
|
|
@@ -59,14 +71,8 @@ Return ONLY valid JSON matching this exact schema:
|
|
| 59 |
"risks_and_mitigations": [
|
| 60 |
{
|
| 61 |
"risk": "<string>",
|
| 62 |
-
"mitigation":"<string>"
|
| 63 |
}
|
| 64 |
]
|
| 65 |
}
|
| 66 |
-
|
| 67 |
-
Constraints:
|
| 68 |
-
- The 'phases' array must cover the entire build process.
|
| 69 |
-
- Total time for all phases must not exceed 48 hours.
|
| 70 |
-
- Mermaid diagrams must be valid and represent the project architecture.
|
| 71 |
-
- Include at least one meaningful code snippet.
|
| 72 |
-
""".strip()
|
|
|
|
| 1 |
MAIN_PROMPT_TEMPLATE = """
|
| 2 |
+
You are an AI that outputs ONLY valid JSON.
|
| 3 |
+
Do NOT include explanations. Do NOT include any text before or after the JSON.
|
| 4 |
+
Generate 3 client-side hackathon ideas. {CUSTOM_PROMPT}
|
| 5 |
+
Return ONLY JSON in this exact format:
|
|
|
|
| 6 |
{
|
| 7 |
"ideas": [
|
| 8 |
{
|
| 9 |
+
"id": 1,
|
| 10 |
+
"title": "<string>",
|
| 11 |
+
"elevator": "<string>",
|
| 12 |
+
"overview": "<string>",
|
| 13 |
+
"primary_tech_stack": ["<string>"],
|
| 14 |
+
"difficulty": "<Easy|Medium|Hard>",
|
| 15 |
+
"time_estimate_hours": <number>
|
| 16 |
+
},
|
| 17 |
+
{
|
| 18 |
+
"id": 2,
|
| 19 |
+
"title": "<string>",
|
| 20 |
+
"elevator": "<string>",
|
| 21 |
+
"overview": "<string>",
|
| 22 |
+
"primary_tech_stack": ["<string>"],
|
| 23 |
+
"difficulty": "<Easy|Medium|Hard>",
|
| 24 |
+
"time_estimate_hours": <number>
|
| 25 |
+
},
|
| 26 |
+
{
|
| 27 |
+
"id": 3,
|
| 28 |
"title": "<string>",
|
| 29 |
"elevator": "<string>",
|
| 30 |
"overview": "<string>",
|
| 31 |
+
"primary_tech_stack": ["<string>"],
|
| 32 |
"difficulty": "<Easy|Medium|Hard>",
|
| 33 |
"time_estimate_hours": <number>
|
| 34 |
}
|
| 35 |
],
|
| 36 |
+
"best_pick_id": <1|2|3>,
|
| 37 |
"best_pick_reason": "<string>"
|
| 38 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
""".strip()
|
| 40 |
|
|
|
|
| 41 |
DETAIL_PROMPT_TEMPLATE = """
|
| 42 |
+
You are an AI that outputs ONLY valid JSON.
|
| 43 |
+
Do NOT include explanations. Do NOT include any text before or after the JSON.
|
| 44 |
+
Expand the hackathon idea "{IDEA_TITLE}" (ID: {IDEA_ID}) into a 48-hour build plan.
|
| 45 |
+
Return ONLY JSON in this exact format:
|
| 46 |
{
|
| 47 |
"id": {IDEA_ID},
|
| 48 |
"title": "{IDEA_TITLE}",
|
| 49 |
+
"mermaid_architecture": "graph LR; A-->B;",
|
| 50 |
"phases": [
|
| 51 |
{
|
| 52 |
"name": "<MVP|Polish|Demo>",
|
| 53 |
"time_hours": <number>,
|
| 54 |
+
"tasks": ["<string>", "<string>"],
|
| 55 |
+
"deliverables": ["<string>", "<string>"]
|
| 56 |
}
|
| 57 |
],
|
| 58 |
"critical_code_snippets": [
|
| 59 |
{
|
| 60 |
"title": "<string>",
|
| 61 |
+
"language": "javascript",
|
| 62 |
+
"code": "<string>"
|
| 63 |
}
|
| 64 |
],
|
| 65 |
"ui_components": [
|
|
|
|
| 71 |
"risks_and_mitigations": [
|
| 72 |
{
|
| 73 |
"risk": "<string>",
|
| 74 |
+
"mitigation": "<string>"
|
| 75 |
}
|
| 76 |
]
|
| 77 |
}
|
| 78 |
+
""".strip()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
requirements.txt
CHANGED
|
@@ -1,5 +1,7 @@
|
|
| 1 |
-
fastapi
|
| 2 |
-
uvicorn
|
| 3 |
-
transformers
|
| 4 |
-
torch
|
| 5 |
-
|
|
|
|
|
|
|
|
|
| 1 |
+
fastapi==0.104.1
|
| 2 |
+
uvicorn[standard]==0.24.0
|
| 3 |
+
transformers==4.35.2
|
| 4 |
+
torch==2.1.0
|
| 5 |
+
pydantic==2.5.0
|
| 6 |
+
sentencepiece==0.1.99
|
| 7 |
+
protobuf==4.25.1
|