|
"""
|
|
PULSE-7B Enhanced Handler
|
|
Ubden® Team - Edited by https://github.com/ck-cankurt
|
|
Support: Text, Image URLs, and Base64 encoded images
|
|
"""
|
|
|
|
import torch
|
|
from typing import Dict, List, Any
|
|
import base64
|
|
from io import BytesIO
|
|
from PIL import Image
|
|
import requests
|
|
|
|
|
|
class EndpointHandler:
|
|
def __init__(self, path=""):
|
|
"""
|
|
Hey there! Let's get this PULSE-7B model up and running.
|
|
We'll load it from the HuggingFace hub directly, so no worries about local files.
|
|
|
|
Args:
|
|
path: Model directory path (we actually ignore this and load from HF hub)
|
|
"""
|
|
print("🚀 Starting up PULSE-7B handler...")
|
|
print("📝 Enhanced by Ubden® Team - github.com/ck-cankurt")
|
|
|
|
|
|
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
|
print(f"🖥️ Running on: {self.device}")
|
|
|
|
try:
|
|
|
|
from transformers import pipeline
|
|
|
|
print("📦 Fetching model from HuggingFace Hub...")
|
|
self.pipe = pipeline(
|
|
"text-generation",
|
|
model="PULSE-ECG/PULSE-7B",
|
|
torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
|
|
device=0 if torch.cuda.is_available() else -1,
|
|
trust_remote_code=True,
|
|
model_kwargs={
|
|
"low_cpu_mem_usage": True,
|
|
"use_safetensors": True
|
|
}
|
|
)
|
|
print("✅ Model loaded successfully via pipeline!")
|
|
|
|
except Exception as e:
|
|
print(f"⚠️ Pipeline didn't work out: {e}")
|
|
print("🔄 Let me try a different approach...")
|
|
|
|
try:
|
|
|
|
from transformers import AutoTokenizer, LlamaForCausalLM
|
|
|
|
|
|
print("📖 Setting up tokenizer...")
|
|
self.tokenizer = AutoTokenizer.from_pretrained(
|
|
"PULSE-ECG/PULSE-7B",
|
|
trust_remote_code=True
|
|
)
|
|
|
|
|
|
print("🧠 Loading the model as Llama...")
|
|
self.model = LlamaForCausalLM.from_pretrained(
|
|
"PULSE-ECG/PULSE-7B",
|
|
torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
|
|
device_map="auto",
|
|
low_cpu_mem_usage=True,
|
|
trust_remote_code=True
|
|
)
|
|
|
|
|
|
if self.tokenizer.pad_token is None:
|
|
self.tokenizer.pad_token = self.tokenizer.eos_token
|
|
self.tokenizer.pad_token_id = self.tokenizer.eos_token_id
|
|
|
|
self.model.eval()
|
|
self.use_pipeline = False
|
|
print("✅ Model loaded successfully via direct loading!")
|
|
|
|
except Exception as e2:
|
|
print(f"😓 That didn't work either: {e2}")
|
|
|
|
self.pipe = None
|
|
self.model = None
|
|
self.tokenizer = None
|
|
self.use_pipeline = None
|
|
else:
|
|
self.use_pipeline = True
|
|
|
|
def process_image_input(self, image_input):
|
|
"""
|
|
Handle both URL and base64 image inputs like a champ!
|
|
|
|
Args:
|
|
image_input: Can be a URL string or base64 encoded image
|
|
|
|
Returns:
|
|
PIL Image object or None if something goes wrong
|
|
"""
|
|
try:
|
|
|
|
if isinstance(image_input, str) and (image_input.startswith('http://') or image_input.startswith('https://')):
|
|
print(f"🌐 Fetching image from URL: {image_input[:50]}...")
|
|
response = requests.get(image_input, timeout=10)
|
|
response.raise_for_status()
|
|
image = Image.open(BytesIO(response.content)).convert('RGB')
|
|
print("✅ Image downloaded successfully!")
|
|
return image
|
|
|
|
|
|
elif isinstance(image_input, str):
|
|
print("🔍 Decoding base64 image...")
|
|
|
|
if "base64," in image_input:
|
|
image_input = image_input.split("base64,")[1]
|
|
|
|
image_data = base64.b64decode(image_input)
|
|
image = Image.open(BytesIO(image_data)).convert('RGB')
|
|
print("✅ Image decoded successfully!")
|
|
return image
|
|
|
|
except Exception as e:
|
|
print(f"❌ Couldn't process the image: {e}")
|
|
return None
|
|
|
|
return None
|
|
|
|
def __call__(self, data: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|
"""
|
|
Main processing function - where the magic happens!
|
|
|
|
Args:
|
|
data: Input data with 'inputs' and optional 'parameters'
|
|
|
|
Returns:
|
|
List with the generated response
|
|
"""
|
|
|
|
if self.use_pipeline is None:
|
|
return [{
|
|
"generated_text": "Oops! Model couldn't load properly. Please check the deployment settings.",
|
|
"error": "Model initialization failed",
|
|
"handler": "Ubden® Team Enhanced Handler"
|
|
}]
|
|
|
|
try:
|
|
|
|
inputs = data.get("inputs", "")
|
|
text = ""
|
|
image = None
|
|
|
|
if isinstance(inputs, dict):
|
|
|
|
text = inputs.get("text", inputs.get("prompt", str(inputs)))
|
|
|
|
|
|
image_input = inputs.get("image", inputs.get("image_url", inputs.get("image_base64", None)))
|
|
if image_input:
|
|
image = self.process_image_input(image_input)
|
|
if image:
|
|
|
|
text = f"[Image provided - {image.size[0]}x{image.size[1]} pixels] {text}"
|
|
else:
|
|
|
|
text = str(inputs)
|
|
|
|
if not text:
|
|
return [{"generated_text": "Hey, I need some text to work with! Please provide an input."}]
|
|
|
|
|
|
parameters = data.get("parameters", {})
|
|
max_new_tokens = min(parameters.get("max_new_tokens", 256), 1024)
|
|
temperature = parameters.get("temperature", 0.7)
|
|
top_p = parameters.get("top_p", 0.95)
|
|
do_sample = parameters.get("do_sample", True)
|
|
repetition_penalty = parameters.get("repetition_penalty", 1.0)
|
|
|
|
|
|
if self.use_pipeline:
|
|
result = self.pipe(
|
|
text,
|
|
max_new_tokens=max_new_tokens,
|
|
temperature=temperature,
|
|
top_p=top_p,
|
|
do_sample=do_sample,
|
|
repetition_penalty=repetition_penalty,
|
|
return_full_text=False
|
|
)
|
|
|
|
|
|
if isinstance(result, list) and len(result) > 0:
|
|
return [{"generated_text": result[0].get("generated_text", "")}]
|
|
else:
|
|
return [{"generated_text": str(result)}]
|
|
|
|
|
|
else:
|
|
|
|
encoded = self.tokenizer(
|
|
text,
|
|
return_tensors="pt",
|
|
truncation=True,
|
|
max_length=2048
|
|
)
|
|
|
|
input_ids = encoded["input_ids"].to(self.device)
|
|
attention_mask = encoded.get("attention_mask")
|
|
if attention_mask is not None:
|
|
attention_mask = attention_mask.to(self.device)
|
|
|
|
|
|
with torch.no_grad():
|
|
outputs = self.model.generate(
|
|
input_ids,
|
|
attention_mask=attention_mask,
|
|
max_new_tokens=max_new_tokens,
|
|
temperature=temperature,
|
|
top_p=top_p,
|
|
do_sample=do_sample,
|
|
repetition_penalty=repetition_penalty,
|
|
pad_token_id=self.tokenizer.pad_token_id,
|
|
eos_token_id=self.tokenizer.eos_token_id
|
|
)
|
|
|
|
|
|
generated_ids = outputs[0][input_ids.shape[-1]:]
|
|
generated_text = self.tokenizer.decode(
|
|
generated_ids,
|
|
skip_special_tokens=True,
|
|
clean_up_tokenization_spaces=True
|
|
)
|
|
|
|
return [{"generated_text": generated_text}]
|
|
|
|
except Exception as e:
|
|
error_msg = f"Something went wrong during generation: {str(e)}"
|
|
print(f"❌ {error_msg}")
|
|
return [{
|
|
"generated_text": "",
|
|
"error": error_msg,
|
|
"handler": "Ubden® Team Enhanced Handler"
|
|
}] |