Bhanushray commited on
Commit
bdbbcf1
·
verified ·
1 Parent(s): 63afdf2

Upload 4 files

Browse files
Files changed (4) hide show
  1. DockerFile +22 -0
  2. app.py +54 -0
  3. model_handler.py +33 -0
  4. requirements.txt +7 -0
DockerFile ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # USE THE OFFICIAL PYTHON 3.9 SLIM IMAGE
2
+ FROM python:3.9-slim
3
+
4
+ # SET THE WORKING DIRECTORY INSIDE THE CONTAINER
5
+ WORKDIR /code
6
+
7
+ # COPY THE REQUIREMENTS FILE FIRST FOR EFFICIENT CACHING
8
+ COPY ./requirements.txt /code/requirements.txt
9
+
10
+ # INSTALL ALL THE REQUIRED LIBRARIES
11
+ RUN pip install --no-cache-dir --upgrade pip -r /code/requirements.txt
12
+
13
+ # COPY THE REST OF YOUR APPLICATION CODE
14
+ COPY ./app.py /code/app.py
15
+ COPY ./model_handler.py /code/model_handler.py
16
+
17
+ # HUGGING FACE SPACES RUNS APPS ON PORT 7860
18
+ EXPOSE 7860
19
+
20
+ # THE COMMAND TO START THE GUNICORN PRODUCTION SERVER
21
+ # IT RUNS THE 'FLASK_APP' OBJECT FROM THE 'app.py' FILE
22
+ CMD ["gunicorn", "--bind", "0.0.0.0:7860", "app:FLASK_APP"]
app.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, jsonify
2
+ from model_handler import MODEL_HANDLER
3
+
4
+ # INITIALIZING THE FLASK APP
5
+ FLASK_APP = Flask(__name__)
6
+
7
+ # --- API ENDPOINT DEFINITIONS ---
8
+
9
+ @FLASK_APP.route("/", methods=["GET"])
10
+ def health_Check():
11
+ # HEALTH CHECKING ENDPOINT TO CONFIRM THE API IS LIVE
12
+ return jsonify({
13
+ "status": "ok",
14
+ "message": "Semantic Similarity API is operational."
15
+ })
16
+
17
+ @FLASK_APP.route("/predict", methods=["POST"])
18
+ def predict_Handler():
19
+ """
20
+ HANDLES THE PREDICTION REQUEST.
21
+ """
22
+ # GETTING THE JSON PAYLOAD FROM THE REQUEST
23
+ input_Payload = request.get_json()
24
+
25
+ # VALIDATING THE INCOMING DATA
26
+ if not input_Payload:
27
+ return jsonify({"error": "BAD REQUEST: Missing JSON body."}), 400
28
+
29
+ text1_Value = input_Payload.get("text1")
30
+ text2_Value = input_Payload.get("text2")
31
+
32
+ if not text1_Value or not text2_Value:
33
+ return jsonify({"error": "BAD REQUEST: 'text1' and 'text2' are required fields."}), 400
34
+
35
+ # PROCESSING THE REQUEST AND GET THE SCORE
36
+ try:
37
+ # USING THE MODEL HANDLER TO GET THE SIMILARITY SCORE
38
+ similarityScore = MODEL_HANDLER.calculate_Similarity(text1_Value, text2_Value)
39
+
40
+ # THE RESPONSE BODY
41
+ response_Body = {
42
+ "similarity_score": similarityScore
43
+ }
44
+
45
+ return jsonify(response_Body), 200
46
+
47
+ except Exception as e:
48
+ # CATCHING ANY UNEXPECTED ERRORS
49
+ print(f"INTERNAL ERROR: {e}")
50
+ return jsonify({"error": "An internal server error occurred."}), 500
51
+
52
+ if __name__ == "__main__":
53
+ # THIS PART IS ONLY FOR LOCAL TESTING. GUNICORN WILL RUN THE APP ON HUGGING FACE
54
+ FLASK_APP.run(host="0.0.0.0", port=8000, debug=True)
model_handler.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sentence_transformers.cross_encoder import CrossEncoder
2
+ import torch
3
+
4
+ class SimilarityModelHandler:
5
+ # HOLDING THE MODEL INSTANCE TO PREVENT RELOADING
6
+ SIMILARITY_MODEL_INSTANCE = None
7
+
8
+ def __init__(self):
9
+ # CONSTRUCTOR: LOADING THE MODEL IF IT DOESN'T EXIST
10
+ if not SimilarityModelHandler.SIMILARITY_MODEL_INSTANCE:
11
+ print("INITIALIZING AND LOADING THE MODEL...")
12
+ # CHECKING FOR GPU, FALLBACK TO CPU
13
+ device = 'cuda' if torch.cuda.is_available() else 'cpu'
14
+ print(f"SERVICE IS RUNNING ON DEVICE: {device}")
15
+
16
+ # LOADING THE PRE-TRAINED CROSS-ENCODER MODEL
17
+ model_Name = 'cross-encoder/stsb-roberta-large'
18
+ SimilarityModelHandler.SIMILARITY_MODEL_INSTANCE = CrossEncoder(model_Name, device=device)
19
+ print("MODEL LOADED SUCCESSFULLY.")
20
+
21
+ def calculate_Similarity(self, text_One: str, text_Two: str) -> float:
22
+ """
23
+ CALCULATES THE SIMILARITY SCORE BETWEEN TWO TEXTS.
24
+ """
25
+ # GETTING THE SCORE FROM THE MODEL( 0-1 )
26
+ finalScore = self.SIMILARITY_MODEL_INSTANCE.predict([(text_One, text_Two)])
27
+
28
+ # CONVERTING FROM NUMPY ARRAY TO A SIMPLE FLOAT
29
+ return finalScore.item()
30
+
31
+
32
+ # CREATING A SINGLE INSTANCE TO BE USED BY THE API
33
+ MODEL_HANDLER = SimilarityModelHandler()
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ # Libraries for the model
2
+ sentence-transformers>=2.2.0
3
+ torch>=1.9.0
4
+
5
+ # Libraries for the API server
6
+ Flask>=2.0.0
7
+ gunicorn>=20.0.0