Spaces:
Paused
Paused
File size: 3,797 Bytes
f814c93 cb51934 f814c93 cb51934 007c634 f814c93 cb51934 f814c93 32e01fc f814c93 cb51934 007c634 f814c93 007c634 f814c93 cb51934 f814c93 cb51934 f814c93 29e5c2f 007c634 f814c93 cb51934 f814c93 29e5c2f 007c634 cb51934 f814c93 cb51934 f814c93 cb51934 f814c93 cb51934 f814c93 cb51934 f814c93 adf7dca f814c93 adf7dca f814c93 adf7dca f814c93 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | # model_loader.py
import os
import torch
import gc
import json
from huggingface_hub import login
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
from peft import PeftModel
# CONFIG - change these if your repo name differs
BASE_MODEL = "meta-llama/Llama-3.2-3B" # or local path if you prefer
ADAPTER = "iatechaways/crm_model" # your LoRA adapter on HF
# Get HF token from environment
HF_TOKEN = os.getenv("HF_TOKEN")
# NOTE: For ZeroGPU we LOAD on CPU and move to GPU only during inference.
def load_model_cpu():
"""
Load base model + adapter into CPU memory (device_map='cpu' or low mem).
Return a dict that holds references to model and tokenizer.
"""
# load tokenizer
tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL, use_fast=True, token=HF_TOKEN)
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"
# load base model on CPU to minimize early GPU allocation
base = AutoModelForCausalLM.from_pretrained(
BASE_MODEL,
device_map={"": "cpu"},
torch_dtype=torch.float32,
low_cpu_mem_usage=True,
token=HF_TOKEN
)
model = PeftModel.from_pretrained(
base,
ADAPTER,
device_map={"": "cpu"},
torch_dtype=torch.float32,
is_trainable=False,
low_cpu_mem_usage=True,
token=HF_TOKEN
)
# don't create pipeline here; we'll call generate with model directly
return {
"tokenizer": tokenizer,
"model": model,
"base_name": BASE_MODEL,
"adapter": ADAPTER
}
def move_model_to_gpu(info: dict):
"""Move model to GPU and set dtype to float16 for inference speed."""
if not torch.cuda.is_available():
return
model = info["model"]
# move to cuda
model.to("cuda")
# if tokenizer/pipeline required, we keep tokenizer on CPU
torch.cuda.empty_cache()
def move_model_to_cpu(info: dict):
"""Move model back to CPU & free GPU memory."""
if not torch.cuda.is_available():
return
model = info["model"]
model.to("cpu")
torch.cuda.empty_cache()
gc.collect()
def generate_with_model(info: dict, email_text: str, mail_type: str, client_data: dict, max_new_tokens: int = 200):
"""Run text generation using the loaded model (assumes model on device)."""
tokenizer = info["tokenizer"]
model = info["model"]
device = next(model.parameters()).device
# Prepare client context
client_context = (
f"Client Info:\n"
f"Name: {client_data.get('name')}\n"
f"Policy No: {client_data.get('policy_number')}\n"
f"Plan: {client_data.get('indiafirst_life_insurance_plan')}\n"
f"Status: {client_data.get('status')}\n"
f"Premium: ₹{client_data.get('premium_amt')}\n"
f"Due Date: {client_data.get('premium_due_date')}\n\n"
)
prompt = f"""Email Category: {mail_type}
### Instruction:
You are an LIC customer-service assistant. Respond politely and concisely (2–5 sentences).
Do NOT invent facts that are not present in the client data. If data is missing, ask the customer to provide correct details.
{client_context}
### Input:
{email_text}
### Response:
"""
inputs = tokenizer(prompt, return_tensors="pt", truncation=True, max_length=1024).to(device)
with torch.no_grad():
outputs = model.generate(
**inputs,
max_new_tokens=max_new_tokens,
temperature=0.6,
top_p=0.9,
do_sample=True,
pad_token_id=tokenizer.eos_token_id,
repetition_penalty=1.12,
num_beams=1
)
decoded = tokenizer.decode(outputs[0], skip_special_tokens=True)
return decoded
|