qyle commited on
Commit
2d42370
·
verified ·
1 Parent(s): fe0be60

deployment

Browse files
constants.py CHANGED
@@ -20,8 +20,8 @@ MAX_RAM_USAGE_PERCENT = 90
20
  # Max history messages to keep for context
21
  MAX_HISTORY = 20
22
 
23
- MAX_MESSAGE_LENGTH = 1000
24
- MAX_COMMENT_LENGTH = 500
25
  MAX_RESPONSE_LENGTH = 5000
26
  MAX_ID_LENGTH = 50
27
  MAX_FILE_NAME_LENGTH = 50
 
20
  # Max history messages to keep for context
21
  MAX_HISTORY = 20
22
 
23
+ MAX_MESSAGE_LENGTH = 2500
24
+ MAX_COMMENT_LENGTH = 2500
25
  MAX_RESPONSE_LENGTH = 5000
26
  MAX_ID_LENGTH = 50
27
  MAX_FILE_NAME_LENGTH = 50
llama_guard_test.ipynb ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "id": "7ddc61c7",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "from detoxify import Detoxify\n",
11
+ "\n",
12
+ "multilingual_detoxify_model = Detoxify(\"multilingual\", device=\"cuda\")\n",
13
+ "multilingual_detoxify_model.predict(\"Hello\")"
14
+ ]
15
+ }
16
+ ],
17
+ "metadata": {
18
+ "kernelspec": {
19
+ "display_name": ".venv_win (3.11.9)",
20
+ "language": "python",
21
+ "name": "python3"
22
+ },
23
+ "language_info": {
24
+ "codemirror_mode": {
25
+ "name": "ipython",
26
+ "version": 3
27
+ },
28
+ "file_extension": ".py",
29
+ "mimetype": "text/x-python",
30
+ "name": "python",
31
+ "nbconvert_exporter": "python",
32
+ "pygments_lexer": "ipython3",
33
+ "version": "3.11.9"
34
+ }
35
+ },
36
+ "nbformat": 4,
37
+ "nbformat_minor": 5
38
+ }
load_conversations.ipynb ADDED
@@ -0,0 +1,288 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "id": "fc07d69e",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "import boto3\n",
11
+ "import json\n",
12
+ "import os\n",
13
+ "import pytz\n",
14
+ "\n",
15
+ "from boto3.dynamodb.conditions import Attr\n",
16
+ "from collections import defaultdict\n",
17
+ "from datetime import datetime\n",
18
+ "from decimal import Decimal\n",
19
+ "from dotenv import load_dotenv"
20
+ ]
21
+ },
22
+ {
23
+ "cell_type": "code",
24
+ "execution_count": null,
25
+ "id": "aa2cda42",
26
+ "metadata": {},
27
+ "outputs": [],
28
+ "source": [
29
+ "load_dotenv()"
30
+ ]
31
+ },
32
+ {
33
+ "cell_type": "code",
34
+ "execution_count": null,
35
+ "id": "2a2214ff",
36
+ "metadata": {},
37
+ "outputs": [],
38
+ "source": [
39
+ "AWS_REGION = os.getenv(\"AWS_REGION\", \"us-east-1\")\n",
40
+ "AWS_ACCESS_KEY = os.getenv(\"AWS_ACCESS_KEY\", None)\n",
41
+ "AWS_SECRET_ACCESS_KEY = os.getenv(\"AWS_SECRET_ACCESS_KEY\", None)"
42
+ ]
43
+ },
44
+ {
45
+ "cell_type": "code",
46
+ "execution_count": null,
47
+ "id": "290b04ff",
48
+ "metadata": {},
49
+ "outputs": [],
50
+ "source": [
51
+ "# 1. Initialize the DynamoDB resource\n",
52
+ "dynamodb = boto3.resource(\n",
53
+ " \"dynamodb\",\n",
54
+ " region_name=AWS_REGION,\n",
55
+ " aws_access_key_id=AWS_ACCESS_KEY,\n",
56
+ " aws_secret_access_key=AWS_SECRET_ACCESS_KEY,\n",
57
+ ")\n",
58
+ "client = dynamodb.meta.client"
59
+ ]
60
+ },
61
+ {
62
+ "cell_type": "code",
63
+ "execution_count": null,
64
+ "id": "81477e4d",
65
+ "metadata": {},
66
+ "outputs": [],
67
+ "source": [
68
+ "existing_tables = client.list_tables()[\"TableNames\"]\n",
69
+ "existing_tables"
70
+ ]
71
+ },
72
+ {
73
+ "cell_type": "code",
74
+ "execution_count": null,
75
+ "id": "a3426a87",
76
+ "metadata": {},
77
+ "outputs": [],
78
+ "source": [
79
+ "table = dynamodb.Table(\"chatbot-conversations\")\n",
80
+ "table"
81
+ ]
82
+ },
83
+ {
84
+ "cell_type": "code",
85
+ "execution_count": null,
86
+ "id": "3111db17",
87
+ "metadata": {},
88
+ "outputs": [],
89
+ "source": [
90
+ "def get_all_grouped_sessions(date_string):\n",
91
+ " grouped_data = defaultdict(list)\n",
92
+ "\n",
93
+ " # Scan the entire table\n",
94
+ " response = table.scan(FilterExpression=Attr(\"timestamp\").gte(date_string))\n",
95
+ " items = response.get(\"Items\", [])\n",
96
+ "\n",
97
+ " # Handle pagination if the table is large\n",
98
+ " while \"LastEvaluatedKey\" in response:\n",
99
+ " response = table.scan(\n",
100
+ " ExclusiveStartKey=response[\"LastEvaluatedKey\"],\n",
101
+ " FilterExpression=Attr(\"timestamp\").gte(date_string),\n",
102
+ " )\n",
103
+ " items.extend(response.get(\"Items\", []))\n",
104
+ "\n",
105
+ " # Grouping logic\n",
106
+ " for item in items:\n",
107
+ " sid = item[\"session_id\"]\n",
108
+ " grouped_data[sid].append(item)\n",
109
+ "\n",
110
+ " return dict(grouped_data)"
111
+ ]
112
+ },
113
+ {
114
+ "cell_type": "code",
115
+ "execution_count": null,
116
+ "id": "8b72d9ae",
117
+ "metadata": {},
118
+ "outputs": [],
119
+ "source": [
120
+ "local_timezone = pytz.timezone(\"America/Montreal\")\n",
121
+ "\n",
122
+ "# Date of the demo\n",
123
+ "# We want to extract every conversation since that date\n",
124
+ "local_date = datetime(2026, 2, 10, 0, 0, 0)\n",
125
+ "\n",
126
+ "localized_date = local_timezone.localize(local_date)\n",
127
+ "\n",
128
+ "utc_date = localized_date.astimezone(pytz.utc)\n",
129
+ "\n",
130
+ "# We format the date for dynamodb\n",
131
+ "utc_date_dynamodb = utc_date.strftime(\"%Y-%m-%dT%H:%M:%SZ\")"
132
+ ]
133
+ },
134
+ {
135
+ "cell_type": "code",
136
+ "execution_count": null,
137
+ "id": "a5444c0f",
138
+ "metadata": {},
139
+ "outputs": [],
140
+ "source": [
141
+ "sessions = get_all_grouped_sessions(utc_date_dynamodb)\n",
142
+ "sessions"
143
+ ]
144
+ },
145
+ {
146
+ "cell_type": "code",
147
+ "execution_count": null,
148
+ "id": "eb4bfda0",
149
+ "metadata": {},
150
+ "outputs": [],
151
+ "source": [
152
+ "# Helper to handle DynamoDB Decimal and Set types when saving the conversations\n",
153
+ "def decimal_set_default(obj):\n",
154
+ " if isinstance(obj, Decimal):\n",
155
+ " return float(obj) if obj % 1 > 0 else int(obj)\n",
156
+ " if isinstance(obj, set):\n",
157
+ " return list(obj)\n",
158
+ " raise TypeError\n",
159
+ "\n",
160
+ "\n",
161
+ "with open(\"conversations.json\", \"w\", encoding=\"utf-8\") as f:\n",
162
+ " json.dump(\n",
163
+ " sessions,\n",
164
+ " f,\n",
165
+ " indent=4, # Makes the file human-readable (pretty-print)\n",
166
+ " ensure_ascii=True, # Allows special characters (like emojis or accents)\n",
167
+ " default=decimal_set_default, # Uses our helper for Decimals and Sets\n",
168
+ " )"
169
+ ]
170
+ },
171
+ {
172
+ "cell_type": "code",
173
+ "execution_count": null,
174
+ "id": "a53d80a5",
175
+ "metadata": {},
176
+ "outputs": [],
177
+ "source": [
178
+ "with open(\"conversations.json\", \"r\", encoding=\"utf-8\") as f:\n",
179
+ " conversations = json.load(f)"
180
+ ]
181
+ },
182
+ {
183
+ "cell_type": "code",
184
+ "execution_count": null,
185
+ "id": "55cf17e5",
186
+ "metadata": {},
187
+ "outputs": [],
188
+ "source": [
189
+ "conversations"
190
+ ]
191
+ },
192
+ {
193
+ "cell_type": "code",
194
+ "execution_count": null,
195
+ "id": "b03b5f25",
196
+ "metadata": {},
197
+ "outputs": [],
198
+ "source": [
199
+ "def filter_grouped_sessions(grouped_data, target_timestamp):\n",
200
+ " return {\n",
201
+ " sid: [item for item in items if item[\"timestamp\"] >= target_timestamp]\n",
202
+ " for sid, items in grouped_data.items()\n",
203
+ " # Optional: remove the session_id if the resulting list is empty\n",
204
+ " if any(item[\"timestamp\"] >= target_timestamp for item in items)\n",
205
+ " }"
206
+ ]
207
+ },
208
+ {
209
+ "cell_type": "code",
210
+ "execution_count": null,
211
+ "id": "42f7cc13",
212
+ "metadata": {},
213
+ "outputs": [],
214
+ "source": [
215
+ "local_date = datetime(2026, 2, 6, 14, 41, 0)\n",
216
+ "\n",
217
+ "localized_date = local_timezone.localize(local_date)\n",
218
+ "\n",
219
+ "utc_date = localized_date.astimezone(pytz.utc)\n",
220
+ "\n",
221
+ "# We format the date for dynamodb\n",
222
+ "utc_date_dynamodb = utc_date.strftime(\"%Y-%m-%dT%H:%M:%SZ\")\n",
223
+ "\n",
224
+ "filtered_conversations = filter_grouped_sessions(conversations, utc_date_dynamodb)\n",
225
+ "filtered_conversations"
226
+ ]
227
+ },
228
+ {
229
+ "cell_type": "code",
230
+ "execution_count": null,
231
+ "id": "5ec5002b",
232
+ "metadata": {},
233
+ "outputs": [],
234
+ "source": [
235
+ "for conv in filtered_conversations.values():\n",
236
+ " if any(\"error\" in message for message in conv):\n",
237
+ " print(conv)"
238
+ ]
239
+ },
240
+ {
241
+ "cell_type": "code",
242
+ "execution_count": null,
243
+ "id": "67fad2b2",
244
+ "metadata": {},
245
+ "outputs": [],
246
+ "source": [
247
+ "def filter_comments(grouped_data):\n",
248
+ " return {\n",
249
+ " sid: filtered_items\n",
250
+ " for sid, items in grouped_data.items()\n",
251
+ " if (filtered_items := [item for item in items if \"comment\" in item[\"data\"]])\n",
252
+ " }"
253
+ ]
254
+ },
255
+ {
256
+ "cell_type": "code",
257
+ "execution_count": null,
258
+ "id": "4fae7474",
259
+ "metadata": {},
260
+ "outputs": [],
261
+ "source": [
262
+ "comments = filter_comments(conversations)\n",
263
+ "comments"
264
+ ]
265
+ }
266
+ ],
267
+ "metadata": {
268
+ "kernelspec": {
269
+ "display_name": ".venv_win (3.11.9)",
270
+ "language": "python",
271
+ "name": "python3"
272
+ },
273
+ "language_info": {
274
+ "codemirror_mode": {
275
+ "name": "ipython",
276
+ "version": 3
277
+ },
278
+ "file_extension": ".py",
279
+ "mimetype": "text/x-python",
280
+ "name": "python",
281
+ "nbconvert_exporter": "python",
282
+ "pygments_lexer": "ipython3",
283
+ "version": "3.11.9"
284
+ }
285
+ },
286
+ "nbformat": 4,
287
+ "nbformat_minor": 5
288
+ }
main.py CHANGED
@@ -23,7 +23,6 @@ from classes.base_models import (
23
  )
24
 
25
  from classes.pii_filter import PIIFilter
26
- from classes.prompt_injection_filter import PromptInjectionFilter
27
  from classes.session_conversation_store import SessionConversationStore
28
  from classes.session_document_store import SessionDocumentStore
29
  from classes.session_tracker import SessionTracker
 
23
  )
24
 
25
  from classes.pii_filter import PIIFilter
 
26
  from classes.session_conversation_store import SessionConversationStore
27
  from classes.session_document_store import SessionDocumentStore
28
  from classes.session_tracker import SessionTracker
static/components/chat-component.js CHANGED
@@ -111,7 +111,7 @@ export const ChatComponent = {
111
  const copyBtn = document.createElement('button');
112
  copyBtn.classList.add('feedback-btn', 'copy-btn');
113
  copyBtn.innerHTML = '📋';
114
- // TODO: if the language changes, the titles are not affected
115
  copyBtn.title = translations[StateManager.currentLang]["copy_reply_btn"];
116
  copyBtn.addEventListener('click', () => {
117
  this.copyMessage(message.content, copyBtn);
@@ -119,9 +119,10 @@ export const ChatComponent = {
119
 
120
  // Like button
121
  const likeBtn = document.createElement('button');
122
- likeBtn.classList.add('feedback-btn');
123
  if (isRated && currentRating === 'like') likeBtn.classList.add('active');
124
  likeBtn.innerHTML = '👍';
 
125
  likeBtn.title = translations[StateManager.currentLang]["feedback_like_btn"];
126
  likeBtn.addEventListener('click', () => {
127
  window.FeedbackComponent.openModal(index, modelType, 'like', message.content);
@@ -129,9 +130,10 @@ export const ChatComponent = {
129
 
130
  // Dislike button
131
  const dislikeBtn = document.createElement('button');
132
- dislikeBtn.classList.add('feedback-btn');
133
  if (isRated && currentRating === 'dislike') dislikeBtn.classList.add('active');
134
  dislikeBtn.innerHTML = '👎';
 
135
  dislikeBtn.title = translations[StateManager.currentLang]["feedback_dislike_btn"];
136
  dislikeBtn.addEventListener('click', () => {
137
  window.FeedbackComponent.openModal(index, modelType, 'dislike', message.content);
@@ -139,9 +141,10 @@ export const ChatComponent = {
139
 
140
  // Mixed button
141
  const mixedBtn = document.createElement('button');
142
- mixedBtn.classList.add('feedback-btn');
143
  if (isRated && currentRating === 'mixed') mixedBtn.classList.add('active');
144
  mixedBtn.innerHTML = '~';
 
145
  mixedBtn.title = translations[StateManager.currentLang]["feedback_mixed_btn"];
146
  mixedBtn.addEventListener('click', () => {
147
  window.FeedbackComponent.openModal(index, modelType, 'mixed', message.content);
 
111
  const copyBtn = document.createElement('button');
112
  copyBtn.classList.add('feedback-btn', 'copy-btn');
113
  copyBtn.innerHTML = '📋';
114
+ copyBtn.dataset.i18nTitle = "copy_reply_btn";
115
  copyBtn.title = translations[StateManager.currentLang]["copy_reply_btn"];
116
  copyBtn.addEventListener('click', () => {
117
  this.copyMessage(message.content, copyBtn);
 
119
 
120
  // Like button
121
  const likeBtn = document.createElement('button');
122
+ likeBtn.classList.add('feedback-btn', 'like-feedback-btn');
123
  if (isRated && currentRating === 'like') likeBtn.classList.add('active');
124
  likeBtn.innerHTML = '👍';
125
+ likeBtn.dataset.i18nTitle = "feedback_like_btn";
126
  likeBtn.title = translations[StateManager.currentLang]["feedback_like_btn"];
127
  likeBtn.addEventListener('click', () => {
128
  window.FeedbackComponent.openModal(index, modelType, 'like', message.content);
 
130
 
131
  // Dislike button
132
  const dislikeBtn = document.createElement('button');
133
+ dislikeBtn.classList.add('feedback-btn', 'dislike-feedback-btn');
134
  if (isRated && currentRating === 'dislike') dislikeBtn.classList.add('active');
135
  dislikeBtn.innerHTML = '👎';
136
+ dislikeBtn.dataset.i18nTitle = "feedback_dislike_btn";
137
  dislikeBtn.title = translations[StateManager.currentLang]["feedback_dislike_btn"];
138
  dislikeBtn.addEventListener('click', () => {
139
  window.FeedbackComponent.openModal(index, modelType, 'dislike', message.content);
 
141
 
142
  // Mixed button
143
  const mixedBtn = document.createElement('button');
144
+ mixedBtn.classList.add('feedback-btn', 'mixed-feedback-btn');
145
  if (isRated && currentRating === 'mixed') mixedBtn.classList.add('active');
146
  mixedBtn.innerHTML = '~';
147
+ mixedBtn.dataset.i18nTitle = "feedback_mixed_btn";
148
  mixedBtn.title = translations[StateManager.currentLang]["feedback_mixed_btn"];
149
  mixedBtn.addEventListener('click', () => {
150
  window.FeedbackComponent.openModal(index, modelType, 'mixed', message.content);
static/services/translation-service.js CHANGED
@@ -11,17 +11,14 @@ export const TranslationService = {
11
  const key = element.getAttribute('data-i18n');
12
  element.textContent = translations[StateManager.currentLang][key];
13
  });
14
-
15
- // Update placeholders
16
- const userInput = document.getElementById('userInput');
17
- const commentInput = document.getElementById('commentInput');
18
-
19
- if (userInput) {
20
- userInput.placeholder = translations[StateManager.currentLang]["input_placeholder"];
21
- }
22
- if (commentInput) {
23
- commentInput.placeholder = translations[StateManager.currentLang]["comment_placeholder"];
24
- }
25
  },
26
 
27
  /**
 
11
  const key = element.getAttribute('data-i18n');
12
  element.textContent = translations[StateManager.currentLang][key];
13
  });
14
+ document.querySelectorAll('[data-i18n-placeholder]').forEach(element => {
15
+ const key = element.getAttribute('data-i18n-placeholder');
16
+ element.placeholder = translations[StateManager.currentLang][key];
17
+ });
18
+ document.querySelectorAll('[data-i18n-title]').forEach(element => {
19
+ const key = element.getAttribute('data-i18n-title');
20
+ element.title = translations[StateManager.currentLang][key];
21
+ });
 
 
 
22
  },
23
 
24
  /**
static/styles/base.css CHANGED
@@ -154,9 +154,6 @@ svg {
154
  box-sizing: border-box;
155
  margin: 0 auto;
156
 
157
- /* Prevent the modal from touching the edges of the screen */
158
- width: 90%;
159
-
160
  /* Enable scrolling */
161
  overflow-y: auto;
162
  }
@@ -189,7 +186,6 @@ svg {
189
  .language-modal,
190
  .consent-box,
191
  .profile,
192
- .settings-modal-content,
193
  .feedback-modal {
194
  display: flex;
195
  flex-direction: column;
 
154
  box-sizing: border-box;
155
  margin: 0 auto;
156
 
 
 
 
157
  /* Enable scrolling */
158
  overflow-y: auto;
159
  }
 
186
  .language-modal,
187
  .consent-box,
188
  .profile,
 
189
  .feedback-modal {
190
  display: flex;
191
  flex-direction: column;
static/styles/components/comment.css CHANGED
@@ -9,6 +9,7 @@
9
  border-radius: 15px;
10
  border: 1px solid #2c3554;
11
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
 
12
  }
13
 
14
  .comment-area h2 {
 
9
  border-radius: 15px;
10
  border: 1px solid #2c3554;
11
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
12
+ width: 90%;
13
  }
14
 
15
  .comment-area h2 {
static/styles/components/feedback.css CHANGED
@@ -76,6 +76,7 @@
76
  /* Feedback modal */
77
  .feedback-modal {
78
  position: relative;
 
79
  }
80
 
81
  .feedback-modal h2 {
 
76
  /* Feedback modal */
77
  .feedback-modal {
78
  position: relative;
79
+ width: 90%;
80
  }
81
 
82
  .feedback-modal h2 {
static/styles/components/settings.css CHANGED
@@ -16,7 +16,12 @@
16
  }
17
 
18
  .settings-modal-content {
 
 
19
  position: relative;
 
 
 
20
  }
21
 
22
  /* Font size */
@@ -24,7 +29,8 @@
24
  display: flex;
25
  gap: 12px;
26
  margin-top: 8px;
27
- justify-content: flex-start;
 
28
  }
29
 
30
  .font-size-btn {
@@ -50,11 +56,3 @@
50
  .font-size-btn:active {
51
  transform: translateY(0);
52
  }
53
-
54
-
55
- /* Responsive */
56
- @media (max-width: 768px) {
57
- .font-size-container {
58
- justify-content: center;
59
- }
60
- }
 
16
  }
17
 
18
  .settings-modal-content {
19
+ width: 480px;
20
+ max-width: 95%;
21
  position: relative;
22
+ display: flex;
23
+ flex-direction: column;
24
+ justify-content: space-between;
25
  }
26
 
27
  /* Font size */
 
29
  display: flex;
30
  gap: 12px;
31
  margin-top: 8px;
32
+ margin-bottom: 8px;
33
+ justify-content: center;
34
  }
35
 
36
  .font-size-btn {
 
56
  .font-size-btn:active {
57
  transform: translateY(0);
58
  }
 
 
 
 
 
 
 
 
static/translations.js CHANGED
@@ -1,7 +1,7 @@
1
  const translations = {
2
  en: {
3
  header: "CHAMP Model Comparison",
4
- sub_header: "Talk to and compare chatbots powered by different models. Please remember to avoid sharing any sensitive or private details during the conversation.",
5
 
6
  user_guide_label: "User guide:",
7
  user_guide_link: "CHAMP Model Comparison – Participant Testing Guide",
@@ -24,7 +24,7 @@ const translations = {
24
  btn_agree_continue: "Agree and Continue",
25
 
26
  profile_title: "Profile",
27
- profile_desc: "We collect this information to help us understand how different groups of users interact with the system. This data allows us to improve the system and ensure the tool is effective for everyone.",
28
  select_option: "(Please select an option)",
29
  label_age: "Age group",
30
  label_gender: "Gender",
@@ -44,7 +44,7 @@ const translations = {
44
  link_comment: "Leave a comment",
45
 
46
  comment_title: "Leave a comment",
47
- comment_placeholder: "Type your comment and click Send...",
48
  comment_sent: "Comment sent!",
49
 
50
  file_title: "Add a file",
@@ -92,15 +92,16 @@ const translations = {
92
 
93
  feedback_for_message: "Message:",
94
  feedback_comment_label: "Tell us why (optional)",
95
- feedback_comment_placeholder: "Your feedback helps us improve...",
96
  feedback_optional: "You can submit without a comment",
97
- btn_submit: "Submit",
98
 
99
  message_copied: "Message copied to clipboard!",
100
  feedback_submitted: "Feedback submitted successfully!",
101
  feedback_failed_server_error: "Feedback submission failed: server error",
102
  feedback_failed_network_error: "Feedback submission failed: network error",
103
 
 
 
104
  done_btn: "Done",
105
 
106
  ready: "Ready",
@@ -114,13 +115,14 @@ const translations = {
114
  network_error: "Network error",
115
 
116
  btn_send: "Send",
 
117
  btn_cancel: "Cancel",
118
 
119
  show_more: "About this demo",
120
  },
121
  fr: {
122
  header: "Comparaison de Modèles CHAMP",
123
- sub_header: "Discutez avec des chatbots propulsés par différents modèles et comparez-les. Veillez à ne partager aucune information sensible ou privée durant la conversation.",
124
 
125
  user_guide_label: "Guide de l'utilisateur :",
126
  user_guide_link: "Comparaison de Modèles CHAMP – Guide de test du participant",
@@ -142,7 +144,7 @@ const translations = {
142
  btn_agree_continue: "Accepter et continuer",
143
 
144
  profile_title: "Profil",
145
- profile_desc: "Nous collectons ces informations pour nous aider à comprendre comment différents groupes d'utilisateurs interagissent avec le système. Ces données nous permettent d'améliorer le système et d'assurer que cet outil est efficace pour tout le monde.",
146
  select_option: "(Veuillez sélectionner une option)",
147
  label_age: "Tranche d'âge",
148
  label_gender: "Genre",
@@ -209,15 +211,16 @@ const translations = {
209
  feedback_neutral_title: "Vous pensez que cette réponse peut être améliorée",
210
  feedback_for_message: "Message :",
211
  feedback_comment_label: "Dites-nous pourquoi (facultatif)",
212
- feedback_comment_placeholder: "Vos commentaires nous aident à nous améliorer...",
213
  feedback_optional: "Vous pouvez soumettre sans commentaire",
214
- btn_submit: "Soumettre",
215
 
216
  message_copied: "Message copié dans le presse-papiers !",
217
  feedback_submitted: "Retour envoyé avec succès !",
218
  feedback_failed_server_error: "Échec de l'envoi du retour: erreur du serveur",
219
  feedback_failed_network_error: "Échec de l'envoi du retour: erreur réseau",
220
 
 
 
221
  done_btn: "Terminer",
222
 
223
  ready: "Prêt",
@@ -231,6 +234,7 @@ const translations = {
231
  network_error: "Erreur réseau",
232
 
233
  btn_send: "Envoyer",
 
234
  btn_cancel: "Annuler",
235
 
236
  show_more: "À propos de cette démo",
 
1
  const translations = {
2
  en: {
3
  header: "CHAMP Model Comparison",
4
+ sub_header: "Talk to different models and compare their reponses. Please remember to avoid sharing any sensitive or private details during the conversation.",
5
 
6
  user_guide_label: "User guide:",
7
  user_guide_link: "CHAMP Model Comparison – Participant Testing Guide",
 
24
  btn_agree_continue: "Agree and Continue",
25
 
26
  profile_title: "Profile",
27
+ profile_desc: "We collect this information to help us understand how different groups of users interact with the system.",
28
  select_option: "(Please select an option)",
29
  label_age: "Age group",
30
  label_gender: "Gender",
 
44
  link_comment: "Leave a comment",
45
 
46
  comment_title: "Leave a comment",
47
+ comment_placeholder: "Type your comment and press Enter or click Send...",
48
  comment_sent: "Comment sent!",
49
 
50
  file_title: "Add a file",
 
92
 
93
  feedback_for_message: "Message:",
94
  feedback_comment_label: "Tell us why (optional)",
95
+ feedback_comment_placeholder: "Type your comment and press Enter or click Send...",
96
  feedback_optional: "You can submit without a comment",
 
97
 
98
  message_copied: "Message copied to clipboard!",
99
  feedback_submitted: "Feedback submitted successfully!",
100
  feedback_failed_server_error: "Feedback submission failed: server error",
101
  feedback_failed_network_error: "Feedback submission failed: network error",
102
 
103
+ settings_btn: "Settings",
104
+
105
  done_btn: "Done",
106
 
107
  ready: "Ready",
 
115
  network_error: "Network error",
116
 
117
  btn_send: "Send",
118
+ btn_submit: "Submit",
119
  btn_cancel: "Cancel",
120
 
121
  show_more: "About this demo",
122
  },
123
  fr: {
124
  header: "Comparaison de Modèles CHAMP",
125
+ sub_header: "Discutez avec différents modèles et comparez leurs réponses. Veillez à ne partager aucune information sensible ou privée durant la conversation.",
126
 
127
  user_guide_label: "Guide de l'utilisateur :",
128
  user_guide_link: "Comparaison de Modèles CHAMP – Guide de test du participant",
 
144
  btn_agree_continue: "Accepter et continuer",
145
 
146
  profile_title: "Profil",
147
+ profile_desc: "Nous collectons ces informations pour nous aider à comprendre comment différents groupes d'utilisateurs interagissent avec le système.",
148
  select_option: "(Veuillez sélectionner une option)",
149
  label_age: "Tranche d'âge",
150
  label_gender: "Genre",
 
211
  feedback_neutral_title: "Vous pensez que cette réponse peut être améliorée",
212
  feedback_for_message: "Message :",
213
  feedback_comment_label: "Dites-nous pourquoi (facultatif)",
214
+ feedback_comment_placeholder: "Tapez votre commentaire et appuyez sur Entrée ou cliquez sur Envoyer...",
215
  feedback_optional: "Vous pouvez soumettre sans commentaire",
 
216
 
217
  message_copied: "Message copié dans le presse-papiers !",
218
  feedback_submitted: "Retour envoyé avec succès !",
219
  feedback_failed_server_error: "Échec de l'envoi du retour: erreur du serveur",
220
  feedback_failed_network_error: "Échec de l'envoi du retour: erreur réseau",
221
 
222
+ settings_btn: "Paramètres",
223
+
224
  done_btn: "Terminer",
225
 
226
  ready: "Prêt",
 
234
  network_error: "Erreur réseau",
235
 
236
  btn_send: "Envoyer",
237
+ btn_submit: "Soumettre",
238
  btn_cancel: "Annuler",
239
 
240
  show_more: "À propos de cette démo",
templates/index.html CHANGED
@@ -48,7 +48,7 @@
48
  <button id="clearBtn" class="clear-button" data-i18n="btn_clear"></button>
49
  </fieldset>
50
 
51
- <button id="settings-btn" class="settings-button">⚙️</button>
52
  </div>
53
 
54
  <!-- Settings overlay -->
@@ -190,8 +190,8 @@
190
  <label for="feedbackInput" data-i18n="feedback_comment_label"></label>
191
  <textarea
192
  id="feedbackInput"
193
- rows="4"
194
- maxlength="500"
195
  data-i18n-placeholder="feedback_comment_placeholder"
196
  ></textarea>
197
  <small class="form-hint unselectable" data-i18n="feedback_optional"></small>
@@ -199,7 +199,7 @@
199
 
200
  <div class="button-group">
201
  <button id="cancelFeedbackBtn" class="cancelBtn" data-i18n="btn_cancel"></button>
202
- <button id="submitFeedbackBtn" class="ok-button" data-i18n="btn_submit"></button>
203
  </div>
204
  </div>
205
  </div>
@@ -210,10 +210,11 @@
210
  <textarea
211
  id="userInput"
212
  rows="2"
213
- maxlength="1000"
 
214
  ></textarea>
215
  <div class="chat-toolbar">
216
- <button id="upload-file-btn" title="Upload file" class="toolbar-btn" data-i18n="btn_add_file"></button>
217
  </div>
218
  </div>
219
 
@@ -233,7 +234,9 @@
233
  <h2 data-i18n="comment_title"></h2>
234
  <textarea
235
  id="commentInput"
236
- maxlength="1000"
 
 
237
  ></textarea>
238
  <div id="commentStatus" class="comment-status"></div>
239
  <div class="button-group">
@@ -250,6 +253,7 @@
250
  <h2 data-i18n="file_title"></h2>
251
  <p data-i18n="file_inactivity"></p>
252
  <p data-i18n="file_format"></p>
 
253
  <h3 data-i18n="file_list_title"></h3>
254
  <div id="file-list" class="file-list">
255
  <!-- No files added yet -->
 
48
  <button id="clearBtn" class="clear-button" data-i18n="btn_clear"></button>
49
  </fieldset>
50
 
51
+ <button id="settings-btn" class="settings-button" data-i18n-title="settings_btn">⚙️</button>
52
  </div>
53
 
54
  <!-- Settings overlay -->
 
190
  <label for="feedbackInput" data-i18n="feedback_comment_label"></label>
191
  <textarea
192
  id="feedbackInput"
193
+ rows="20"
194
+ maxlength="2500"
195
  data-i18n-placeholder="feedback_comment_placeholder"
196
  ></textarea>
197
  <small class="form-hint unselectable" data-i18n="feedback_optional"></small>
 
199
 
200
  <div class="button-group">
201
  <button id="cancelFeedbackBtn" class="cancelBtn" data-i18n="btn_cancel"></button>
202
+ <button id="submitFeedbackBtn" class="ok-button" data-i18n="btn_send"></button>
203
  </div>
204
  </div>
205
  </div>
 
210
  <textarea
211
  id="userInput"
212
  rows="2"
213
+ maxlength="2500"
214
+ data-i18n-placeholder="input_placeholder"
215
  ></textarea>
216
  <div class="chat-toolbar">
217
+ <button id="upload-file-btn" class="toolbar-btn" data-i18n="btn_add_file"></button>
218
  </div>
219
  </div>
220
 
 
234
  <h2 data-i18n="comment_title"></h2>
235
  <textarea
236
  id="commentInput"
237
+ maxlength="2500"
238
+ data-i18n-placeholder="comment_placeholder"
239
+ rows="20"
240
  ></textarea>
241
  <div id="commentStatus" class="comment-status"></div>
242
  <div class="button-group">
 
253
  <h2 data-i18n="file_title"></h2>
254
  <p data-i18n="file_inactivity"></p>
255
  <p data-i18n="file_format"></p>
256
+ <p data-i18n="file_size_limit"></p>
257
  <h3 data-i18n="file_list_title"></h3>
258
  <div id="file-list" class="file-list">
259
  <!-- No files added yet -->