Ephraimmm commited on
Commit
5d7d3c3
·
verified ·
1 Parent(s): c6d67d7

Update handler.py

Browse files
Files changed (1) hide show
  1. handler.py +131 -83
handler.py CHANGED
@@ -1,23 +1,16 @@
1
- from typing import Dict, List, Any
2
- import torch
3
  from transformers import AutoModelForCausalLM, AutoTokenizer
 
4
 
5
 
6
  class EndpointHandler:
7
- """
8
- Custom handler for HuggingFace Inference Endpoints
9
- Handles Nigerian Pidgin English text generation
10
- """
11
-
12
  def __init__(self, path: str = ""):
13
- # Load tokenizer first (safer for remote-code models)
14
  self.tokenizer = AutoTokenizer.from_pretrained(
15
  path,
16
  trust_remote_code=True,
17
- use_fast=True,
18
  )
19
 
20
- # Some tokenizers have no pad token; align to eos to avoid generate() errors
21
  if self.tokenizer.pad_token_id is None:
22
  self.tokenizer.pad_token = self.tokenizer.eos_token
23
 
@@ -27,85 +20,140 @@ class EndpointHandler:
27
  torch_dtype="auto",
28
  device_map="auto",
29
  trust_remote_code=True,
 
30
  )
31
- self.model.eval()
32
 
33
- self.default_system_prompt = (
34
- "You are a helpful assistant that speaks Nigerian Pidgin English. "
35
- "Respond naturally in Pidgin."
36
- )
37
 
38
- # Pick a stable device for inputs (first shard device if sharded)
39
- self._device = next(iter(self.model.hf_device_map.values()))
40
- if isinstance(self._device, str) and self._device.startswith("cuda"):
41
- self._device = torch.device(self._device)
42
- elif self._device == "cpu":
43
- self._device = torch.device("cpu")
44
-
45
- print("✓ Model and tokenizer loaded successfully")
46
-
47
- def __call__(self, data: Dict[str, Any]) -> List[Dict[str, Any]]:
48
- inputs_text = data.get("inputs", data)
49
- parameters = data.get("parameters", {}) or {}
50
-
51
- system_prompt = parameters.get("system_prompt", self.default_system_prompt)
52
- max_new_tokens = int(parameters.get("max_new_tokens", 100))
53
- temperature = float(parameters.get("temperature", 0.7))
54
- top_p = float(parameters.get("top_p", 0.9))
55
- top_k = int(parameters.get("top_k", 50))
56
- repetition_penalty = float(parameters.get("repetition_penalty", 1.1))
57
- do_sample = bool(parameters.get("do_sample", True))
58
- return_full_text = bool(parameters.get("return_full_text", False))
59
-
60
- # Prefer chat template if tokenizer supports it
61
- if hasattr(self.tokenizer, "apply_chat_template"):
62
- messages = []
63
- if system_prompt:
64
- messages.append({"role": "system", "content": system_prompt})
65
- messages.append({"role": "user", "content": str(inputs_text)})
66
-
67
- prompt = self.tokenizer.apply_chat_template(
68
- messages,
69
- tokenize=False,
70
- add_generation_prompt=True,
71
- )
72
- else:
73
- # Fallback
74
- if system_prompt:
75
- prompt = f"{system_prompt}\n\nUser: {inputs_text}\nAssistant:"
76
- else:
77
- prompt = str(inputs_text)
78
-
79
- enc = self.tokenizer(
80
- prompt,
81
- return_tensors="pt",
82
- truncation=True,
83
- max_length=2048,
84
- )
85
 
86
- # Move only input tensors to the chosen device
87
- enc = {k: v.to(self._device) for k, v in enc.items()}
88
 
89
  with torch.inference_mode():
90
- out = self.model.generate(
91
- **enc,
92
- max_new_tokens=max_new_tokens,
93
- do_sample=do_sample,
94
- temperature=temperature if do_sample else None,
95
- top_p=top_p if do_sample else None,
96
- top_k=top_k if do_sample else None,
97
- repetition_penalty=repetition_penalty,
98
  pad_token_id=self.tokenizer.pad_token_id,
99
- eos_token_id=self.tokenizer.eos_token_id,
100
  )
101
 
102
- decoded = self.tokenizer.decode(out[0], skip_special_tokens=True)
103
-
104
- if not return_full_text:
105
- # If we used chat template, easiest is to strip the prompt prefix
106
- if decoded.startswith(prompt):
107
- decoded = decoded[len(prompt):].strip()
108
- elif "Assistant:" in decoded:
109
- decoded = decoded.split("Assistant:")[-1].strip()
110
-
111
- return [{"generated_text": decoded}]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from transformers import AutoModelForCausalLM, AutoTokenizer
2
+ import torch
3
 
4
 
5
  class EndpointHandler:
 
 
 
 
 
6
  def __init__(self, path: str = ""):
7
+ # Load tokenizer
8
  self.tokenizer = AutoTokenizer.from_pretrained(
9
  path,
10
  trust_remote_code=True,
11
+ use_auth_token=True,
12
  )
13
 
 
14
  if self.tokenizer.pad_token_id is None:
15
  self.tokenizer.pad_token = self.tokenizer.eos_token
16
 
 
20
  torch_dtype="auto",
21
  device_map="auto",
22
  trust_remote_code=True,
23
+ use_auth_token=True,
24
  )
 
25
 
26
+ self.model.eval()
27
+ print(" Model loaded successfully")
 
 
28
 
29
+ def __call__(self, data):
30
+ prompt = data["inputs"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
+ inputs = self.tokenizer(prompt, return_tensors="pt")
33
+ inputs = {k: v.to(self.model.device) for k, v in inputs.items()}
34
 
35
  with torch.inference_mode():
36
+ outputs = self.model.generate(
37
+ **inputs,
38
+ max_new_tokens=128,
39
+ do_sample=True,
40
+ temperature=0.7,
41
+ top_p=0.9,
 
 
42
  pad_token_id=self.tokenizer.pad_token_id,
 
43
  )
44
 
45
+ text = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
46
+ return [{"generated_text": text}]
47
+
48
+
49
+ # from typing import Dict, List, Any
50
+ # import torch
51
+ # from transformers import AutoModelForCausalLM, AutoTokenizer
52
+
53
+
54
+ # class EndpointHandler:
55
+ # """
56
+ # Custom handler for HuggingFace Inference Endpoints
57
+ # Handles Nigerian Pidgin English text generation
58
+ # """
59
+
60
+ # def __init__(self, path: str = ""):
61
+ # # Load tokenizer first (safer for remote-code models)
62
+ # self.tokenizer = AutoTokenizer.from_pretrained(
63
+ # path,
64
+ # trust_remote_code=True,
65
+ # use_fast=True,
66
+ # )
67
+
68
+ # # Some tokenizers have no pad token; align to eos to avoid generate() errors
69
+ # if self.tokenizer.pad_token_id is None:
70
+ # self.tokenizer.pad_token = self.tokenizer.eos_token
71
+
72
+ # # Load model
73
+ # self.model = AutoModelForCausalLM.from_pretrained(
74
+ # path,
75
+ # torch_dtype="auto",
76
+ # device_map="auto",
77
+ # trust_remote_code=True,
78
+ # )
79
+ # self.model.eval()
80
+
81
+ # self.default_system_prompt = (
82
+ # "You are a helpful assistant that speaks Nigerian Pidgin English. "
83
+ # "Respond naturally in Pidgin."
84
+ # )
85
+
86
+ # # Pick a stable device for inputs (first shard device if sharded)
87
+ # self._device = next(iter(self.model.hf_device_map.values()))
88
+ # if isinstance(self._device, str) and self._device.startswith("cuda"):
89
+ # self._device = torch.device(self._device)
90
+ # elif self._device == "cpu":
91
+ # self._device = torch.device("cpu")
92
+
93
+ # print("✓ Model and tokenizer loaded successfully")
94
+
95
+ # def __call__(self, data: Dict[str, Any]) -> List[Dict[str, Any]]:
96
+ # inputs_text = data.get("inputs", data)
97
+ # parameters = data.get("parameters", {}) or {}
98
+
99
+ # system_prompt = parameters.get("system_prompt", self.default_system_prompt)
100
+ # max_new_tokens = int(parameters.get("max_new_tokens", 100))
101
+ # temperature = float(parameters.get("temperature", 0.7))
102
+ # top_p = float(parameters.get("top_p", 0.9))
103
+ # top_k = int(parameters.get("top_k", 50))
104
+ # repetition_penalty = float(parameters.get("repetition_penalty", 1.1))
105
+ # do_sample = bool(parameters.get("do_sample", True))
106
+ # return_full_text = bool(parameters.get("return_full_text", False))
107
+
108
+ # # Prefer chat template if tokenizer supports it
109
+ # if hasattr(self.tokenizer, "apply_chat_template"):
110
+ # messages = []
111
+ # if system_prompt:
112
+ # messages.append({"role": "system", "content": system_prompt})
113
+ # messages.append({"role": "user", "content": str(inputs_text)})
114
+
115
+ # prompt = self.tokenizer.apply_chat_template(
116
+ # messages,
117
+ # tokenize=False,
118
+ # add_generation_prompt=True,
119
+ # )
120
+ # else:
121
+ # # Fallback
122
+ # if system_prompt:
123
+ # prompt = f"{system_prompt}\n\nUser: {inputs_text}\nAssistant:"
124
+ # else:
125
+ # prompt = str(inputs_text)
126
+
127
+ # enc = self.tokenizer(
128
+ # prompt,
129
+ # return_tensors="pt",
130
+ # truncation=True,
131
+ # max_length=2048,
132
+ # )
133
+
134
+ # # Move only input tensors to the chosen device
135
+ # enc = {k: v.to(self._device) for k, v in enc.items()}
136
+
137
+ # with torch.inference_mode():
138
+ # out = self.model.generate(
139
+ # **enc,
140
+ # max_new_tokens=max_new_tokens,
141
+ # do_sample=do_sample,
142
+ # temperature=temperature if do_sample else None,
143
+ # top_p=top_p if do_sample else None,
144
+ # top_k=top_k if do_sample else None,
145
+ # repetition_penalty=repetition_penalty,
146
+ # pad_token_id=self.tokenizer.pad_token_id,
147
+ # eos_token_id=self.tokenizer.eos_token_id,
148
+ # )
149
+
150
+ # decoded = self.tokenizer.decode(out[0], skip_special_tokens=True)
151
+
152
+ # if not return_full_text:
153
+ # # If we used chat template, easiest is to strip the prompt prefix
154
+ # if decoded.startswith(prompt):
155
+ # decoded = decoded[len(prompt):].strip()
156
+ # elif "Assistant:" in decoded:
157
+ # decoded = decoded.split("Assistant:")[-1].strip()
158
+
159
+ # return [{"generated_text": decoded}]