zabaanai-v2 / scripts /06_deploy_api.py
shaikhsalman's picture
ZabaanAI v2 complete project - Pakistan multilingual AI
c1f5657 verified
Raw
History Blame Contribute Delete
3.83 kB
#!/usr/bin/env python3
# ============================================================
# ZabaanAI-v2: FastAPI Server for Production Deployment
# Run: uvicorn scripts.06_deploy_api:app --host 0.0.0.0 --port 8000
# ============================================================
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional, List
import torch
import os, warnings
warnings.filterwarnings('ignore')
app = FastAPI(title='ZabaanAI v2 API', version='2.0.0',
description='Pakistan Multilingual AI - Supports Urdu, Punjabi, Sindhi, Pashto, Balochi, Saraiki, English, Roman Urdu')
USE_GPU = os.getenv('USE_GPU', '0') == '1'
MODEL_PATH = os.getenv('MODEL_PATH', 'shaikhsalman/zabaanai-v2-sft')
DEVICE = 'cuda' if USE_GPU else 'cpu'
# Load on startup
print(f'Loading model from {MODEL_PATH} on {DEVICE}...')
from transformers import AutoTokenizer, AutoModelForCausalLM
from peft import PeftModel
tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_code=True)
base = AutoModelForCausalLM.from_pretrained(
'Qwen/Qwen2.5-7B-Instruct',
device_map=DEVICE,
load_in_4bit=(not USE_GPU),
torch_dtype=torch.bfloat16 if USE_GPU else torch.float16,
trust_remote_code=True
)
model = PeftModel.from_pretrained(base, MODEL_PATH)
model.eval()
print('Model ready!')
SYSTEM_MSG = (
'You are ZabaanAI, a helpful multilingual AI assistant specializing in '
'Pakistan languages. Respond in the same language as the user.'
)
class Message(BaseModel):
role: str
content: str
class ChatRequest(BaseModel):
messages: List[Message]
max_tokens: int = 512
temperature: float = 0.7
top_p: float = 0.9
class GenerateRequest(BaseModel):
prompt: str
max_tokens: int = 512
temperature: float = 0.7
system: Optional[str] = None
def build_prompt(messages: List[Message], system: str = None) -> str:
sys_msg = system or SYSTEM_MSG
prompt = f'<|im_start|>system\n{sys_msg}<|im_end|>\n'
for m in messages:
role = 'user' if m.role in ('user', 'human') else 'assistant'
prompt += f'<|im_start|>{role}\n{m.content}<|im_end|>\n'
prompt += '<|im_start|>assistant\n'
return prompt
@app.post('/v1/chat/completions')
async def chat_completions(req: ChatRequest):
prompt = build_prompt(req.messages)
inputs = tokenizer(prompt, return_tensors='pt').to(model.device)
with torch.no_grad():
outputs = model.generate(
**inputs,
max_new_tokens=req.max_tokens,
temperature=req.temperature,
do_sample=True,
top_p=req.top_p,
pad_token_id=tokenizer.pad_token_id,
eos_token_id=tokenizer.eos_token_id,
)
response = tokenizer.decode(outputs[0][inputs['input_ids'].shape[1]:], skip_special_tokens=True)
return {'model': 'zabaanai-v2', 'choices': [{'message': {'role': 'assistant', 'content': response.strip()}}]}
@app.post('/v1/generate')
async def generate(req: GenerateRequest):
sys_msg = req.system or SYSTEM_MSG
prompt = f'<|im_start|>system\n{sys_msg}<|im_end|>\n<|im_start|>user\n{req.prompt}<|im_end|>\n<|im_start|>assistant\n'
inputs = tokenizer(prompt, return_tensors='pt').to(model.device)
with torch.no_grad():
outputs = model.generate(
**inputs, max_new_tokens=req.max_tokens,
temperature=req.temperature, do_sample=True,
pad_token_id=tokenizer.pad_token_id, eos_token_id=tokenizer.eos_token_id,
)
return {'text': tokenizer.decode(outputs[0][inputs['input_ids'].shape[1]:], skip_special_tokens=True).strip()}
@app.get('/health')
async def health():
return {'status': 'ok', 'model': 'zabaanai-v2'}
if __name__ == '__main__':
import uvicorn
uvicorn.run(app, host='0.0.0.0', port=8000)