File size: 4,787 Bytes
32adcec
 
 
 
 
e88d283
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32adcec
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e88d283
32adcec
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e88d283
32adcec
 
 
 
 
 
 
 
 
 
 
5fd634a
32adcec
 
 
4a3c57b
 
32adcec
 
 
 
b7b2238
32adcec
 
e88d283
32adcec
 
 
 
5fd634a
 
 
 
 
 
 
 
 
 
 
 
 
e88d283
5fd634a
 
 
 
 
 
 
32adcec
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
from pyabsa import available_checkpoints
from pyabsa import ATEPCCheckpointManager
import gradio as gr


def assign_sentiment_marker(sentiment_list, aspect_index):
    """
    This function returns a sentiment marker '+' for Positive, '-' for Negative, and '$' for any other sentiment.
    It maps the sentiment from the sentiment_list at the aspect_index to the respective marker.

    Parameters:
    sentiment_list (list): A list of sentiments.
    aspect_index (int): The index of the sentiment in sentiment_list to map to a marker.

    Returns:
    str: The sentiment marker.
    """

    # Define a dictionary to map sentiment labels to markers.
    sentiment_markers = {
        "Positive": "pos",
        "Negative": "neg"
    }

    # Fetch sentiment label from the sentiment_list using aspect_index.
    sentiment_label = sentiment_list[aspect_index]

    # Use get method on dictionary to fetch corresponding marker or default to '$' for unlisted sentiments.
    return sentiment_markers.get(sentiment_label, "neu")
    

def annotate_sentiment(tokens, aspect_positions, sentiment_list):
    """
    Function to post-process the output from the aspect extractor model.
    Annotates tokens based on sentiment, either positive (+) or negative (-).
    
    :param tokens: list of tokens to be processed
    :param aspect_positions: list of positions in tokens that refer to aspects
    :param sentiment_list: list of sentiments corresponding to each aspect
    :return: list of tuples where each tuple contains a token and its corresponding sentiment (if any)
    """
    annotated_tokens = []
    aspect_index = 0
    for i, token_group in enumerate(tokens):
        if aspect_index < len(aspect_positions) and i == aspect_positions[aspect_index]:
            for token in token_group:
                sentiment = assign_sentiment_marker(sentiment_list, aspect_index)
                annotated_tokens.append((token, sentiment))
            aspect_index += 1
        else:
            for token in token_group:
                annotated_tokens.append((token, None))

        # Add space between groups of tokens, if it's not the last group
        if i != len(tokens) - 1:
            annotated_tokens.append((' ', None))
    
    return annotated_tokens


def annotate_text_sentiment(text):
    """
    Interface function to extract aspects and their sentiments from the given text.
    Uses an aspect extractor model, then processes its output for sentiment annotation.
    
    :param text: string to be processed
    :return: list of tuples where each tuple contains a token from the text and its corresponding sentiment (if any)
    """
    aspect_extraction_result = aspect_extractor.extract_aspect(inference_source=[text], pred_sentiment=True)[0]
    tokens = aspect_extraction_result["tokens"]
    
    # If no aspects found, aspect_positions and sentiment_list are empty
    if len(aspect_extraction_result['position']) == 0:
        aspect_positions = []
        sentiment_list = []
    else:
        aspect_positions = [position[0]-1 for position in aspect_extraction_result['position']]
        sentiment_list = aspect_extraction_result["sentiment"]

    print(sentiment_list)
    annotated_tokens = annotate_sentiment(tokens, aspect_positions, sentiment_list)
    return annotated_tokens

# Initializing the aspect extractor model
checkpoint_map = available_checkpoints()
aspect_extractor = ATEPCCheckpointManager.get_aspect_extractor(checkpoint='english',
                                   auto_device=True  # False means load model on CPU
                                   )



demo1 = gr.Interface(
    annotate_text_sentiment,
    [
        gr.Textbox(
            label="Enter the text for aspect extraction and polarity detection",
            info="Example: The food was good, but the service was terrible.",
            lines=3,
        ),
    ],
    gr.HighlightedText(
        label="Aspect Detector based on DeBERTa",
        combine_adjacent=True,
        show_legend=True,
    ).style(color_map={"pos": "green", "neg": "red", "neu":"blue"}),
    theme=gr.themes.Base()
)


demo2 = gr.Interface(
    annotate_text_sentiment,
    [
        gr.Textbox(
            label="Enter the text for polarity detection",
            info="Example: The food was good, but the service was terrible.",
            lines=3,
        ),
    ],
    gr.HighlightedText(
        label="Aspect Detector based on Relational Graph Attention Networks, and BERT",
        combine_adjacent=True,
        show_legend=True,
    ).style(color_map={"pos": "green", "neg": "red", "neu":"blue"}),
    theme=gr.themes.Base()
)



demo = gr.TabbedInterface([demo1, demo2], ["Aspect Polarity Detection with Extraction", "Aspect Polarity Detection without Extraction"])

demo.launch()