sakibzaman's picture
Update app.py
d161189 verified
Raw
History Blame Contribute Delete
4.44 kB
import gradio as gr
import os
import torch
from huggingface_hub import login
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline, BitsAndBytesConfig
from peft import PeftModel
# === Step 1: Login to Hugging Face ===
HF_TOKEN = os.environ.get("HF_TOKEN")
if not HF_TOKEN:
raise ValueError("❌ HF_TOKEN not set! Add it in Settings > Secrets.")
login(token=HF_TOKEN)
# === Step 2: Model IDs ===
BASE_MODEL_ID = "meta-llama/Llama-3.2-3B-Instruct"
ADAPTER_MODEL_ID = "sakibzaman/llama3.2-bengaliPunc-adapter-3b"
# Create a folder for offloading (required for low VRAM)
OFFLOAD_FOLDER = "./offload"
os.makedirs(OFFLOAD_FOLDER, exist_ok=True)
# === Step 3: 4-bit Quantization Config ===
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_use_double_quant=True,
)
# === Step 4: Load Model Safely ===
try:
print("🔍 Loading tokenizer...")
tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL_ID, token=HF_TOKEN)
tokenizer.pad_token = tokenizer.eos_token # Important for generation
print("🧠 Loading base model with 4-bit quantization...")
base_model = AutoModelForCausalLM.from_pretrained(
BASE_MODEL_ID,
quantization_config=bnb_config,
device_map="auto", # Automatically splits layers across GPU/CPU
torch_dtype=torch.float16,
token=HF_TOKEN,
offload_folder=OFFLOAD_FOLDER, # Required for CPU offloading
)
print("📎 Loading LoRA adapter...")
model = PeftModel.from_pretrained(
base_model,
ADAPTER_MODEL_ID,
token=HF_TOKEN,
offload_folder=OFFLOAD_FOLDER,
)
print("🚀 Creating generation pipeline...")
pipe = pipeline(
"text-generation",
model=model,
tokenizer=tokenizer,
max_new_tokens=64,
temperature=0.1,
top_p=0.9,
do_sample=True,
repetition_penalty=1.1,
pad_token_id=tokenizer.eos_token_id,
)
print("✅ Model loaded successfully!")
except Exception as e:
raise RuntimeError(f"❌ Failed to load model: {e}")
# === Step 5: Inference Function ===
def punctuate_text(text):
if not text.strip():
return "⚠️ Please enter some Bengali text."
try:
messages = [
{
"role": "system",
"content": "You are an expert in Bengali. Restore punctuation. Only return corrected text, nothing else."
},
{
"role": "user",
"content": text.strip()
}
]
outputs = pipe(messages)
response = outputs[0]["generated_text"]
# Extract only the assistant's part
for msg in reversed(response):
if msg["role"] == "assistant":
return msg["content"].strip()
return "�� Could not extract response."
except Exception as e:
return f"❌ Error: {str(e)}"
# === Step 6: Gradio UI & API ===
with gr.Blocks(theme=gr.themes.Soft(), title="🇧🇩 Bengali Punctuation") as demo:
gr.HTML("""
<h1 style="text-align: center;">🇧🇩 Bengali Punctuation Assistant</h1>
<p style="text-align: center;">
Powered by Llama-3.2-3B + LoRA • API enabled at <code>/api/predict</code>
</p>
""")
inp = gr.Textbox(label="📝 Input Bengali Text", placeholder="আমি ঢাকায় থাকি আমার বাড়ি সিলেটে", lines=4)
out = gr.Textbox(label="✅ Output", lines=4, interactive=False)
btn = gr.Button("🔤 Add Punctuation", variant="primary")
gr.Examples(
examples=[
["আপনি কেমন আছেন"],
["আমি ঢাকায় থাকি আমার বাড়ি সিলেটে"],
["তুমি কখন আসবে আমি অপেক্ষা করছি"]
],
inputs=inp,
outputs=out,
fn=punctuate_text,
label="Try Examples"
)
btn.click(fn=punctuate_text, inputs=inp, outputs=out, api_name="punctuate")
gr.HTML("""
<div style="text-align: center; margin-top: 20px; color: #555;">
💡 API: Use <code>/api/punctuate</code> for programmatic access
</div>
""")
# === Step 7: Launch ===
if __name__ == "__main__":
demo.queue(max_size=200).launch(debug=True, show_api=True)