Metadata-Version: 2.3
Name: sentimotion
Version: 0.1.0
Summary: Add your description here
Requires-Dist: kaleido>=1.2.0
Requires-Dist: nltk>=3.9.2
Requires-Dist: numpy>=2.4.0
Requires-Dist: pandas>=2.3.3
Requires-Dist: plotly>=6.5.0
Requires-Dist: tensorflow>=2.20.0
Requires-Dist: textblob>=0.19.0
Requires-Dist: tf-keras>=2.20.1
Requires-Dist: torch>=2.9.1
Requires-Dist: tqdm>=4.67.1
Requires-Dist: transformers>=4.57.3
Requires-Python: >=3.13
Description-Content-Type: text/markdown

<!-- PROJECT LOGO -->
<br />
<div align="center">
  <h3 align="center">Sentimotion</h3>

  <p align="center">
    A repository containing the source code for the Sentimotion Python Package. The package can be used for undertaking a comparative analysis of Emotion and Sentiment modelling techniques, including visualisation over time.
    <br />
    <a href="https://github.com/KieronHolmes/Sentimotion"><strong>Read the paper »</strong></a>
  </p>
</div>

## About The Project

Sentimotion is a Python package used to assist with undertaking a Sentiment & Emotion analysis of a large, unlabelled corpora. The package uses a series of widely used classifiers, LLM's and custom implementations of Lexicons, such as NRC. We have used this package to undertake Dynamic Emotion and Dynamic Sentiment Analysis of Twitter datasets with in excess of 1 million Tweets.

The source code is optimised and will run on CPU-only systems; however, please bear in mind that performance is likely to be extremely limited.

## Requirements
- Python 3.13
- Kaleido
- NLTK
- Numpy
- Pandas
- Plotly
- Tensorflow
- TextBlob
- PyTorch
- TQDM
- Transformers

## Usage

### Installation

#### Development

For local development, we have utilised the Rust-based package and environment manager, [UV by Astral](https://docs.astral.sh/uv/). You are of course free to use whichever package manager you prefer, however, instructions have been provided for UV below for ease of use. The distributable version on this repository **only** supports the CPU-based version of PyTorch. You may wish to install the relevant GPU packages for your system.

1. Clone the repository locally
```
git clone https://github.com/KieronHolmes/Sentimotion.git
```

2. Change your current working directory to the Sentimotion directory
```
cd Sentimotion
```

3. Create a virtual environment and install dependencies
```
uv venv
uv sync
```

### Setup

#### Initiating Sentimotion
To use the Sentimotion package, you must initiate the Sentimotion class, passing values for **emotion_model** and **sentiment_model**. An example of how this can be done is as follows:
``` python
from sentimotion import Sentimotion

sentimotionmodel = Sentimotion(
    language="english",
    emotion_model=emotion_model, # Substitute this with your emotion model of choice
    sentiment_model=sentiment_model, # Substitute this with your emotion model of choice
    verbose=True,
)
```

#### Calculating Sentiment/Emotion
To calculate the Sentiment/Emotion of input content, you must provide a Python list to the **calculate** method in Sentimotion. An example of how this can be done is as follows:
``` python
documents_input = [
    "Lorem ipsum dolor sit amet",
    "Lorem ipsum dolor sit amet",
    "Lorem ipsum dolor sit amet"
]
sentimotionmodel.calculate(documents=documents_input)
```

#### Getting Document Info
Once the **calculate** method has been executed, you can access the calculated Sentiment and Emotion by using the **get_document_info** method, passing document info to the class. An example of the code to undertake this is as follows:
``` python
df = sentimotionmodel.get_document_info(documents=documents_input)
```
This is an instance of the ```pandas.DataFrame``` class, so you are free to interrogate or export the data as you wish, using functions such as ```.to_csv()```.

#### Visualisations

All visualisations return an instance of the ```plotly.graph_objects``` class. You are able to visualise and inspect these using all common functions such as ```fig.write_image()``` and ```fig.write_html()```

##### Sentiment - Pie Chart

``` python
fig = sentimotionmodel.visualise_sentiment_piechart()

```

##### Emotion - Pie Chart

``` python
fig = sentimotionmodel.visualise_emotion_piechart()
```

##### Sentiment & Emotion - Barchart

``` python
fig = sentimotionmodel.visualise_emotion_sentiment_barchart()
```

##### Sentiment Over Time
This visualisation has two required parameters:
- **nr_bins:** The number of timing bins to group data into. This should be a relatively low number for large datasets to speed up generation.
- **timestamps:** Provide timestamps correlating to the documents input when training the model.
``` python
fig = sentimotionmodel.visualise_sentiment_over_time(nr_bins=20, timestamps=timestamps_input)
```

##### Emotion Over Time
This visualisation has two required parameters:
- **nr_bins:** The number of timing bins to group data into. This should be a relatively low number for large datasets to speed up generation.
- **timestamps:** Provide timestamps correlating to the documents input when training the model.
``` python
fig = sentimotionmodel.visualise_emotion_over_time(nr_bins=20, timestamps=timestamps_input)
```

## Available Classifiers

### Emotion
This package supports the following Emotion Classifier Models:

#### CardiffNLP
``` python
from sentimotion.emotion import CardiffNLP as CardiffNLPEmotion

emotion_model = CardiffNLPEmotion()
```

This classifier has two required parameters during instantiation:
- **batch_size:** (default: 250) The number of input documents to include in each batch when running parallel or on GPU.
- **model_name:** (default: "cardiffnlp/twitter-roberta-base-emotion-multilabel-latest") The named huggingface transformer to use.

#### GoEmotions
``` python
from sentimotion.emotion import GoEmotions

emotion_model = GoEmotions()
```

This classifier has two required parameter during instantiation:
- **batch_size:** (default: 250) The number of input documents to include in each batch when running parallel or on GPU.
- **model_name:** (default: "SamLowe/roberta-base-go_emotions") The named huggingface transformer to use.

#### NRC
``` python
from sentimotion.emotion import NRC

emotion_model = NRC()
```

This classifier has one required parameter during instantiation:
- **lexicon_file:** (default: "./nrc-lexicons/NRC-Emotion-Lexicon-Wordlevel-v0.92.txt") The filepath to the NRC Lexicon.

#### OpenAI (API)
``` python
from sentimotion.emotion import OpenAI as OpenAIEmotion

emotion_model = OpenAIEmotion()
```

This classifier has one required parameter during instantiation:
- **openai_client:** (default: None) An instance of the ```OpenAI``` class.
- **model_name:** (default: "gpt-4o-mini") The OpenAI model to use for inference.

#### Deepseek R1 1.5B (Local)
``` python
from sentimotion.emotion import Deepseek as DeepseekEmotion

emotion_model = DeepseekEmotion()
```

This classifier has two required parameters during instantiation:
- **batch_size:** (default: 250) The number of input documents to include in each batch when running parallel or on GPU.
- **model_name:** (default: "deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B") The named huggingface transformer to use.

### Sentiment
This package supports the following Sentiment Classifier Models:

#### CardiffNLP
``` python
from sentimotion.sentiment import CardiffNLP as CardiffNLPSentiment

sentiment_model = CardiffNLPSentiment()
```

This classifier has two required parameters during instantiation:
- **batch_size:** (default: 250) The number of input documents to include in each batch when running parallel or on GPU.
- **model_name:** (default: "cardiffnlp/twitter-roberta-base-emotion-multilabel-latest") The named huggingface transformer to use.

#### SentiWordNet
``` python
from sentimotion.sentiment import SentiWordNet

sentiment_model = SentiWordNet()
```

This classifier has no required parameters.

#### VaderSentiment
``` python
from sentimotion.sentiment import VaderSentiment

sentiment_model = VaderSentiment()
```

This classifier has no required parameters.

#### OpenAI (API)
``` python
from sentimotion.sentiment import OpenAI as OpenAISentiment

sentiment_model = OpenAISentiment()
```
This classifier has one required parameter during instantiation:
- **openai_client:** (default: None) An instance of the ```OpenAI``` class.
- **model_name:** (default: "gpt-4o-mini") The OpenAI model to use for inference.

#### Deepseek R1 1.5B (Local)
``` python
from sentimotion.sentiment import Deepseek as DeepseekSentiment

sentiment_model = DeepseekSentiment()
```

This classifier has two required parameters during instantiation:
- **batch_size:** (default: 250) The number of input documents to include in each batch when running parallel or on GPU.
- **model_name:** (default: "deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B") The named huggingface transformer to use.

## Example Code
``` python
# Import Packages
from sentimotion import Sentimotion
from sentimotion.emotion import CardiffNLP as CardiffNLPEmotion
from sentimotion.sentiment import CardiffNLP as CardiffNLPSentiment

# Input Documents and Timestamps
documents_input = [
    "Lorem ipsum dolor sit amet",
    "Lorem ipsum dolor sit amet",
    "Lorem ipsum dolor sit amet",
    "Lorem ipsum dolor sit amet",
    "Lorem ipsum dolor sit amet"
]

timestamps_input = [
    "2024-01-01 00:00:00",
    "2024-01-02 00:00:00",
    "2024-01-03 00:00:00",
    "2024-01-04 00:00:00",
    "2024-01-05 00:00:00"
]

# Calculate Emotion/Sentiment
sentimotionmodel.calculate(documents=documents_input)

# Get Sentiment and Emotion for each document and output to csv
df = sentimotionmodel.get_document_info(documents=documents_input)
df.to_csv(f"./output/emotion-sentiment-output.csv")

# Undertake Dynamic Sentiment Analysis and output to svg
fig = sentimotionmodel.visualise_sentiment_over_time(nr_bins=20, timestamps=timestamps_input)
fig.write_image(f"./output/sentiment-over-time-svg.svg")
```
