Commit
·
afbf5e5
1
Parent(s):
44dd2f2
feat: Added application file
Browse files- Dockerfile +11 -0
- config/config.ini +6 -0
- data/data.json +23 -0
- data/possible_labels.json +4 -0
- requirements.txt +6 -0
- src/SentimentAndIntentionAnalysis.py +26 -0
- src/api.py +40 -0
- src/data_loader.py +31 -0
Dockerfile
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.9
|
| 2 |
+
|
| 3 |
+
WORKDIR /code
|
| 4 |
+
|
| 5 |
+
COPY ./requirements.txt /code/requirements.txt
|
| 6 |
+
|
| 7 |
+
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
|
| 8 |
+
|
| 9 |
+
COPY . .
|
| 10 |
+
|
| 11 |
+
CMD ["uvicorn", "src.api:app", "--host", "0.0.0.0", "--port", "7860"]
|
config/config.ini
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[data]
|
| 2 |
+
data_dir = C:\Users\kbuzlu\PycharmProjects\SentimentIntentionAnalysis\data\data.json
|
| 3 |
+
possible_labels_dir = C:\Users\kbuzlu\PycharmProjects\SentimentIntentionAnalysis\data\possible_labels.json
|
| 4 |
+
|
| 5 |
+
[model]
|
| 6 |
+
name = facebook/bart-large-mnli
|
data/data.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{"text": "Hello! Thank you for reaching out to our customer service. How can I assist you today?"},
|
| 3 |
+
{"text": "Hi! I'm interested in purchasing the new iPhone 14."},
|
| 4 |
+
{"text": "That's fantastic to hear! The iPhone 14 is a great choice. Which specific model are you considering?"},
|
| 5 |
+
{"text": "I'm looking at the iPhone 14 Pro Max with the highest storage capacity."},
|
| 6 |
+
{"text": "Excellent choice! Would you like to buy it outright or explore our payment plan options?"},
|
| 7 |
+
{"text": "I'd like to explore the payment plan options, please."},
|
| 8 |
+
{"text": "Of course. We offer several flexible payment plans. Could you please provide your information so I can assist you further?"},
|
| 9 |
+
{"text": "Sure, I'm ready."},
|
| 10 |
+
{"text": "Firstly, may I have your full name and email address?"},
|
| 11 |
+
{"text": "My name is John Doe and my email address is johndoe@example.com."},
|
| 12 |
+
{"text": "Thank you, John. Now, would you prefer a 12-month or 24-month payment plan?"},
|
| 13 |
+
{"text": "I think a 24-month plan would be more manageable for me."},
|
| 14 |
+
{"text": "Understood. Do you have any devices you'd like to trade in towards your purchase?"},
|
| 15 |
+
{"text": "Yes, I have an iPhone 12 Pro that I'd like to trade in."},
|
| 16 |
+
{"text": "I see. Let me check our current offers and see if we have any promotions that would benefit you."},
|
| 17 |
+
{"text": "Based on the condition of your iPhone 12 Pro, I'm sorry to say that we can't offer much for a trade-in value."},
|
| 18 |
+
{"text": "That's disappointing to hear."},
|
| 19 |
+
{"text": "I understand your frustration. Is there anything else I can assist you with?"},
|
| 20 |
+
{"text": "No, that's all for now. Thank you!"},
|
| 21 |
+
{"text": "You're welcome! If you have any further questions, feel free to reach out to us anytime. Have a great day!"}
|
| 22 |
+
]
|
| 23 |
+
|
data/possible_labels.json
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"sentiment_labels": ["Positive", "Negative", "Neutral"],
|
| 3 |
+
"intention_labels": ["Inquire", "Inform", "Payment", "Price", "Trade In", "Discount", "Complaint", "Approve", "Selling", "Confusion", "Change Package", "Upgrade", "Purchase", "Help"]
|
| 4 |
+
}
|
requirements.txt
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
fastapi
|
| 2 |
+
uvicorn
|
| 3 |
+
torch
|
| 4 |
+
configparser
|
| 5 |
+
transformers
|
| 6 |
+
pydantic
|
src/SentimentAndIntentionAnalysis.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from transformers import pipeline, BartTokenizer, BartForSequenceClassification
|
| 2 |
+
class ZeroShotClassifier:
|
| 3 |
+
|
| 4 |
+
def __init__(self, model_name, sentiment_labels, intention_labels):
|
| 5 |
+
self.model = self.create_model(model_name)
|
| 6 |
+
self.model_name = model_name
|
| 7 |
+
self.sentiment_labels = sentiment_labels
|
| 8 |
+
self.intention_labels = intention_labels
|
| 9 |
+
|
| 10 |
+
def create_model(self, model_name):
|
| 11 |
+
# Create Model
|
| 12 |
+
tokenizer = BartTokenizer.from_pretrained(model_name)
|
| 13 |
+
model = BartForSequenceClassification.from_pretrained(model_name)
|
| 14 |
+
classifier = pipeline("zero-shot-classification", model=model, tokenizer=tokenizer)
|
| 15 |
+
return classifier
|
| 16 |
+
|
| 17 |
+
def analyze_text(self, text):
|
| 18 |
+
# Sentiment analysis
|
| 19 |
+
sentiment_result = self.model(text, self.sentiment_labels)
|
| 20 |
+
sentiment = sentiment_result["labels"][0]
|
| 21 |
+
|
| 22 |
+
# Intention analysis
|
| 23 |
+
intention_result = self.model(text, self.intention_labels)
|
| 24 |
+
intention = intention_result["labels"][0]
|
| 25 |
+
|
| 26 |
+
return {"sentiment": sentiment, "intention": intention}
|
src/api.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import configparser
|
| 2 |
+
|
| 3 |
+
from fastapi import FastAPI
|
| 4 |
+
from fastapi.middleware.cors import CORSMiddleware
|
| 5 |
+
from pydantic import BaseModel
|
| 6 |
+
from SentimentAndIntentionAnalysis import ZeroShotClassifier
|
| 7 |
+
from data_loader import *
|
| 8 |
+
|
| 9 |
+
# Initialize FastAPI app
|
| 10 |
+
app = FastAPI()
|
| 11 |
+
app.add_middleware(CORSMiddleware,
|
| 12 |
+
allow_origins=["http://localhost:8501"],
|
| 13 |
+
allow_credentials=True,
|
| 14 |
+
allow_methods=["*"],
|
| 15 |
+
allow_headers=["*"],)
|
| 16 |
+
#Get model_name, data_path and labels_path
|
| 17 |
+
model_name, data_path, labels_path = get_config()
|
| 18 |
+
|
| 19 |
+
# Load sentiment labels and intention labels
|
| 20 |
+
sentiment_labels, intention_labels = load_labels(labels_path)
|
| 21 |
+
# Create Analzer
|
| 22 |
+
analyzer = ZeroShotClassifier(model_name=model_name, sentiment_labels=sentiment_labels, intention_labels=intention_labels)
|
| 23 |
+
|
| 24 |
+
class AnalysisResult(BaseModel):
|
| 25 |
+
sentiment: str
|
| 26 |
+
intention: str
|
| 27 |
+
|
| 28 |
+
class Text(BaseModel):
|
| 29 |
+
text: str
|
| 30 |
+
|
| 31 |
+
@app.post("/analyze/")
|
| 32 |
+
def analyze_text(data: Text):
|
| 33 |
+
result = analyzer.analyze_text(data.text)
|
| 34 |
+
return AnalysisResult(sentiment=result["sentiment"], intention=result["intention"])
|
| 35 |
+
|
| 36 |
+
if __name__ == "__main__":
|
| 37 |
+
import uvicorn
|
| 38 |
+
uvicorn.run("api:app", host="0.0.0.0", port=8000, reload=True)
|
| 39 |
+
|
| 40 |
+
|
src/data_loader.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import configparser
|
| 2 |
+
import json
|
| 3 |
+
def get_config():
|
| 4 |
+
# Read config
|
| 5 |
+
config = configparser.ConfigParser()
|
| 6 |
+
config.read(r"C:\Users\kbuzlu\PycharmProjects\SentimentIntentionAnalysis\config\config.ini")
|
| 7 |
+
|
| 8 |
+
# Get model_name
|
| 9 |
+
model_name = config["model"]["name"]
|
| 10 |
+
|
| 11 |
+
# Get data path
|
| 12 |
+
data_path = config["data"]["data_dir"]
|
| 13 |
+
|
| 14 |
+
# Get possible labels
|
| 15 |
+
labels_path = config["data"]["possible_labels_dir"]
|
| 16 |
+
return model_name, data_path, labels_path
|
| 17 |
+
|
| 18 |
+
def load_data(data_path):
|
| 19 |
+
# Load data
|
| 20 |
+
with open(data_path, "r") as file:
|
| 21 |
+
data = json.load(file)
|
| 22 |
+
texts = [entry["text"] for entry in data]
|
| 23 |
+
return texts
|
| 24 |
+
|
| 25 |
+
def load_labels(labels_path):
|
| 26 |
+
# Load labels
|
| 27 |
+
with open(labels_path, "r") as file:
|
| 28 |
+
data = json.load(file)
|
| 29 |
+
sentiment_labels = data["sentiment_labels"]
|
| 30 |
+
intention_labels = data["intention_labels"]
|
| 31 |
+
return sentiment_labels, intention_labels
|