Jordan Martens commited on
Commit
a328cf1
·
verified ·
1 Parent(s): 7c49514

Create handler.py

Browse files

added handler file for hf inference

Files changed (1) hide show
  1. handler.py +97 -0
handler.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import torch
3
+ from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
4
+
5
+ class EndpointHandler():
6
+ """
7
+ Custom handler for Hugging Face Inference Endpoints.
8
+ This handler will be used to load the model and tokenizer, and to handle inference requests.
9
+ """
10
+ def __init__(self, path=""):
11
+ """
12
+ Initializes the model and tokenizer. This method is called only once
13
+ when the endpoint is created.
14
+
15
+ Args:
16
+ path (str, optional): The path to the model directory.
17
+ If not provided, it defaults to the model loaded by the endpoint.
18
+ """
19
+ # Get the model ID from the environment variable set by Hugging Face Inference Endpoints
20
+ model_id = os.environ.get("HF_MODEL_ID", "Pragmanic0/Nomadic-ICDU-v8")
21
+
22
+ print(f"Loading model: {model_id}...")
23
+
24
+ # Load the tokenizer from the pretrained model
25
+ self.tokenizer = AutoTokenizer.from_pretrained(model_id)
26
+
27
+ # Load the model with recommended settings
28
+ # torch.bfloat16 is used for better performance on compatible hardware (e.g., Ampere GPUs)
29
+ # device_map="auto" automatically distributes the model across available GPUs
30
+ self.model = AutoModelForCausalLM.from_pretrained(
31
+ model_id,
32
+ torch_dtype=torch.bfloat16,
33
+ device_map="auto"
34
+ )
35
+
36
+ # Create a text generation pipeline
37
+ # This simplifies the process of generating text from a prompt
38
+ self.pipeline = pipeline(
39
+ "text-generation",
40
+ model=self.model,
41
+ tokenizer=self.tokenizer,
42
+ )
43
+
44
+ print("Model and pipeline loaded successfully.")
45
+
46
+ def __call__(self, data: dict) -> list:
47
+ """
48
+ This method is called for every inference request.
49
+
50
+ Args:
51
+ data (dict): The request payload from the user. It contains the inputs and parameters.
52
+
53
+ Returns:
54
+ list: A list containing the generated text in a dictionary.
55
+ """
56
+ # Extract the prompt from the input data
57
+ prompt = data.get("inputs", "")
58
+
59
+ # Extract generation parameters, with sensible defaults
60
+ # These parameters can be overridden by the user in the request
61
+ parameters = data.get("parameters", {})
62
+ max_new_tokens = parameters.get("max_new_tokens", 512)
63
+ temperature = parameters.get("temperature", 0.7)
64
+ top_p = parameters.get("top_p", 0.95)
65
+ do_sample = parameters.get("do_sample", True)
66
+
67
+ # Apply the specific prompt template required by the Nomadic-ICDU-v8 model
68
+ # This is crucial for getting high-quality responses from instruction-tuned models
69
+ formatted_prompt = f"<s>[INST] {prompt} [/INST]"
70
+
71
+ print(f"Generating text for prompt: '{prompt}'")
72
+
73
+ # Use the pipeline to generate text
74
+ # We pass the formatted prompt and the generation parameters
75
+ try:
76
+ generated = self.pipeline(
77
+ formatted_prompt,
78
+ max_new_tokens=max_new_tokens,
79
+ do_sample=do_sample,
80
+ temperature=temperature,
81
+ top_p=top_p,
82
+ return_full_text=False, # Only return the generated part, not the prompt
83
+ )
84
+
85
+ # The pipeline returns a list of dictionaries
86
+ # We extract the 'generated_text' from the first element
87
+ result = generated[0]
88
+
89
+ except Exception as e:
90
+ print(f"An error occurred during generation: {e}")
91
+ # Return an error message in the expected format
92
+ result = {"generated_text": f"Error: {e}"}
93
+
94
+ print(f"Generated text: {result['generated_text']}")
95
+
96
+ # Return the result in a list, as expected by the Inference Endpoints framework
97
+ return [result]