Texbase / AgenticControl /Local_prompt.py
Asad999's picture
Initial clean deployment for Hugging Face Spaces (v5 - final fix)
d712cef
Raw
History Blame Contribute Delete
3.48 kB
import os
import torch
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from contextlib import asynccontextmanager
from transformers import AutoTokenizer, AutoModelForCausalLM
# We will store the loaded model and tokenizer here so they persist
ml_models = {}
# ── 1. Load Model Once on Startup ───────────────────────────────────────
@asynccontextmanager
async def lifespan(app: FastAPI):
print("⏳ Loading text model into memory... This might take a minute.")
# Point this to the local folder where you downloaded the weights
local_model_path = os.path.join(os.environ.get('WORKSPACE_ROOT', os.path.join(os.environ.get('WORKSPACE_ROOT', '.'), 'AgenticControl/local_qwen_model" )
# Added trust_remote_code=True here as well
tokenizer = AutoTokenizer.from_pretrained(
local_model_path,
trust_remote_code=True
)
model = AutoModelForCausalLM.from_pretrained(
local_model_path,
device_map="auto",
torch_dtype="auto", # Saves memory by using the optimal precision
trust_remote_code=True
)
ml_models["tokenizer"] = tokenizer
ml_models["model"] = model
print("βœ… Model loaded successfully! Server is ready for text requests.")
yield
# Clean up when the server shuts down
ml_models.clear()
print("πŸ›‘ Server shutting down, memory cleared.")
# Initialize the FastAPI app with the lifespan manager
app = FastAPI(lifespan=lifespan)
# ── 2. Define the Request Data Structure ────────────────────────────────
class GenerateRequest(BaseModel):
system_prompt: str
query: str
max_new_tokens: int = 200 # Increased default since text answers are usually longer
# ── 3. Create the API Endpoint ──────────────────────────────────────────
@app.post("/generate")
async def generate(request: GenerateRequest):
try:
tokenizer = ml_models["tokenizer"]
model = ml_models["model"]
# Format the prompt using the standard system/user role structure
messages = [
{"role": "system", "content": request.system_prompt},
{"role": "user", "content": request.query}
]
# Generate the formatted text string first (avoids dictionary/tensor errors)
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
# Tokenize the formatted string into PyTorch tensors and send to GPU/CPU
model_inputs = tokenizer([text], return_tensors="pt").to(model.device)
# Generate response
generated_ids = model.generate(
**model_inputs,
max_new_tokens=request.max_new_tokens
)
# Decode only the newly generated text (ignoring the input prompt tokens)
generated_ids = [
output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]
result_text = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
return {"response": result_text}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))