eliseobao commited on
Commit
ddbfd90
1 Parent(s): b635266

Initial commit

Browse files
Dockerfile ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.9.18
2
+
3
+ RUN useradd -m -u 1000 user
4
+
5
+ USER user
6
+
7
+ ENV HOME=/home/user \
8
+ PATH=/home/user/.local/bin:$PATH
9
+
10
+ WORKDIR $HOME/app
11
+
12
+ COPY --chown=user . $HOME/app
13
+
14
+ COPY requirements.txt requirements.txt
15
+
16
+ RUN pip install -r requirements.txt
17
+ EXPOSE 7860
18
+
19
+ ENTRYPOINT ["python", "src/manage.py", "runserver","0.0.0.0:7860"]
requirements.txt ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ absl-py==2.0.0
2
+ asgiref==3.7.2
3
+ click==8.1.7
4
+ colorama==0.4.6
5
+ Django==4.2.7
6
+ joblib==1.3.2
7
+ lxml==4.9.3
8
+ nltk==3.8.1
9
+ numpy==1.26.2
10
+ portalocker==2.8.2
11
+ regex==2023.10.3
12
+ rouge-score==0.1.2
13
+ sacrebleu==2.3.2
14
+ six==1.16.0
15
+ sqlparse==0.4.4
16
+ tabulate==0.9.0
17
+ tqdm==4.66.1
18
+ typing_extensions==4.8.0
src/manage.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ """Django's command-line utility for administrative tasks."""
3
+ import os
4
+ import sys
5
+
6
+
7
+ def main():
8
+ """Run administrative tasks."""
9
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "web.settings")
10
+ try:
11
+ from django.core.management import execute_from_command_line
12
+ except ImportError as exc:
13
+ raise ImportError(
14
+ "Couldn't import Django. Are you sure it's installed and "
15
+ "available on your PYTHONPATH environment variable? Did you "
16
+ "forget to activate a virtual environment?"
17
+ ) from exc
18
+ execute_from_command_line(sys.argv)
19
+
20
+
21
+ if __name__ == "__main__":
22
+ main()
src/templates/index.html ADDED
@@ -0,0 +1,230 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
5
+
6
+ <script>
7
+ function computeFunction() {
8
+ var references = document.getElementById('references').value;
9
+ var predictions = document.getElementById('predictions').value;
10
+ var checkboxSentenceBleu = document.getElementById('checkbox-sentence-bleu').checked;
11
+ var checkboxCorpusBleu = document.getElementById('checkbox-corpus-bleu').checked;
12
+ var checkboxRouge1 = document.getElementById('checkbox-rouge1').checked;
13
+ var checkboxRouge2 = document.getElementById('checkbox-rouge2').checked;
14
+ var checkboxRougeL = document.getElementById('checkbox-rougeL').checked;
15
+ var checkboxTf1 = document.getElementById('checkbox-tf1').checked;
16
+
17
+ $.ajax({
18
+ type: 'POST',
19
+ url: '/compute/',
20
+ data: {
21
+ references: references,
22
+ predictions: predictions,
23
+ checkbox_sentence_bleu: checkboxSentenceBleu,
24
+ checkbox_corpus_bleu: checkboxCorpusBleu,
25
+ checkbox_rouge1: checkboxRouge1,
26
+ checkbox_rouge2: checkboxRouge2,
27
+ checkbox_rougeL: checkboxRougeL,
28
+ checkbox_tf1: checkboxTf1,
29
+ csrfmiddlewaretoken: '{{ csrf_token }}'
30
+ },
31
+ success: function (data) {
32
+ var resultsContainer = document.getElementById('results-container');
33
+ var resultHTML = '';
34
+
35
+ if (checkboxSentenceBleu && 'sentence_bleu' in data) {
36
+ resultHTML += '<p>Sentence BLEU: ' + data.sentence_bleu + '</p>';
37
+ }
38
+ if (checkboxCorpusBleu && 'corpus_bleu' in data) {
39
+ resultHTML += '<p>Corpus BLEU: ' + data.corpus_bleu + '</p>';
40
+ }
41
+ if (checkboxRouge1 && 'rouge1' in data) {
42
+ resultHTML += '<p>ROUGE-1: ' + data.rouge1 + '</p>';
43
+ }
44
+ if (checkboxRouge2 && 'rouge2' in data) {
45
+ resultHTML += '<p>ROUGE-2: ' + data.rouge2 + '</p>';
46
+ }
47
+ if (checkboxRougeL && 'rougeL' in data) {
48
+ resultHTML += '<p>ROUGE-L: ' + data.rougeL + '</p>';
49
+ }
50
+ if (checkboxTf1 && 'tf1' in data) {
51
+ resultHTML += '<p>TF1: ' + data.tf1 + '</p>';
52
+ }
53
+
54
+ resultsContainer.innerHTML = resultHTML || '<p>No results available</p>';
55
+ },
56
+ error: function () {
57
+ alert('Error computing results');
58
+ }
59
+ });
60
+ }
61
+
62
+ function handleFileDrop(event, textareaId) {
63
+ event.preventDefault();
64
+ var textarea = document.getElementById(textareaId);
65
+ var files = event.dataTransfer.files;
66
+
67
+ if (files.length > 0) {
68
+ var reader = new FileReader();
69
+ reader.onload = function (e) {
70
+ textarea.value = e.target.result;
71
+ };
72
+
73
+ reader.readAsText(files[0]);
74
+ }
75
+ }
76
+
77
+ function handleFileUpload(inputId, textareaId) {
78
+ var input = document.getElementById(inputId);
79
+ var textarea = document.getElementById(textareaId);
80
+
81
+ var files = input.files;
82
+
83
+ if (files.length > 0) {
84
+ var reader = new FileReader();
85
+ reader.onload = function (e) {
86
+ textarea.value = e.target.result;
87
+ };
88
+
89
+ reader.readAsText(files[0]);
90
+ }
91
+ }
92
+
93
+ function handleDragOver(event) {
94
+ event.preventDefault();
95
+ }
96
+ </script>
97
+
98
+ <head>
99
+ <meta charset="UTF-8">
100
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
101
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
102
+ <title>BLEU | ROUGE | TF1</title>
103
+ <style>
104
+ body {
105
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
106
+ background-color: #f5f5f5;
107
+ margin: 0;
108
+ display: flex;
109
+ align-items: center;
110
+ justify-content: center;
111
+ height: 100vh;
112
+ }
113
+
114
+ #container {
115
+ background-color: #fff;
116
+ box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
117
+ border-radius: 8px;
118
+ width: 80%;
119
+ max-width: 800px;
120
+ padding: 20px;
121
+ box-sizing: border-box;
122
+ }
123
+
124
+ header {
125
+ text-align: center;
126
+ margin-bottom: 20px;
127
+ }
128
+
129
+ .label-container {
130
+ width: 100%;
131
+ text-align: center;
132
+ margin-bottom: 20px;
133
+ }
134
+
135
+ textarea {
136
+ width: 100%;
137
+ padding: 10px;
138
+ box-sizing: border-box;
139
+ border: 1px solid #ccc;
140
+ border-radius: 4px;
141
+ resize: vertical;
142
+ }
143
+
144
+ .checkbox-container {
145
+ text-align: center;
146
+ margin-bottom: 20px;
147
+ }
148
+
149
+ label {
150
+ margin-right: 10px;
151
+ }
152
+
153
+ button {
154
+ background-color: #4caf50;
155
+ color: #fff;
156
+ border: none;
157
+ padding: 10px 20px;
158
+ text-align: center;
159
+ text-decoration: none;
160
+ display: inline-block;
161
+ font-size: 16px;
162
+ border-radius: 4px;
163
+ cursor: pointer;
164
+ transition: background-color 0.3s;
165
+ }
166
+
167
+ button:hover {
168
+ background-color: #45a049;
169
+ }
170
+ </style>
171
+ </head>
172
+
173
+ <body>
174
+ <div id="container">
175
+ <header>
176
+ <h1>How faithful are your predictions?</h1>
177
+ <p>You can write, drag-and-drop or upload your references and predictions. <br> End <span style="text-decoration:underline">all</span> of them with with a comma and a
178
+ newline.</p>
179
+ </header>
180
+
181
+ <div class="label-container" ondrop="handleFileDrop(event, 'references')" ondragover="handleDragOver(event)">
182
+ <label for="references">References</label>
183
+ <textarea id="references" rows="5" placeholder="a,&#10;b,&#10;c&#10;" draggable="true"
184
+ ondrop="handleFileDrop(event, 'references')" ondragover="handleDragOver(event)"></textarea>
185
+ <input type="file" id="file-references" accept=".txt"
186
+ onchange="handleFileUpload('file-references', 'references')">
187
+ </div>
188
+
189
+ <div class="label-container" ondrop="handleFileDrop(event, 'predictions')" ondragover="handleDragOver(event)">
190
+ <label for="predictions">Predictions</label>
191
+ <textarea id="predictions" rows="5" placeholder="a,&#10;d,&#10;c&#10;" draggable="true"
192
+ ondrop="handleFileDrop(event, 'predictions')" ondragover="handleDragOver(event)"></textarea>
193
+ <input type="file" id="file-predictions" accept=".txt"
194
+ onchange="handleFileUpload('file-predictions', 'predictions')">
195
+ </div>
196
+
197
+ <div class="checkbox-container">
198
+ <label for="checkbox-sentence-bleu">
199
+ <input type="checkbox" id="checkbox-sentence-bleu" name="checkbox-sentence-bleu"> <a href="https://aclanthology.org/P02-1040/">Sentence BLEU</a>
200
+ </label>
201
+
202
+ <label for="checkbox-corpus-bleu">
203
+ <input type="checkbox" id="checkbox-corpus-bleu" name="checkbox-corpus-bleu"> <a href="https://aclanthology.org/P02-1040/">Corpus BLEU</a>
204
+ </label>
205
+
206
+ <label for="checkbox-rouge1">
207
+ <input type="checkbox" id="checkbox-rouge1" name="checkbox-rouge1"> <a href="https://aclanthology.org/W04-1013/">ROUGE-1</a>
208
+ </label>
209
+
210
+ <label for="checkbox-rouge2">
211
+ <input type="checkbox" id="checkbox-rouge2" name="checkbox-rouge2"> <a href="https://aclanthology.org/W04-1013/">ROUGE-2</a>
212
+ </label>
213
+
214
+ <label for="checkbox-rougeL">
215
+ <input type="checkbox" id="checkbox-rougeL" name="checkbox-rougeL"> <a href="https://aclanthology.org/W04-1013/">ROUGE-L</a>
216
+ </label>
217
+
218
+ <label for="checkbox-tf1">
219
+ <input type="checkbox" id="checkbox-tf1" name="checkbox-tf1"> <a href="https://aclanthology.org/2020.acl-main.408/">TF1</a>
220
+ </label>
221
+ </div>
222
+
223
+ <div style="text-align: center;">
224
+ <button onclick="computeFunction()">Compute</button>
225
+ </div>
226
+ <div id="results-container" style="text-align: center; margin-top: 20px;"></div>
227
+ </div>
228
+ </body>
229
+
230
+ </html>
src/web/__init__.py ADDED
File without changes
src/web/settings.py ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Django settings for web project.
3
+
4
+ Generated by 'django-admin startproject' using Django 4.2.7.
5
+
6
+ For more information on this file, see
7
+ https://docs.djangoproject.com/en/4.2/topics/settings/
8
+
9
+ For the full list of settings and their values, see
10
+ https://docs.djangoproject.com/en/4.2/ref/settings/
11
+ """
12
+ import os
13
+ from pathlib import Path
14
+
15
+ # Build paths inside the project like this: BASE_DIR / 'subdir'.
16
+ BASE_DIR = Path(__file__).resolve().parent.parent
17
+
18
+
19
+ # Quick-start development settings - unsuitable for production
20
+ # See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
21
+
22
+ # SECURITY WARNING: keep the secret key used in production secret!
23
+ SECRET_KEY = "django-insecure-*r6s+e#n%b*26gf($$x9g35=^)a2=9g+0i*$uukx1_%x)p)h@="
24
+
25
+ # SECURITY WARNING: don't run with debug turned on in production!
26
+ DEBUG = True
27
+
28
+ ALLOWED_HOSTS = []
29
+
30
+
31
+ # Application definition
32
+
33
+ INSTALLED_APPS = [
34
+ "django.contrib.admin",
35
+ "django.contrib.auth",
36
+ "django.contrib.contenttypes",
37
+ "django.contrib.sessions",
38
+ "django.contrib.messages",
39
+ "django.contrib.staticfiles",
40
+ ]
41
+
42
+ MIDDLEWARE = [
43
+ "django.middleware.security.SecurityMiddleware",
44
+ "django.contrib.sessions.middleware.SessionMiddleware",
45
+ "django.middleware.common.CommonMiddleware",
46
+ "django.middleware.csrf.CsrfViewMiddleware",
47
+ "django.contrib.auth.middleware.AuthenticationMiddleware",
48
+ "django.contrib.messages.middleware.MessageMiddleware",
49
+ "django.middleware.clickjacking.XFrameOptionsMiddleware",
50
+ ]
51
+
52
+ ROOT_URLCONF = "web.urls"
53
+
54
+ TEMPLATES = [
55
+ {
56
+ "BACKEND": "django.template.backends.django.DjangoTemplates",
57
+ "DIRS": [os.path.join(BASE_DIR, "templates")],
58
+ "APP_DIRS": True,
59
+ "OPTIONS": {
60
+ "context_processors": [
61
+ "django.template.context_processors.debug",
62
+ "django.template.context_processors.request",
63
+ "django.contrib.auth.context_processors.auth",
64
+ "django.contrib.messages.context_processors.messages",
65
+ ],
66
+ },
67
+ },
68
+ ]
69
+
70
+ WSGI_APPLICATION = "web.wsgi.application"
71
+
72
+
73
+ # Database
74
+ # https://docs.djangoproject.com/en/4.2/ref/settings/#databases
75
+
76
+ DATABASES = {
77
+ # 'default': {
78
+ # 'ENGINE': 'django.db.backends.sqlite3',
79
+ # 'NAME': BASE_DIR / 'db.sqlite3',
80
+ # }
81
+ }
82
+
83
+
84
+ # Password validation
85
+ # https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
86
+
87
+ AUTH_PASSWORD_VALIDATORS = [
88
+ {
89
+ "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
90
+ },
91
+ {
92
+ "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
93
+ },
94
+ {
95
+ "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
96
+ },
97
+ {
98
+ "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
99
+ },
100
+ ]
101
+
102
+
103
+ # Internationalization
104
+ # https://docs.djangoproject.com/en/4.2/topics/i18n/
105
+
106
+ LANGUAGE_CODE = "en-us"
107
+
108
+ TIME_ZONE = "UTC"
109
+
110
+ USE_I18N = True
111
+
112
+ USE_TZ = True
113
+
114
+
115
+ # Static files (CSS, JavaScript, Images)
116
+ # https://docs.djangoproject.com/en/4.2/howto/static-files/
117
+
118
+ STATIC_URL = "static/"
119
+
120
+ # Default primary key field type
121
+ # https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
122
+
123
+ DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
src/web/tasks.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sacrebleu
2
+ import statistics
3
+
4
+ from rouge_score import rouge_scorer
5
+
6
+
7
+ def sentence_bleu(references, predictions):
8
+ scores = []
9
+ for ref, pred in zip(references, predictions):
10
+ scores.append(
11
+ sacrebleu.sentence_bleu(
12
+ pred,
13
+ [ref],
14
+ smooth_method="exp",
15
+ smooth_value=0.0,
16
+ lowercase=True,
17
+ tokenize="intl",
18
+ ).score
19
+ )
20
+
21
+ return statistics.mean(scores)
22
+
23
+
24
+ def corpus_bleu(references, predictions):
25
+ return sacrebleu.corpus_bleu(
26
+ predictions,
27
+ [references],
28
+ smooth_method="exp",
29
+ smooth_value=0.0,
30
+ lowercase=True,
31
+ tokenize="intl",
32
+ ).score
33
+
34
+
35
+ def rouge(scope, references, predictions):
36
+ rouge = f"rouge{scope}"
37
+ scorer = rouge_scorer.RougeScorer([rouge], use_stemmer=True)
38
+
39
+ scores_dict = {"precision": 0, "recall": 0, "f1": 0}
40
+
41
+ for reference, prediction in zip(references, predictions):
42
+ scores = scorer.score(reference, prediction)
43
+
44
+ scores_dict["precision"] += scores[rouge].precision
45
+ scores_dict["recall"] += scores[rouge].recall
46
+ scores_dict["f1"] += scores[rouge].fmeasure
47
+
48
+ return {k: v / len(references) for k, v in scores_dict.items()}
src/web/urls.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ URL configuration for web project.
3
+
4
+ The `urlpatterns` list routes URLs to views. For more information please see:
5
+ https://docs.djangoproject.com/en/4.2/topics/http/urls/
6
+ Examples:
7
+ Function views
8
+ 1. Add an import: from my_app import views
9
+ 2. Add a URL to urlpatterns: path('', views.home, name='home')
10
+ Class-based views
11
+ 1. Add an import: from other_app.views import Home
12
+ 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
13
+ Including another URLconf
14
+ 1. Import the include() function: from django.urls import include, path
15
+ 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
16
+ """
17
+ from django.urls import path
18
+
19
+ from . import views
20
+
21
+ urlpatterns = [
22
+ path("", views.index, name="index"),
23
+ path("compute/", views.compute, name="compute"),
24
+ ]
src/web/views.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from . import tasks
2
+
3
+ from django.http import JsonResponse
4
+ from django.shortcuts import render
5
+ from django.views.decorators.cache import cache_control
6
+ from django.views.decorators.csrf import csrf_exempt
7
+
8
+
9
+ @cache_control(no_cache=True, must_revalidate=True, no_store=True, max_age=0)
10
+ def index(request):
11
+ return render(request, "index.html", {})
12
+
13
+
14
+ @csrf_exempt
15
+ def compute(request):
16
+
17
+ def _format_rouge_result(rouge):
18
+ return "P: {:.1f} | R: {:.1f} | F1: {:.1f}".format(rouge['precision'], rouge['recall'], rouge['f1'])
19
+
20
+ if request.method == "POST":
21
+ references = list(filter(None, request.POST.get("references", "").split(",\n")))
22
+ predictions = list(filter(None, request.POST.get("predictions", "").split(",\n")))
23
+
24
+ print(references)
25
+ print(predictions)
26
+
27
+ result = {}
28
+ if request.POST.get("checkbox_sentence_bleu", False) == "true":
29
+ result["sentence_bleu"] = "{:.1f}".format(tasks.sentence_bleu(references, predictions))
30
+ if request.POST.get("checkbox_corpus_bleu", False) == "true":
31
+ result["corpus_bleu"] = "{:.1f}".format(tasks.corpus_bleu(references, predictions))
32
+ if request.POST.get("checkbox_rouge1", False) == "true":
33
+ result["rouge1"] = _format_rouge_result(tasks.rouge('1', references, predictions))
34
+ if request.POST.get("checkbox_rouge2", False) == "true":
35
+ result["rouge2"] = _format_rouge_result(tasks.rouge('2', references, predictions))
36
+ if request.POST.get("checkbox_rougeL", False) == "true":
37
+ result["rougeL"] = _format_rouge_result(tasks.rouge('L', references, predictions))
38
+ if request.POST.get("checkbox_tf1", False) == "true":
39
+ result["tf1"] = 0.90
40
+
41
+ print(result)
42
+ return JsonResponse(result)
43
+
44
+ return JsonResponse({"error": "Invalid request method"})
src/web/wsgi.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ WSGI config for web project.
3
+
4
+ It exposes the WSGI callable as a module-level variable named ``application``.
5
+
6
+ For more information on this file, see
7
+ https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/
8
+ """
9
+
10
+ import os
11
+
12
+ from django.core.wsgi import get_wsgi_application
13
+
14
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "web.settings")
15
+
16
+ application = get_wsgi_application()