RichardLu commited on
Commit
b92b201
·
verified ·
1 Parent(s): 46af991

Create handler.py

Browse files
Files changed (1) hide show
  1. handler.py +88 -0
handler.py ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from typing import Dict, List, Any
3
+ import torch
4
+ from unsloth import FastLanguageModel
5
+
6
+ class EndpointHandler:
7
+ def __init__(self, model_dir: str = ""):
8
+ print(f"[DEBUG] Original model_dir: {model_dir}")
9
+ # For this task, we force the model to be loaded from your checkpoint.
10
+ # (Note: In an endpoint, you may want to allow model_dir to be passed in,
11
+ # but here we override it for clarity.)
12
+ model_dir = "RichardLu/mistral7b_aspectsentiment_res"
13
+ print(f"[DEBUG] Using model_dir: {model_dir}")
14
+
15
+ # Inference configuration.
16
+ max_seq_length = 2048
17
+ load_in_4bit = True # Set to True or False as needed.
18
+
19
+ # Load the model and tokenizer from the checkpoint.
20
+ self.model, self.tokenizer = FastLanguageModel.from_pretrained(
21
+ model_name=model_dir,
22
+ max_seq_length=max_seq_length,
23
+ load_in_4bit=load_in_4bit
24
+ )
25
+ print("[DEBUG] Model and tokenizer loaded successfully.")
26
+
27
+ # Switch the model to inference mode.
28
+ FastLanguageModel.for_inference(self.model)
29
+
30
+ # Define the instructabsa instruction text with examples.
31
+ self.instructabsa_instruction = """Definition: The output will be 'positive' if the aspect identified in the sentence contains a positive sentiment. If the sentiment of the identified aspect in the input is negative the answer will be 'negative'.
32
+ Otherwise, the output should be 'neutral'. For aspects which are classified as noaspectterm, the sentiment is none.
33
+ Positive example 1-
34
+ input: With the great variety on the menu , I eat here often and never get bored. The aspect is menu.
35
+ output: positive
36
+ Positive example 2-
37
+ input: Great food, good size menu, great service and an unpretensious setting. The aspect is food.
38
+ output: positive
39
+ Negative example 1-
40
+ input: They did not have mayonnaise, forgot our toast, left out ingredients (ie cheese in an omelet), below hot temperatures and the bacon was so over cooked it crumbled on the plate when you touched it. The aspect is toast.
41
+ output: negative
42
+ Negative example 2-
43
+ input: The seats are uncomfortable if you are sitting against the wall on wooden benches. The aspect is seats.
44
+ output: negative
45
+ Neutral example 1-
46
+ input: I asked for seltzer with lime, no ice. The aspect is seltzer with lime.
47
+ output: neutral
48
+ Neutral example 2-
49
+ input: They wouldnt even let me finish my glass of wine before offering another. The aspect is glass of wine.
50
+ output: neutral
51
+ Now complete the following example-
52
+ """
53
+
54
+ # Define the Alpaca-style prompt template.
55
+ self.alpaca_prompt = """Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.
56
+ ### Instruction:
57
+ {}
58
+ ### Input:
59
+ {}
60
+ ### Response:
61
+ {}"""
62
+
63
+ def __call__(self, data: Dict[str, Any]) -> List[Dict[str, Any]]:
64
+ # Expecting two keys in the payload: 'review' and 'aspect'
65
+ review_text = data.get("review", "")
66
+ aspect = data.get("aspect", "")
67
+ if not review_text or not aspect:
68
+ return [{"error": "Both 'review' and 'aspect' are required."}]
69
+
70
+ # Build the combined input text.
71
+ full_input = f"{review_text} The aspect is {aspect}."
72
+ prompt = self.alpaca_prompt.format(self.instructabsa_instruction, full_input, "")
73
+
74
+ # Set device for inference.
75
+ device = "cuda" if torch.cuda.is_available() else "cpu"
76
+ inputs = self.tokenizer(prompt, return_tensors="pt", truncation=True).to(device)
77
+
78
+ # Generate the output.
79
+ output_ids = self.model.generate(**inputs, max_new_tokens=128)
80
+ output_text = self.tokenizer.decode(output_ids[0], skip_special_tokens=True)
81
+
82
+ # Extract the predicted sentiment.
83
+ if "### Response:" in output_text:
84
+ predicted = output_text.split("### Response:")[-1].strip()
85
+ else:
86
+ predicted = output_text.strip()
87
+
88
+ return [{"predicted": predicted}]