yangxinsci1993 commited on
Commit
6e4fc64
1 Parent(s): c160098

edit interface

Browse files
Files changed (27) hide show
  1. .DS_Store +0 -0
  2. app.py +147 -21
  3. bin/reframe +32 -0
  4. pred.txt +1 -0
  5. test.py +34 -0
  6. test.sh +9 -0
  7. test/1.gold.txt +1 -0
  8. test/1.txt +1 -0
  9. test/10.gold.txt +1 -0
  10. test/10.txt +1 -0
  11. test/2.gold.txt +1 -0
  12. test/2.txt +1 -0
  13. test/3.gold.txt +1 -0
  14. test/3.txt +1 -0
  15. test/4.gold.txt +1 -0
  16. test/4.txt +1 -0
  17. test/5.gold.txt +1 -0
  18. test/5.txt +1 -0
  19. test/6.gold.txt +1 -0
  20. test/6.txt +1 -0
  21. test/7.gold.txt +1 -0
  22. test/7.txt +1 -0
  23. test/8.gold.txt +1 -0
  24. test/8.txt +1 -0
  25. test/9.gold.txt +1 -0
  26. test/9.txt +1 -0
  27. test/test.sh +0 -0
.DS_Store CHANGED
Binary files a/.DS_Store and b/.DS_Store differ
 
app.py CHANGED
@@ -1,8 +1,10 @@
1
- import torch
2
  from transformers import pipeline
3
  from transformers import AutoModelForSeq2SeqLM
4
  from transformers import AutoTokenizer
5
  from textblob import TextBlob
 
 
 
6
 
7
  # Load trained model
8
  model = AutoModelForSeq2SeqLM.from_pretrained("output/reframer")
@@ -10,32 +12,156 @@ tokenizer = AutoTokenizer.from_pretrained("output/reframer")
10
  reframer = pipeline('summarization', model=model, tokenizer=tokenizer)
11
 
12
 
13
- def reframe(text, strategy):
14
- text_with_strategy = text + "Strategy: ['" + strategy + "']"
15
- #Input Control
16
- #The input text cannot be too short to ensure it has substantial content to be reframed. It also cannot be too long to ensure the text has a focused idea.
17
- if len(text) < 15:
18
- return "[Error]: Input is too short. Please try again by inputing text with moderate length."
19
- if len(text) > 150:
20
- return "[Error]: Input is too long. Please try again by inputing text with moderate length."
21
- if TextBlob(text).sentiment.polarity > 0.2:
22
- return "[Error]: Input is too positive. Please try again by inputing text that is negative."
23
- from hatesonar import Sonar
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  sonar = Sonar()
25
- if sonar.ping(text)['classes'][1]['confidence'] > 0.8:
26
- return "[Error]: Input is offensive. Please try again by not inputing offensive language."
27
- #if TextBlob(text).sentiment.polarity > 0:
28
- # return "Please try again by inputing text that is negative."
29
- return reframer(text_with_strategy)[0]['summary_text']
 
 
30
 
 
 
 
31
 
32
- import gradio as gr
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  with gr.Blocks() as demo:
 
 
 
 
 
 
 
 
34
  text = gr.Textbox(label="Original Text")
35
- radio = gr.Radio(
 
 
 
 
 
 
 
 
 
 
 
 
36
  ["thankfulness", "neutralizing", "optimism", "growth", "impermanence", "self_affirmation"], label="Strategy to use?"
37
  )
38
- output = gr.Textbox(label="Reframed Output")
 
39
  greet_btn = gr.Button("Reframe")
40
- greet_btn.click(fn=reframe, inputs=[text, radio], outputs=output)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  demo.launch()
 
 
1
  from transformers import pipeline
2
  from transformers import AutoModelForSeq2SeqLM
3
  from transformers import AutoTokenizer
4
  from textblob import TextBlob
5
+ from hatesonar import Sonar
6
+ import gradio as gr
7
+ import torch
8
 
9
  # Load trained model
10
  model = AutoModelForSeq2SeqLM.from_pretrained("output/reframer")
 
12
  reframer = pipeline('summarization', model=model, tokenizer=tokenizer)
13
 
14
 
15
+ CHAR_LENGTH_LOWER_BOUND = 15 # The minimum character length threshold for the input text
16
+ CHAR_LENGTH_HIGHER_BOUND = 150 # The maximum character length threshold for the input text
17
+ SENTIMENT_THRESHOLD = 0.2 # The maximum Textblob sentiment score for the input text
18
+ OFFENSIVENESS_CONFIDENCE_THRESHOLD = 0.8 # The threshold for the confidence score of a text being offensive
19
+
20
+ LENGTH_ERROR = "The input text is too long or too short. Please try again by inputing text with moderate length."
21
+ SENTIMENT_ERROR = "The input text is too positive. Please try again by inputing text with negative sentiment."
22
+ OFFENSIVE_ERROR = "The input text is offensive. Please try again by inputing non-offensive text."
23
+
24
+ CACHE = [] # A list storing the most recent 5 reframing history
25
+ MAX_STORE = 5 # The maximum number of history user would like to store
26
+
27
+ BEST_N = 3 # The number of best decodes user would like to seee
28
+
29
+
30
+ def input_error_message(error_type):
31
+ # type: (str) -> str
32
+ """Generate an input error message from error type."""
33
+ return "[Error]: Invalid Input. " + error_type
34
+
35
+ def update_cache(cache, new_record):
36
+ # type: List[List[str, str, str]] -> List[List[str, str, str]]
37
+ """Update the cache to store the most recent five reframing histories."""
38
+ cache.append(new_record)
39
+ if len(cache) > MAX_STORE:
40
+ cache = cache[1:]
41
+ return cache
42
+
43
+ def reframe(input_text, strategy):
44
+ # type: (str, str) -> str
45
+ """Reframe the input text with a specified strategy.
46
+
47
+ The strategy will be concetenated to the input text and passed to a finetuned BART model.
48
+
49
+ The reframed positive text will be returned.
50
+ """
51
+ text_with_strategy = input_text + "Strategy: ['" + strategy + "']"
52
+
53
+ # Input Control
54
+ # The input text cannot be too short to ensure it has substantial content to be reframed. It also cannot be too long to ensure the text has a focused idea.
55
+ if len(input_text) < CHAR_LENGTH_LOWER_BOUND or len(input_text) > CHAR_LENGTH_HIGHER_BOUND:
56
+ return input_error_message(LENGTH_ERROR)
57
+ # The input text cannot be too positive to ensure the text can be positively reframed.
58
+ if TextBlob(input_text).sentiment.polarity > 0.2:
59
+ return input_error_message(SENTIMENT_ERROR)
60
+ # The input text cannot be offensive.
61
  sonar = Sonar()
62
+ # sonar.ping(input_text) outputs a dictionary and the second score under the key classes is the confidence for the input text being offensive language
63
+ if sonar.ping(input_text)['classes'][1]['confidence'] > OFFENSIVENESS_CONFIDENCE_THRESHOLD:
64
+ return input_error_message(OFFENSIVE_ERROR)
65
+
66
+ # Reframing
67
+ # reframer pipeline outputs a list containing one dictionary where the value for 'summary_text' is the reframed text output
68
+ reframed_text = reframer(text_with_strategy)[0]['summary_text']
69
 
70
+ # Update cache
71
+ global CACHE
72
+ CACHE = update_cache(CACHE, [input_text, strategy, reframed_text])
73
 
74
+ return reframed_text
75
+
76
+
77
+ def show_reframe_change(input_text, strategy):
78
+ # type: (str, str) -> List[Tuple[str, str]]
79
+ """Compare the addition and deletion of characters in input_text to form reframed_text.
80
+
81
+ The returned output is a list of tuples with two elements, the first element being the character in reframed text and the second element being the action performed with respect to the input text.
82
+ """
83
+ reframed_text = reframe(input_text, strategy)
84
+ from difflib import Differ
85
+ d = Differ()
86
+ return [
87
+ (token[2:], token[0] if token[0] != " " else None)
88
+ for token in d.compare(input_text, reframed_text)
89
+ ]
90
+
91
+ def show_n_best_decodes(input_text, strategy):
92
+ # type: (str, str) -> str
93
+ prompt = [input_text + "Strategy: ['" + strategy + "']"]
94
+ n_best_decodes = model.generate(torch.tensor(tokenizer(prompt, padding=True)['input_ids']),
95
+ do_sample=True,
96
+ num_return_sequences=BEST_N
97
+ )
98
+ best_n_result = ""
99
+ for i in range(len(n_best_decodes)):
100
+ best_n_result += str(i+1) + " " + tokenizer.decode(n_best_decodes[i], skip_special_tokens=True)
101
+ if i < BEST_N - 1:
102
+ best_n_result += "\n"
103
+ return best_n_result
104
+
105
+ def show_history(cache):
106
+ # type: List[List[str, str, str]] -> str
107
+ history = ""
108
+ for i in cache:
109
+ input_text, strategy, reframed_text = i
110
+ history += "Input text: " + input_text + " Strategy: " + strategy + " -> Reframed text: " + reframed_text + "\n"
111
+ return gr.Textbox.update(value=history, visible=True)
112
+
113
+
114
+ # Build Gradio interface
115
  with gr.Blocks() as demo:
116
+ # Instruction
117
+ gr.Markdown(
118
+ '''
119
+ # Positive Reframing
120
+ Start inputing negative texts to see how you can see the same event from a positive angle.
121
+ ''')
122
+
123
+ # Input text to be reframed
124
  text = gr.Textbox(label="Original Text")
125
+
126
+ # Input strategy for the reframing
127
+ gr.Markdown(
128
+ '''
129
+ Choose one of the six strategies to carry out reframing: \n
130
+ **Growth Mindset:** Viewing a challenging event as an opportunity for the author specifically to grow or improve themselves. \n
131
+ **Impermanence:** Saying bad things don’t last forever, will get better soon, and/or that others have experienced similar struggles. \n
132
+ **Neutralizing:** Replacing a negative word with a neutral word. For example, “This was a terrible day” becomes “This was a long day.” \n
133
+ **Optimism:** Focusing on things about the situation itself, in that moment, that are good (not just forecasting a better future). \n
134
+ **Self-affirmation:** Talking about what strengths the author already has, or the values they admire, like love, courage, perseverance, etc. \n
135
+ **Thankfulness:** Expressing thankfulness or gratitude with key words like appreciate, glad that, thankful for, good thing, etc.
136
+ ''')
137
+ strategy = gr.Radio(
138
  ["thankfulness", "neutralizing", "optimism", "growth", "impermanence", "self_affirmation"], label="Strategy to use?"
139
  )
140
+
141
+ # Trigger button for reframing
142
  greet_btn = gr.Button("Reframe")
143
+ best_output = gr.HighlightedText(
144
+ label="Diff",
145
+ combine_adjacent=True,
146
+ ).style(color_map={"+": "green", "-": "red"})
147
+ greet_btn.click(fn=show_reframe_change, inputs=[text, strategy], outputs=best_output)
148
+
149
+ # Trigger button for showing n best reframings
150
+ greet_btn = gr.Button("Show Best {n} Results".format(n=BEST_N))
151
+ n_best_output = gr.Textbox(interactive=False)
152
+ greet_btn.click(fn=show_n_best_decodes, inputs=[text, strategy], outputs=n_best_output)
153
+
154
+ # Default examples of text and strategy pairs for user to have a quick start
155
+ gr.Markdown("## Examples")
156
+ gr.Examples(
157
+ [["I have a lot of homework to do today.", "self_affirmation"], ["This has been the longest and most stressful week of my life!", "optimism"], ["So stressed about the midterms next week.", "thankfulness"]],
158
+ [text, strategy], output, show_reframe_change, cache_examples=False, run_on_click=False
159
+ )
160
+
161
+ # Link to paper and Github repo
162
+ gr.Markdown(
163
+ '''
164
+ For more details: You can read our [paper](https://arxiv.org/abs/2204.02952) or access our [code](https://github.com/SALT-NLP/positive-frames).
165
+ ''')
166
+
167
  demo.launch()
bin/reframe ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+
3
+ import argparse
4
+ from transformers import pipeline
5
+ from transformers import AutoModelForSeq2SeqLM
6
+ from transformers import AutoTokenizer
7
+
8
+ def get_args():
9
+ """ args from input
10
+ """
11
+ parser = argparse.ArgumentParser(description='HSIC-Bottleneck research')
12
+
13
+ parser.add_argument('-ipt', '--input', required=True,
14
+ type=str, help='input path')
15
+
16
+ args = parser.parse_args()
17
+
18
+ return args
19
+
20
+ def main():
21
+
22
+ args = get_args()
23
+
24
+ input_file = args.input
25
+
26
+ with open(input_file, 'r') as file:
27
+ data = file.read().rstrip()
28
+ print(data)
29
+
30
+
31
+ if __name__ == '__main__':
32
+ main()
pred.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ I have a lot of homework to do today, but I know I can finish it.
test.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import pipeline
2
+ from transformers import AutoModelForSeq2SeqLM
3
+ from transformers import AutoTokenizer
4
+ import argparse
5
+
6
+ # Load trained model
7
+ model = AutoModelForSeq2SeqLM.from_pretrained("output/reframer")
8
+ tokenizer = AutoTokenizer.from_pretrained("output/reframer")
9
+ reframer = pipeline('summarization', model=model, tokenizer=tokenizer)
10
+
11
+ def get_args():
12
+ """ args from input
13
+ """
14
+ parser = argparse.ArgumentParser(description='HSIC-Bottleneck research')
15
+
16
+ parser.add_argument('-ipt', '--input', required=True,
17
+ type=str, help='input path')
18
+
19
+ args = parser.parse_args()
20
+
21
+ return args
22
+
23
+ def main():
24
+
25
+ args = get_args()
26
+
27
+ input_file = args.input
28
+
29
+ with open(input_file, 'r') as file:
30
+ data = file.read().rstrip()
31
+ print(reframer(data)[0]['summary_text'])
32
+
33
+ if __name__ == '__main__':
34
+ main()
test.sh ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ for n in 1 2 3 4 5 6 7 8 9 10
4
+ do
5
+ echo '------------------------------------------------------------'
6
+ echo $n
7
+ echo "test/$n.txt"
8
+ python test.py --input="test/$n.txt" | diff - test/$n.gold.txt
9
+ done
test/1.gold.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ I have a lot of homework to do today, but I know I can finish .
test/1.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ I have a lot of homework to do today. Strategy: ['self_affirmation']
test/10.gold.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ The restaurant is not a good one.
test/10.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ The restaurant is horrible. Strategy: ['neutralizing']
test/2.gold.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ I have a lot of homework to do today, but I'm thankful that I have the time to do it.
test/2.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ I have a lot of homework to do today. Strategy: ['thankfulness']
test/3.gold.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ I have a lot of homework to do today, but it will be over soon.
test/3.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ I have a lot of homework to do today. Strategy: ['impermanence']
test/4.gold.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ So stressed about the midterm next week. But I know I can do it.
test/4.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ So stressed about the midterm next week. Strategy: ['self_affirmation']
test/5.gold.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ So stressed about the midterm next week. Hope I do well.
test/5.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ So stressed about the midterm next week. Strategy: ['optimism']
test/6.gold.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ I'm stressed about the midterm next week, but I know it will be over soon.
test/6.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ So stressed about the midterm next week. Strategy: ['impermanence']
test/7.gold.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ I failed my math quiz, but I know I can do better next time.
test/7.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ I failed my math quiz I am such a loser. Strategy: ['self_affirmation']
test/8.gold.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ I failed my math quiz I am such a loser. I need to study harder next time.
test/8.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ I failed my math quiz I am such a loser. Strategy: ['growth']
test/9.gold.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ I failed my math quiz, but I'm sure I'll pass next time.
test/9.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ I failed my math quiz I am such a loser. Strategy: ['optimism']
test/test.sh ADDED
File without changes