Hi everyone, I have been struggling for a quite a bit with a problem I’m having. So, to provide context, I fine-tuned a Distilbert model with LoRA (PEFT) to save on costs and also to explore this method (after learning about it recently and seeing some great content on it from HuggingFace). I fine-tuned the distilbert-base-uncased model with a HuggingFace estimator in Sagemaker for a sentiment analysis task and it works just fine there. I can get predictions from my endpoint no problem.
I then wanted to use this deployed model in a web app that takes in movie reviews, then communicated with my model to get predictions via Amazon API Gateway and AWS Lambda.
This is my Lambda function
import json
import boto3
def lambda_handler(event, context):
# The SageMaker runtime is what allows us to invoke the endpoint that we've created.
runtime = boto3.Session().client('sagemaker-runtime')
# Put incoming review in the format the model expects and add truncation so that it can handle really long reviews
response_body_param = {"inputs": event['body'],"parameters": {"truncation": True}}
# enter the endpoint name
endpoint_name = 'endpoint-huggingface-pytorch-inference-2023-07-20-01-45-57-792'
try:
# Now we use the SageMaker runtime to invoke our endpoint, sending the review we were given
response = runtime.invoke_endpoint(EndpointName = endpoint_name, # The name of the endpoint we created
ContentType = 'application/json', # The data format that is expected into the model
Accept = 'application/json', # The data format that is expected out of the model
Body = json.dumps(response_body_param)) # The actual review (formatted to be input to model)
# The response is an HTTP response whose body contains the result of our inference
result_output = response['Body'].read().decode()
result = json.loads(result_output)[0]
#result = json.loads(response.content.decode("utf-8"))
label_mapping_dict = {'LABEL_0':0, 'LABEL_1':1}
result['label'] = label_mapping_dict[result['label']]
return {
'statusCode' : 200,
'headers' : { 'Content-Type' : 'application/json', 'Access-Control-Allow-Origin' : '*' },
'body' : str(result)
}
except Exception as e:
print(repr(e))
return {
"statusCode": 500,
"headers": {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials": True,
},
"body": json.dumps({"error": repr(e)}),
}
and when I test it e.g. with the review “The movie was sensational. I loved it.”, it works just fine as seen below:
Test Event Name
test_event
Response
{
"statusCode": 200,
"headers": {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*"
},
"body": "{'label': 1, 'score': 0.9998412132263184}"
}
I also did a test on my API Gateway and it works as seen below:
However, when I am trying to send a review through from the website to the model and click submit, i get the error:
{"error": "ModelError('An error occurred (ModelError) when calling the InvokeEndpoint operation: Received client error (400) from primary with message \"{\\n \"code\": 400,\\n \"type\": \"InternalServerException\",\\n \"message\": \"You need to specify either `text` or `text_target`.\"\\n}\\n\". See https://us-east-1.console.aws.amazon.com/cloudwatch/home?region=us-east-1#logEventViewer:group=/aws/sagemaker/Endpoints/endpoint-huggingface-pytorch-inference-2023-07-20-01-45-57-792 in account 113878691707 for more information.')"}
Has anyone experienced this before? I would really appreciate the help, so I can understand where I’m going wrong here.
Also, see the website code below:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Sentiment Analysis Web App</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link href='https://fonts.googleapis.com/css?family=Londrina+Shadow' rel='stylesheet' type='text/css'>
<style>
body, html {
height: 100%;
}
.bg {
/* The image used */
background-image: url("https://images5.alphacoders.com/329/329544.jpg");
/* Full height */
height: 100%;
/* Center and scale the image nicely */
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
h1 {
font-family: 'Londrina Shadow', cursive;
text-align: center;
font-size: 55px;
color: Black;
}
.color-it {
/* The color of the text */
color:rgba(255, 255, 255, 0.85)
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script>
"use strict";
try {
function submitForm(oFormElement) {
var xhr = new XMLHttpRequest();
xhr.onload = function() {
var result = JSON.parse(xhr.responseText);
var label = result.label;
var score = result.score;
var scorePercentage = (score * 100).toFixed(1);
var resultElement = document.getElementById('result');
if (label == 0) {
resultElement.className = 'bg-danger';
resultElement.innerHTML = 'Your review was NEGATIVE! (I am ' + scorePercentage +'% sure of this)';
} else {
resultElement.className = 'bg-success';
resultElement.innerHTML = 'Your review was POSITIVE! (I am ' + scorePercentage +'% sure of this)';
}
}
xhr.open (oFormElement.method, oFormElement.action, true);
var review = document.getElementById('review');
xhr.send (review.value);
return false;
}
} catch (error) {
console.error('Error occurred:', error)
}
</script>
</head>
<body>
<div class="bg">
<div class="container">
<h1 id="title-color"><b>Is your movie review positive, or negative?</b></h1>
<p class="color-it"><b>Enter your review let's find out...</b></p>
<form method="POST"
action="https://uefbqdl3vj.execute-api.us-east-1.amazonaws.com/test"
onsubmit="return submitForm(this);" > <!-- (Old) API not live for this post on HF -->
<div class="form-group">
<label for="review" class="color-it"><b>Review:</b></label>
<textarea class="form-control" rows="5" id="review">Please write your review here.</textarea>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
<h1 class="bg-success" id="result"></h1>
</div>
</div>
</body>
</html>
(Dislaimer: I have deleted the endpoint that I shared in the code.)
Kind regards,
Henry