Preference-Dissection commited on
Commit
28928f8
1 Parent(s): 38af891

init commit

Browse files
Files changed (27) hide show
  1. .gitattributes +1 -0
  2. .gitignore +2 -0
  3. README.md +5 -5
  4. app.py +936 -0
  5. data/chatbot_arena_no-tie_group_balanced_resolved.jsonl +3 -0
  6. data/chatbot_arena_shuffled_no-tie_gpt4_ref_group_balanced.jsonl +3 -0
  7. data/chatbot_arena_shuffled_no-tie_group_balanced.jsonl +3 -0
  8. data/example_preference_labels.json +1 -0
  9. data/fitted_paras_comparison/model_Advice_fitted_paras.jsonl +3 -0
  10. data/fitted_paras_comparison/model_Code_fitted_paras.jsonl +3 -0
  11. data/fitted_paras_comparison/model_Communication_fitted_paras.jsonl +3 -0
  12. data/fitted_paras_comparison/model_Creative Writing_fitted_paras.jsonl +3 -0
  13. data/fitted_paras_comparison/model_Daily Tasks_fitted_paras.jsonl +3 -0
  14. data/fitted_paras_comparison/model_Exam Questions_fitted_paras.jsonl +3 -0
  15. data/fitted_paras_comparison/model_Functional Writing_fitted_paras.jsonl +3 -0
  16. data/fitted_paras_comparison/model_Knowledge-aware_fitted_paras.jsonl +3 -0
  17. data/fitted_paras_comparison/model_NLP Tasks_fitted_paras.jsonl +3 -0
  18. data/fitted_paras_comparison/model_Others_fitted_paras.jsonl +3 -0
  19. data/fitted_paras_comparison/model_Unsafe Queries_fitted_paras.jsonl +3 -0
  20. data/fitted_paras_comparison/model_express_feeling_fitted_paras.jsonl +3 -0
  21. data/fitted_paras_comparison/model_intent_unclear_fitted_paras.jsonl +3 -0
  22. data/fitted_paras_comparison/model_w_constraints_fitted_paras.jsonl +3 -0
  23. data/fitted_paras_comparison/model_w_mistakes_fitted_paras.jsonl +3 -0
  24. data/fitted_paras_comparison/model_w_stances_fitted_paras.jsonl +3 -0
  25. data/query_aware_idxs.json +0 -0
  26. requirements.txt +10 -0
  27. utils.py +118 -0
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ *.jsonl filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ __pycache__
2
+ .idea
README.md CHANGED
@@ -1,10 +1,10 @@
1
  ---
2
- title: Preference Dissection Visualization
3
- emoji: 🌖
4
- colorFrom: green
5
- colorTo: green
6
  sdk: streamlit
7
- sdk_version: 1.31.1
8
  app_file: app.py
9
  pinned: false
10
  license: mit
 
1
  ---
2
+ title: Preference Decomp Vis
3
+ emoji: 🚀
4
+ colorFrom: yellow
5
+ colorTo: indigo
6
  sdk: streamlit
7
+ sdk_version: 1.30.0
8
  app_file: app.py
9
  pinned: false
10
  license: mit
app.py ADDED
@@ -0,0 +1,936 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import os
3
+ from utils import read_all, json_to_markdown_bold_keys, custom_md_with_color
4
+ from scipy.stats import pearsonr, spearmanr
5
+ import seaborn as sns
6
+ import pandas as pd
7
+ import json
8
+
9
+ import jax
10
+ import jax.numpy as jnp
11
+ import numpy as np
12
+ import numpyro
13
+ import numpyro.distributions as dist
14
+ from numpyro.infer import MCMC, NUTS
15
+ from matplotlib import pyplot as plt
16
+ import shap
17
+ from functools import partial
18
+
19
+
20
+ import base64
21
+
22
+ numpyro.set_host_device_count(4)
23
+
24
+ feature_name_to_id = {
25
+ "harmlessness": 0,
26
+ "grammar, spelling, punctuation, and code-switching": 1,
27
+ "friendly": 2,
28
+ "polite": 3,
29
+ "interactive": 4,
30
+ "authoritative tone": 5,
31
+ "funny and humorous": 6,
32
+ "metaphors, personification, similes, hyperboles, irony, parallelism": 7,
33
+ "complex word usage and sentence structure": 8,
34
+ "use of direct and explicit supporting materials": 9,
35
+ "well formatted": 10,
36
+ "admit limitations or mistakes": 11,
37
+ "persuade user": 12,
38
+ "step by step solution": 13,
39
+ "use of informal expressions": 14,
40
+ "non-repetitive": 15,
41
+ "clear and understandable": 16,
42
+ "relevance without considering inaccuracy": 17,
43
+ "innovative and novel": 18,
44
+ "information richness without considering inaccuracy": 19,
45
+ "no minor errors": 20,
46
+ "no moderate errors": 21,
47
+ "no severe errors": 22,
48
+ "clarify user intent": 23,
49
+ "showing empathetic": 24,
50
+ "satisfying explicit constraints": 25,
51
+ "supporting explicit subjective stances": 26,
52
+ "correcting explicit mistakes or biases": 27,
53
+ "length": 28,
54
+ }
55
+
56
+ feature_name_to_id_short = {
57
+ "harmless": 0,
58
+ "grammarly correct": 1,
59
+ "friendly": 2,
60
+ "polite": 3,
61
+ "interactive": 4,
62
+ "authoritative": 5,
63
+ "funny": 6,
64
+ "use rhetorical devices": 7,
65
+ "complex word & sentence": 8,
66
+ "use supporting materials": 9,
67
+ "well formatted": 10,
68
+ "admit limits": 11,
69
+ "persuasive": 12,
70
+ "step-by-step": 13,
71
+ "use informal expressions": 14,
72
+ "non-repetitive": 15,
73
+ "clear": 16,
74
+ "relevant": 17,
75
+ "novel": 18,
76
+ "contain rich info": 19,
77
+ "no minor errors": 20,
78
+ "no moderate errors": 21,
79
+ "no severe errors": 22,
80
+ "clarify intent": 23,
81
+ "show empathetic": 24,
82
+ "satisfy constraints": 25,
83
+ "support stances": 26,
84
+ "correct mistakes": 27,
85
+ "lengthy": 28,
86
+ }
87
+
88
+ small_mapping_for_query_specific_cases = {
89
+ "w_constraints": "Contain Explicit Constraints",
90
+ "w_stances": "Show Explicit Subjective Stances",
91
+ "w_mistakes": "Contain Mistakes or Bias",
92
+ "intent_unclear": "Unclear User Intent",
93
+ "express_feeling": "Express Feelings of Emotions",
94
+ }
95
+
96
+ pre_set_full_model_order = [
97
+ "yi-6b",
98
+ "yi-6b-chat",
99
+ "llama-2-7b",
100
+ "llama-2-7b-chat",
101
+ "vicuna-7b-v1.5",
102
+ "tulu-2-dpo-7b",
103
+ "mistral-7b",
104
+ "mistral-7b-instruct-v0.1",
105
+ "mistral-7b-instruct-v0.2",
106
+ "zephyr-7b-alpha",
107
+ "zephyr-7b-beta",
108
+ "qwen-7b",
109
+ "qwen-7b-chat",
110
+ "llama-2-13b",
111
+ "llama-2-13b-chat",
112
+ "wizardLM-13b-v1.2",
113
+ "vicuna-13b-v1.5",
114
+ "tulu-2-dpo-13b",
115
+ "qwen-14b",
116
+ "qwen-14b-chat",
117
+ "yi-34b",
118
+ "yi-34b-chat",
119
+ "mistral-8x7b",
120
+ "mistral-8x7b-instruct-v0.1",
121
+ "llama-2-70b",
122
+ "llama-2-70b-chat",
123
+ "wizardLM-70b-v1.0",
124
+ "tulu-2-dpo-70b",
125
+ "qwen-72b",
126
+ "qwen-72b-chat",
127
+ "gpt-3.5-turbo-1106",
128
+ "gpt-4-1106-preview",
129
+ "human",
130
+ ]
131
+
132
+ feature_id_to_name_short = {v: k for k, v in feature_name_to_id_short.items()}
133
+
134
+ feature_names_short = list(feature_name_to_id_short.keys())
135
+
136
+ all_models_fitted_params = {}
137
+
138
+ def formal_group_name(part):
139
+ if part[0].isupper():
140
+ part = f"[Scenario] {part}"
141
+ else:
142
+ part = f"[Query-Specific Cases] {small_mapping_for_query_specific_cases[part]}"
143
+ return part
144
+
145
+ for fn in os.listdir(f"./data/fitted_paras_comparison"):
146
+ part = fn[len("model_"): fn.find("_fitted_paras")]
147
+ part = formal_group_name(part)
148
+ if part not in all_models_fitted_params:
149
+ all_models_fitted_params[part] = {}
150
+ dd = read_all(f"./data/fitted_paras_comparison/{fn}")
151
+ for it in dd:
152
+ all_models_fitted_params[part][it["model_name"]] = it["parameters"]
153
+
154
+ modelwise_fitted_paras = {}
155
+ for group in all_models_fitted_params:
156
+ for model in all_models_fitted_params[group]:
157
+ if model not in modelwise_fitted_paras:
158
+ modelwise_fitted_paras[model] = {}
159
+ modelwise_fitted_paras[model][group] = all_models_fitted_params[group][model]
160
+
161
+
162
+ def show_one_model_prob(weights, feature_names=None):
163
+ plt.figure(figsize=(20, 7))
164
+
165
+ plt.rcParams["font.family"] = "Times New Roman"
166
+ plt.rcParams["font.size"] = 20
167
+
168
+ all_probabilities = []
169
+
170
+ weights = np.asarray(weights)
171
+ posterior_means = weights
172
+ X_test = np.eye(weights.shape[0])
173
+
174
+ logits = X_test @ posterior_means
175
+ probabilities = 100 / (1 + np.exp(-logits))
176
+ all_probabilities.extend(probabilities)
177
+
178
+ plt.scatter(
179
+ range(0, weights.shape[0]),
180
+ probabilities,
181
+ label='apple',
182
+ s=380,
183
+ alpha=0.65,
184
+ )
185
+
186
+ min_prob = min(all_probabilities)
187
+ max_prob = max(all_probabilities)
188
+ plt.ylim([min_prob - 3, max_prob + 3])
189
+
190
+ # plt.xlabel('Feature Names')
191
+ plt.ylabel("Probability of Preferred (%)")
192
+ # plt.legend(loc="upper left", bbox_to_anchor=(1, 1))
193
+
194
+ if feature_names is not None:
195
+ plt.xticks(range(0, len(feature_names)), feature_names, rotation=45, ha="right")
196
+ else:
197
+ plt.xticks(range(0, weights.shape[0]), ha="center")
198
+
199
+ plt.grid(True)
200
+ plt.axhline(y=50, color="red", linestyle="--")
201
+
202
+ plt.subplots_adjust(bottom=0.3, right=0.85)
203
+ plt.tight_layout()
204
+ st.pyplot(plt)
205
+ plt.clf()
206
+
207
+
208
+ def show_all_models_prob(models, selected_models, feature_names=None):
209
+ plt.figure(figsize=(17, 7))
210
+
211
+ plt.rcParams["font.family"] = "Times New Roman"
212
+ plt.rcParams["font.size"] = 20
213
+
214
+ all_probabilities = []
215
+ for model_name in selected_models:
216
+ weights = np.asarray(models[model_name])
217
+ posterior_means = weights
218
+ X_test = np.eye(weights.shape[0])
219
+
220
+ logits = X_test @ posterior_means
221
+ probabilities = 100 / (1 + np.exp(-logits))
222
+ all_probabilities.extend(probabilities)
223
+
224
+ plt.scatter(
225
+ range(0, weights.shape[0]),
226
+ probabilities,
227
+ label=model_name,
228
+ s=380,
229
+ alpha=0.65,
230
+ )
231
+
232
+ min_prob = min(all_probabilities)
233
+ max_prob = max(all_probabilities)
234
+ plt.ylim([min_prob - 3, max_prob + 3])
235
+
236
+ # plt.xlabel('Feature Names')
237
+ plt.ylabel("Probability of Preferred (%)")
238
+ plt.legend(loc="upper left", bbox_to_anchor=(1, 1))
239
+
240
+ if feature_names is not None:
241
+ plt.xticks(range(0, len(feature_names)), feature_names, rotation=45, ha="right")
242
+ else:
243
+ plt.xticks(range(0, weights.shape[0]), ha="center")
244
+
245
+ plt.grid(True)
246
+ plt.axhline(y=50, color="red", linestyle="--")
247
+
248
+ plt.subplots_adjust(bottom=0.3, right=0.85)
249
+ plt.tight_layout()
250
+ st.pyplot(plt)
251
+ plt.clf()
252
+
253
+
254
+ def process_query_info(x):
255
+ s = []
256
+ if x["clear intent"] != "Yes":
257
+ s.append("[Query-Specific Cases] Unclear User Intent")
258
+ if x["explicitly express feelings"] == "Yes":
259
+ s.append("[Query-Specific Cases] Express Feelings of Emotions")
260
+ if len(x["explicit constraints"]) > 0:
261
+ s.append("[Query-Specific Cases] Contain Explicit Constraints")
262
+ if len(x["explicit subjective stances"]) > 0:
263
+ s.append("[Query-Specific Cases] Show Explicit Subjective Stances")
264
+ if len(x["explicit mistakes or biases"]) > 0:
265
+ s.append("[Query-Specific Cases] Contain Mistakes or Bias")
266
+ return s
267
+
268
+
269
+ def get_feature(item, remove_length=False, way="comparison"):
270
+ # way be "comparison" or "diff" or "norm_diff"
271
+ feature = [0] * len(feature_name_to_id)
272
+ comparison = item["comparison"]
273
+ for k, v in comparison.items():
274
+ if k == "accuracy":
275
+ for xx in ["Severe", "Moderate", "Minor"]:
276
+ feature[feature_name_to_id[f"no {xx.lower()} errors"]] = v[way][xx]
277
+ elif k == "repetitive":
278
+ feature[feature_name_to_id["non-repetitive"]] = -v[way]
279
+ else:
280
+ feature[feature_name_to_id[k]] = v[way]
281
+ if remove_length:
282
+ feature = feature[:-1]
283
+ return feature
284
+
285
+
286
+ class BayesianLogisticRegression:
287
+ def __init__(self, alpha):
288
+ self.alpha = alpha
289
+
290
+ def predict(self, X):
291
+ probs = self.return_prob(X)
292
+ predictions = np.round(probs)
293
+ return predictions
294
+
295
+ def return_prob(self, X):
296
+ logits = np.dot(X, self.alpha)
297
+ # return probabilities
298
+ return np.exp(logits) / (1 + np.exp(logits))
299
+
300
+
301
+ def bayesian_logistic_regression(X, y, scale=0.01):
302
+ # Priors for the regression coefficients
303
+ alpha = numpyro.sample('alpha', dist.Laplace(loc=jnp.zeros(X.shape[1]), scale=scale))
304
+
305
+ # Calculate the linear predictor (the logits) using JAX NumPy
306
+ logits = jnp.dot(X, alpha)
307
+
308
+ # Likelihood of the observations given the logistic model
309
+ with numpyro.plate('data', X.shape[0]):
310
+ numpyro.sample('obs', dist.Bernoulli(logits=logits), obs=y)
311
+
312
+
313
+ def fit_bayes_logistic_regression(X, y, scale=0.1, ):
314
+ # repeat X and y on the first axis to get more samples
315
+
316
+ bxx = partial(bayesian_logistic_regression, scale=scale)
317
+
318
+ kernel = NUTS(bxx)
319
+ mcmc = MCMC(kernel, num_warmup=500, num_samples=2000, num_chains=4, progress_bar=False)
320
+ mcmc.run(jax.random.PRNGKey(0), X, y)
321
+
322
+ # Get the posterior samples
323
+ posterior_samples = mcmc.get_samples()
324
+
325
+ # Compute the mean of the posterior for each alpha_i
326
+ alpha_mean = np.mean(posterior_samples['alpha'], axis=0).tolist()
327
+
328
+ return BayesianLogisticRegression(alpha_mean), alpha_mean
329
+
330
+
331
+ def get_similarity(dict1, dict2, type="pearson", select_part="Overall"):
332
+ assert dict1.keys() == dict2.keys(), "Dicts must have the same keys"
333
+ if select_part == "Overall":
334
+ all_sim = 0.0
335
+ count = 0.0
336
+ for key in dict1.keys():
337
+ if key.startswith("[Query-Specific Cases]"): continue
338
+ sim = get_similarity_local(dict1[key], dict2[key], type)
339
+ all_sim += sim
340
+ count += 1
341
+ return all_sim / count
342
+ else:
343
+ return get_similarity_local(dict1[select_part], dict2[select_part], type)
344
+
345
+
346
+ def get_similarity_local(list1, list2, type="pearson"):
347
+ """
348
+ Calculate the similarity between two lists of numbers based on the specified type.
349
+
350
+ :param list1: a dict, each field is a list of floats
351
+ :param list2: a dict, each field is a list of floats
352
+ :param type: which kind of 'similarity' is calculated
353
+ :return: the calculated similarity
354
+ """
355
+ assert len(list1) == len(list2), "Lists must be of the same length"
356
+
357
+ if type == "pearson":
358
+ # Pearson correlation
359
+ similarity, _ = pearsonr(list1, list2)
360
+ elif type == "spearman":
361
+ # Spearman correlation
362
+ similarity, _ = spearmanr(list1, list2)
363
+ elif type == "normed_l1":
364
+ # Normalized negative L1 norm (Manhattan distance)
365
+ similarity = -np.sum(np.abs(np.array(list1) - np.array(list2))) / len(list1)
366
+ elif type == "normed_l2":
367
+ # Normalized negative L2 norm (Euclidean distance)
368
+ similarity = -np.sqrt(np.sum((np.array(list1) - np.array(list2)) ** 2)) / len(
369
+ list1
370
+ )
371
+ else:
372
+ raise NotImplementedError("The specified similarity type is not implemented")
373
+
374
+ return similarity
375
+
376
+
377
+ @st.cache_resource
378
+ def calculate_similarity_matrix(
379
+ modelwise_fitted_paras, selected_models, similarity_type, selected_part
380
+ ):
381
+ # Initialize a matrix to store similarities
382
+ if similarity_type in ["spearman", "pearson"]:
383
+ similarity_matrix = np.ones((len(selected_models), len(selected_models)))
384
+ else:
385
+ similarity_matrix = np.zeros((len(selected_models), len(selected_models)))
386
+
387
+ # Calculate similarities
388
+ for i, model1 in enumerate(selected_models):
389
+ for j, model2 in enumerate(selected_models):
390
+ if i < j: # Calculate only for upper triangular matrix
391
+ sim = get_similarity(
392
+ modelwise_fitted_paras[model1],
393
+ modelwise_fitted_paras[model2],
394
+ similarity_type,
395
+ selected_part,
396
+ )
397
+ similarity_matrix[i, j] = sim
398
+ similarity_matrix[j, i] = sim # Symmetric matrix
399
+ return similarity_matrix
400
+
401
+
402
+ def format_matrix(matrix):
403
+ formatted_matrix = np.array(matrix, dtype=str)
404
+ for i in range(matrix.shape[0]):
405
+ for j in range(matrix.shape[1]):
406
+ formatted_matrix[i, j] = f"{matrix[i, j]:.2f}".lstrip("0")
407
+ return formatted_matrix
408
+
409
+
410
+ def become_formal(name):
411
+ name = (
412
+ name.replace("6b", "6B")
413
+ .replace("7b", "7B")
414
+ .replace("13b", "13B")
415
+ .replace("14b", "14B")
416
+ .replace("34b", "34B")
417
+ .replace("70b", "70B")
418
+ .replace("72b", "72B")
419
+ )
420
+ name = (
421
+ name.replace("llama", "LLaMA")
422
+ .replace("yi", "Yi")
423
+ .replace("mistral", "Mistral")
424
+ .replace("qwen", "Qwen")
425
+ .replace("tulu", "Tulu")
426
+ .replace("vicuna", "Vicuna")
427
+ .replace("wizardLM", "WizardLM")
428
+ .replace("zephyr", "Zephyr")
429
+ )
430
+ name = name.replace("chat", "Chat")
431
+ name = name.replace("gpt-3.5-turbo-1106", "GPT-3.5-Turbo").replace(
432
+ "gpt-4-1106-preview", "GPT-4-Turbo"
433
+ )
434
+ name = (
435
+ name.replace("instruct", "Inst").replace("dpo", "DPO").replace("human", "Human")
436
+ )
437
+ return name
438
+
439
+
440
+ def display_markdown_with_scroll(text, height=200):
441
+ """
442
+ Display the given Markdown text in a scrollable area using <pre> tag.
443
+
444
+ Args:
445
+ text (str): The Markdown text to be displayed.
446
+ height (int): Height of the scrollable area in pixels.
447
+ """
448
+ # 使用 <pre> 标签来包裹 Markdown 内容,并添加 CSS 样式创建可滚动的区域
449
+ markdown_container = f"""
450
+ <pre style="
451
+ overflow-y: scroll;
452
+ height: {height}px;
453
+ border: 1px solid #ccc;
454
+ padding: 10px;
455
+ margin-bottom: 20px;
456
+ background-color: #f5f5f5;
457
+ ">
458
+ {text}
459
+ </pre>
460
+ """
461
+
462
+ st.markdown(markdown_container, unsafe_allow_html=True)
463
+
464
+
465
+ @st.cache_resource
466
+ def compute_one_model_fitted_params(filename, num_fold, query_aware_idxs, resolved_data):
467
+ st.write('---------------')
468
+ one_model_fitted_params = {}
469
+ data = json.load(filename)
470
+ uploaded_labels = [1 if x == "A" else 0 for x in data]
471
+
472
+ ccount=0
473
+
474
+ for part in list(query_aware_idxs.keys()):
475
+ if part == "all": continue
476
+ # 使用 st.empty 创建占位符
477
+ progress_text = st.empty()
478
+ # if part not in ["Advice","NLP Tasks"]:continue
479
+ progress_text.write(f"{ccount+1}/{len(list(query_aware_idxs.keys()))-1} "+formal_group_name(part))
480
+ progress_bar = st.progress(0)
481
+ cared_idxs = query_aware_idxs.get(part)
482
+
483
+ features = []
484
+ labels = []
485
+
486
+ for idx, item in enumerate(resolved_data):
487
+ if idx not in cared_idxs: continue
488
+ if item['comparison']['accuracy']['comparison'] == 999: continue
489
+ label = uploaded_labels[idx]
490
+ feature = get_feature(item, remove_length=False, way='comparison')
491
+ features.append(feature)
492
+ labels.append(label)
493
+
494
+ features = np.asarray(features, dtype=np.float32)
495
+ labels = np.asarray(labels)
496
+
497
+ if num_fold>1:
498
+ np.random.seed(0)
499
+ idxs = np.arange(len(features))
500
+ np.random.shuffle(idxs)
501
+ features = features[idxs]
502
+ labels = labels[idxs]
503
+
504
+ final_paras = None
505
+ for i in range(num_fold):
506
+ # take the i/10 as test set
507
+ features_len = len(features)
508
+ split_point = int(i / num_fold * features_len)
509
+ features_train, features_test = np.concatenate(
510
+ [features[:split_point, :], features[split_point + int(features_len / num_fold):, :]],
511
+ axis=0), features[split_point:split_point + int(features_len / num_fold), :]
512
+ labels_train, labels_test = np.concatenate(
513
+ [labels[:split_point], labels[split_point + int(features_len / num_fold):]], axis=0), labels[
514
+ split_point:split_point + int(
515
+ features_len / 10)]
516
+ model, parameters = fit_bayes_logistic_regression(features_train, labels_train, scale=0.1)
517
+ if final_paras is None:
518
+ final_paras = np.asarray(parameters)
519
+ else:
520
+ final_paras += np.asarray(parameters)
521
+ progress_bar.progress((i + 1)/num_fold)
522
+ else:
523
+ model, parameters = fit_bayes_logistic_regression(features, labels, scale=0.1)
524
+ final_paras = np.asarray(parameters)
525
+ progress_bar.progress(1)
526
+
527
+ final_paras /= num_fold
528
+ parameters = final_paras.tolist()
529
+ one_model_fitted_params[formal_group_name(part)] = parameters
530
+
531
+ # 函数处理完毕,清除进度条和文本
532
+ progress_text.empty()
533
+ progress_bar.empty()
534
+ ccount+=1
535
+
536
+ return one_model_fitted_params
537
+
538
+ def get_json_download_link(json_str, file_name, button_text):
539
+ # 创建一个BytesIO对象
540
+ b64 = base64.b64encode(json_str.encode()).decode()
541
+ href = f'<a href="data:file/json;base64,{b64}" download="{file_name}">{button_text}</a>'
542
+ return href
543
+
544
+
545
+ if __name__ == "__main__":
546
+ st.title("Visualization of Preference Dissection")
547
+
548
+ INTRO = """
549
+ This space is used to show visualization results for human and LLM preference analyzed in the following paper:
550
+
551
+
552
+ ***Dissecting Human and LLM Preferences***
553
+
554
+ ------------
555
+
556
+ Specifically, we include:
557
+
558
+ 1. **Complete Preference Dissection in Paper**: shows how the difference of properties in a pair of responses can influence different LLMs'(human included) preference. <br>
559
+ 2. **Preference Similarity Matrix**: shows the preference similarity among different judges. <br>
560
+ 3. **Sample-level SHAP Analysis**: applies shapley value to show how the difference of properties in a pair of responses affect the final preference. <br>
561
+ 4. **Add a New Model for Preference Dissection**: update the preference labels from a new LLM and visualize the results
562
+
563
+ This analysis is based on:
564
+
565
+ > The data we collected here: https://huggingface.co/datasets/Preference-Dissection/preference-dissection
566
+
567
+ > The code we released here: https://anonymous.4open.science/r/Preference-Dissection
568
+ """
569
+ message = custom_md_with_color(INTRO, "DBEFEB")
570
+
571
+ st.markdown(message, unsafe_allow_html=True)
572
+
573
+ section = st.selectbox(
574
+ "**Select Visualization Section**",
575
+ [
576
+ "Complete Preference Dissection in Paper",
577
+ "Preference Similarity Matrix",
578
+ "Sample-level SHAP Analysis",
579
+ 'Add a New Model for Preference Dissection'
580
+ ],
581
+ )
582
+ st.markdown("---")
583
+
584
+ if section == "Complete Preference Dissection in Paper":
585
+ st.header("Complete Preference Dissection in Paper")
586
+ st.markdown("")
587
+ selected_part = st.selectbox(
588
+ "**Scenario/Query-Specific Cases**", list(all_models_fitted_params.keys())
589
+ )
590
+
591
+ models = all_models_fitted_params[selected_part]
592
+
593
+ model_names = list(models.keys())
594
+ selected_models = st.multiselect(
595
+ "**Select LLMs (Human) to display**",
596
+ model_names,
597
+ default=["human", "gpt-4-1106-preview"],
598
+ )
599
+
600
+ st.text(
601
+ "The value for each property indicates that, when response A satisfies only this\nproperty better than response B and all else equal, the probability of response\nA being preferred.")
602
+
603
+ if len(selected_models) > 0:
604
+ show_all_models_prob(models, selected_models, feature_names_short)
605
+ else:
606
+ st.write("Please select at least one model to display.")
607
+ elif section == "Preference Similarity Matrix":
608
+ st.header("Preference Similarity Matrix")
609
+
610
+ # Initialize session state for similarity matrix
611
+
612
+ # convert `groupwise_fitted_paras` to `modelwise_fitted_paras`
613
+
614
+ models = list(modelwise_fitted_paras.keys())
615
+ # Option to choose between preset models or selecting models
616
+ option = st.radio(
617
+ "**Choose your models setting**",
618
+ ("Use Preset Models", "Select Models Manually"),
619
+ )
620
+
621
+ if option == "Use Preset Models":
622
+ selected_models = pre_set_full_model_order
623
+ else:
624
+ selected_models = st.multiselect(
625
+ "**Select Models**", models, default=models[:5]
626
+ )
627
+
628
+ # Input for threshold value
629
+ st.text(
630
+ "The similarity bewteen two judges is the average pearson correlation coefficient of\nthe fitted Bayesian logistic regression models' weights across all scenarios.")
631
+
632
+ selected_part = st.selectbox(
633
+ "**Overall or Scenario/Query-Specific Cases**", ["Overall"] + list(all_models_fitted_params.keys())
634
+ )
635
+
636
+ st.text(
637
+ "\"Overall\" is the average similarity across all scenarios, \nwhile \"Scenario/Query-Specific Cases\" is the similarity within \nthe selected scenario/query-specific cases.")
638
+
639
+ if len(selected_models) >= 2:
640
+ # Call the cached function
641
+ similarity_matrix = calculate_similarity_matrix(
642
+ modelwise_fitted_paras, selected_models, "pearson", selected_part
643
+ )
644
+ # Store the matrix in session state
645
+ # Slider to adjust figure size
646
+ fig_size = (
647
+ 25
648
+ if option == "Use Preset Models"
649
+ else int(33 * len(selected_models) / 25)
650
+ )
651
+
652
+ plt.figure(figsize=(fig_size * 1.1, fig_size))
653
+ ax = sns.heatmap(
654
+ similarity_matrix,
655
+ annot=True,
656
+ annot_kws={"size": 18}, # Change annotation font size
657
+ xticklabels=[become_formal(x) for x in selected_models],
658
+ yticklabels=[become_formal(x) for x in selected_models],
659
+ )
660
+
661
+ # Add this line to get the colorbar object
662
+ cbar = ax.collections[0].colorbar
663
+
664
+ # Here, specify the font size for the colorbar
665
+ for label in cbar.ax.get_yticklabels():
666
+ # label.set_fontsize(20) # Set the font size (change '10' as needed)
667
+ label.set_fontname(
668
+ "Times New Roman"
669
+ ) # Set the font name (change as needed)
670
+
671
+ plt.xticks(rotation=45, fontname="Times New Roman", ha="right")
672
+ plt.yticks(rotation=0, fontname="Times New Roman")
673
+
674
+ plt.tight_layout()
675
+ st.pyplot(plt)
676
+ else:
677
+ st.warning("Please select at least two models.")
678
+ elif section == "Sample-level SHAP Analysis":
679
+ st.header("Sample-level SHAP Analysis")
680
+ resolved_data_file = "./data/chatbot_arena_no-tie_group_balanced_resolved.jsonl"
681
+ source_data_file = "./data/chatbot_arena_shuffled_no-tie_group_balanced.jsonl"
682
+ reference_data_file = (
683
+ "./data/chatbot_arena_shuffled_no-tie_gpt4_ref_group_balanced.jsonl"
684
+ )
685
+
686
+ # Load and prepare data
687
+ resolved_data, source_data, reference_data = (
688
+ read_all(resolved_data_file),
689
+ read_all(source_data_file),
690
+ read_all(reference_data_file),
691
+ )
692
+ ok_idxs = [
693
+ i
694
+ for i, item in enumerate(resolved_data)
695
+ if item["comparison"]["accuracy"]["comparison"] != 999
696
+ ]
697
+ resolved_data, source_data, reference_data = (
698
+ [resolved_data[i] for i in ok_idxs],
699
+ [source_data[i] for i in ok_idxs],
700
+ [reference_data[i] for i in ok_idxs],
701
+ )
702
+ features = np.asarray(
703
+ [
704
+ get_feature(item, remove_length=False, way="comparison")
705
+ for item in resolved_data
706
+ ],
707
+ dtype=np.float32,
708
+ )
709
+
710
+ # Initialize the index
711
+ if "sample_ind" not in st.session_state:
712
+ st.session_state.sample_ind = 0
713
+
714
+
715
+ # Function to update the index
716
+ def update_index(change):
717
+ st.session_state.sample_ind += change
718
+ st.session_state.sample_ind = max(
719
+ 0, min(st.session_state.sample_ind, len(features) - 1)
720
+ )
721
+
722
+
723
+ col1, col2, col3, col4, col5 = st.columns([1, 2, 1, 2, 1])
724
+
725
+ with col1:
726
+ st.button("Prev", on_click=update_index, args=(-1,))
727
+
728
+ with col3:
729
+ number = st.number_input(
730
+ "Go to sample:",
731
+ min_value=0,
732
+ max_value=len(features) - 1,
733
+ value=st.session_state.sample_ind,
734
+ )
735
+ if number != st.session_state.sample_ind:
736
+ st.session_state.sample_ind = number
737
+
738
+ with col5:
739
+ st.button("Next", on_click=update_index, args=(1,))
740
+
741
+ # Use the updated sample index
742
+ sample_ind = st.session_state.sample_ind
743
+
744
+ reference, source, resolved = (
745
+ reference_data[sample_ind],
746
+ source_data[sample_ind],
747
+ resolved_data[sample_ind],
748
+ )
749
+
750
+ groups = [f"[Scenario] {source['group']}"] + process_query_info(
751
+ resolved["query_info"]
752
+ )
753
+
754
+ st.write("")
755
+ group = st.selectbox(
756
+ "**Scenario & Potential Query-Specific Cases:**\n\nWe set the scenario of this sample by default, but you can also select certain query-specfic groups if the query satisfy certain conditions.",
757
+ options=groups,
758
+ )
759
+ model_name = st.selectbox(
760
+ "**The Preference of which LLM (Human):**",
761
+ options=list(all_models_fitted_params[group].keys()),
762
+ )
763
+ paras_spec = all_models_fitted_params[group][model_name]
764
+ model = BayesianLogisticRegression(paras_spec)
765
+ explainer = shap.Explainer(model=model.return_prob, masker=np.zeros((1, 29)))
766
+
767
+ # Calculate SHAP values
768
+ shap_values = explainer(
769
+ features[st.session_state.sample_ind: st.session_state.sample_ind + 1, :]
770
+ )
771
+ shap_values.feature_names = list(feature_name_to_id_short.keys())
772
+
773
+ # Plotting
774
+
775
+ st.markdown(
776
+ "> *f(x) > 0.5 means response A is preferred more, and vice versa.*"
777
+ )
778
+ st.markdown(
779
+ "> *Property = 1 means response A satisfy the property better than B, and vice versa. We only show the properties that distinguish A and B.*"
780
+ )
781
+
782
+ # count how mant nonzero in shape_values[0].data
783
+ nonzero = np.nonzero(shap_values[0].data)[0].shape[0]
784
+ shap.plots.waterfall(shap_values[0], max_display=nonzero + 1, show=False)
785
+ fig = plt.gcf()
786
+ st.pyplot(fig)
787
+
788
+ # st.subheader(
789
+ # "**Detailed information (source data and annotation) of this sample.**"
790
+ # )
791
+
792
+ # We pop some attributes first
793
+
794
+ # RAW Json
795
+ simplified_source = {
796
+ "query": source["prompt"],
797
+ f"response A ({source['model_a']}, {source['response_a word']} words)": source[
798
+ "response_a"
799
+ ],
800
+ f"response B ({source['model_b']}, {source['response_b word']} words)": source[
801
+ "response_b"
802
+ ],
803
+ "GPT-4-Turbo Reference": reference["output"],
804
+ }
805
+ simplified_resolved = {
806
+ "query-specific:": resolved["query_info"],
807
+ "Annotation": {
808
+ k: v["meta"]
809
+ for k, v in resolved["comparison"].items()
810
+ if v["meta"] is not None and k != "length"
811
+ },
812
+ }
813
+
814
+ # Source Data Rendering
815
+ # st.json(simplified_source)
816
+ st.write("#### Source Data")
817
+ st.text_area(
818
+ "**Query**:\n",
819
+ f"""{source["prompt"]}\n""",
820
+ )
821
+ st.text_area(
822
+ f"**response A ({source['model_a']}, {source['response_a word']} words)**:\n",
823
+ f"""{source["response_a"]}\n""",
824
+ height=200,
825
+ )
826
+ st.text_area(
827
+ f"**response B ({source['model_b']}, {source['response_b word']} words)**:\n",
828
+ f"""{source["response_b"]}\n""",
829
+ height=200,
830
+ )
831
+ st.text_area(
832
+ f"**GPT-4-Turbo Reference**:\n",
833
+ f"""{reference["output"]}\n""",
834
+ height=200,
835
+ )
836
+
837
+ # Resolved Data Rendering
838
+ st.markdown("---")
839
+ st.write("### Annotation")
840
+ # st.json(simplified_resolved)
841
+ st.write("#### Query Information\n")
842
+ query_info = json_to_markdown_bold_keys(simplified_resolved["query-specific:"])
843
+ st.markdown(custom_md_with_color(query_info, "DFEFDB"), unsafe_allow_html=True)
844
+
845
+ specific_check_feature_fixed = [
846
+ "length",
847
+ "accuracy",
848
+ ]
849
+ specific_check_feature_dynamic = [
850
+ "clarify user intent",
851
+ "showing empathetic",
852
+ "satisfying explicit constraints",
853
+ "supporting explicit subjective stances",
854
+ "correcting explicit mistakes or biases"
855
+ ]
856
+ specific_check_feature = specific_check_feature_fixed + specific_check_feature_dynamic
857
+ normal_check_feature = {
858
+ k: v["meta"]
859
+ for k, v in resolved["comparison"].items()
860
+ if v["meta"] is not None and k not in specific_check_feature
861
+ }
862
+ # generate table for normal check feature
863
+ data = {"Category": [], "Response 1": [], "Response 2": []}
864
+
865
+ for category, responses in normal_check_feature.items():
866
+ # print(responses)
867
+ data["Category"].append(category)
868
+ data["Response 1"].append(responses["Response 1"])
869
+ data["Response 2"].append(responses["Response 2"])
870
+
871
+ df = pd.DataFrame(data)
872
+
873
+ # Display the table in Streamlit
874
+ st.write("#### Ratings of Basic Properties\n")
875
+ st.table(df)
876
+
877
+ # specific check features: 'accuracy', and 'satisfying explicit constraints'
878
+ st.write("#### Error Detection")
879
+
880
+ # xx
881
+ acc1 = simplified_resolved["Annotation"]["accuracy"]["Response 1"]
882
+ newacc1 = {"applicable to detect errors": acc1["accuracy check"],
883
+ "detected errors": acc1["inaccuracies"]}
884
+ acc2 = simplified_resolved["Annotation"]["accuracy"]["Response 2"]
885
+ newacc2 = {"applicable to detect errors": acc2["accuracy check"],
886
+ "detected errors": acc2["inaccuracies"]}
887
+
888
+ # Convert the JSON to a Markdown string
889
+ response_1 = json_to_markdown_bold_keys(newacc1)
890
+ response_2 = json_to_markdown_bold_keys(newacc2)
891
+ st.markdown("##### Response 1")
892
+ st.markdown(custom_md_with_color(response_1, "DBE7EF"), unsafe_allow_html=True)
893
+ st.text("")
894
+ st.markdown("##### Response 2")
895
+ st.markdown(custom_md_with_color(response_2, "DBE7EF"), unsafe_allow_html=True)
896
+
897
+ if any(j in simplified_resolved['Annotation'] for j in specific_check_feature_dynamic):
898
+ st.text("")
899
+ st.markdown("#### Query-Specific Annotation")
900
+
901
+ for j in specific_check_feature_dynamic:
902
+ if j in simplified_resolved['Annotation']:
903
+ st.write(f"**{j} (ratings from 0-3 or specific labels)**")
904
+ st.markdown(custom_md_with_color(json_to_markdown_bold_keys(simplified_resolved['Annotation'][j]),
905
+ "E8DAEF"), unsafe_allow_html=True)
906
+ st.text("")
907
+ else:
908
+ resolved_data = read_all("./data/chatbot_arena_no-tie_group_balanced_resolved.jsonl")
909
+ query_aware_idxs = read_all("./data/query_aware_idxs.json")
910
+
911
+ st.write("Upload the preference labels from a new LLM.")
912
+ st.write("The data in ths .json file should be a list with 5240 (the same as the data size) elements, each belongs to {\"A\",\"B\"} indicating the preferred one in each pair.")
913
+ st.write("We provide an example in ```./data/example_preference_labels.json``` in the ``Files`` of the space, which are the preference labels of human.")
914
+ filename = st.file_uploader("", type=["json"],
915
+ key="new_model_fitted_params")
916
+
917
+ one_model_fitted_params = None
918
+
919
+ if filename is not None:
920
+ st.write("Uploaded successfully.")
921
+
922
+ st.write("Please select the number of folds for fitting the models. 1 means no multi-fold averaging. (Warning! Large number of fold may cause OOM and the crush of this space.)")
923
+ num_fold = st.selectbox("Number of Folds", [1, 2, 5, 10], index=0)
924
+
925
+ one_model_fitted_params = compute_one_model_fitted_params(filename, num_fold, query_aware_idxs,
926
+ resolved_data)
927
+
928
+ if one_model_fitted_params is not None:
929
+ json_data = json.dumps(one_model_fitted_params, indent=4)
930
+ st.markdown(get_json_download_link(json_data, "fitted_weights.json", "Download Fitted Bayesian Logistic Models Weights"), unsafe_allow_html=True)
931
+
932
+ st.write("The visualization is the same as the first section.")
933
+
934
+ selected_part = st.selectbox("**Scenario/Query-Specific Cases**", list(one_model_fitted_params.keys()))
935
+ weights = one_model_fitted_params[selected_part]
936
+ show_one_model_prob(weights, feature_names_short)
data/chatbot_arena_no-tie_group_balanced_resolved.jsonl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:900ff866a2fe871229c9ecfd4f22a0e35d8429c9259a44229ea6b23041c38ef9
3
+ size 22779809
data/chatbot_arena_shuffled_no-tie_gpt4_ref_group_balanced.jsonl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cee6231c3fa11a16f100ae6ad2047ca7531273bc881771624146b06e23617ea7
3
+ size 9939477
data/chatbot_arena_shuffled_no-tie_group_balanced.jsonl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e648ac4afd08e335e3809a1c457f1d0036194d804d2b27c1955b2a600b9994c4
3
+ size 16107771
data/example_preference_labels.json ADDED
@@ -0,0 +1 @@
 
 
1
+ ["B", "B", "B", "B", "B", "B", "B", "B", "B", "A", "B", "A", "B", "B", "A", "A", "A", "B", "B", "B", "A", "A", "A", "B", "B", "A", "B", "B", "B", "B", "A", "A", "B", "A", "B", "B", "A", "A", "B", "A", "A", "A", "A", "B", "A", "B", "B", "A", "B", "B", "B", "B", "A", "B", "A", "A", "A", "B", "A", "A", "A", "B", "B", "A", "A", "B", "B", "B", "B", "A", "B", "A", "A", "B", "B", "B", "B", "A", "A", "B", "B", "B", "A", "B", "B", "A", "B", "A", "A", "B", "A", "A", "B", "A", "B", "B", "A", "B", "B", "B", "A", "A", "A", "B", "B", "B", "A", "A", "A", "B", "A", "B", "B", "A", "B", "B", "B", "A", "A", "A", "A", "A", "B", "B", "A", "A", "A", "A", "A", "B", "B", "A", "B", "A", "B", "A", "B", "B", "B", "B", "B", "A", "A", "A", "B", "B", "A", "B", "A", "B", "A", "A", "A", "B", "A", "A", "B", "B", "A", "B", "A", "B", "B", "A", "A", "A", "A", "A", "B", "A", "A", "B", "B", "B", "B", "B", "A", "A", "B", "A", "B", "B", "B", "A", "A", "B", "A", "B", "B", "B", "B", "B", "B", "B", "A", "A", "B", "A", "A", "B", "B", "A", "A", "B", "A", "B", "B", "B", "A", "B", "B", "A", "A", "B", "B", "A", "A", "A", "B", "B", "A", "A", "A", "A", "B", "A", "A", "A", "A", "B", "A", "B", "A", "B", "B", "A", "B", "A", "B", "A", "B", "A", "A", "A", "A", "B", "B", "A", "B", "B", "B", "B", "B", "A", "B", "A", "B", "A", "A", "B", "B", "A", "B", "B", "B", "A", "B", "A", "B", "A", "A", "A", "A", "A", "B", "A", "B", "A", "B", "B", "A", "B", "A", "B", "A", "A", "B", "B", "B", "A", "B", "A", "A", "B", "B", "A", "B", "B", "A", "B", "A", "B", "B", "A", "A", "A", "B", "A", "B", "A", "A", "B", "B", "A", "A", "A", "A", "B", "B", "B", "B", "B", "B", "A", "B", "B", "B", "B", "B", "A", "B", "B", "B", "A", "A", "B", "A", "A", "A", "B", "A", "B", "A", "B", "B", "A", "B", "B", "B", "B", "A", "B", "B", "B", "B", "A", "A", "B", "A", "B", "B", "B", "A", "B", "B", "A", "A", "B", "A", "B", "B", "B", "B", "B", "B", "B", "A", "A", "B", "A", "B", "B", "B", "A", "B", "A", "A", "B", "A", "A", "A", "A", "B", "A", "B", "B", "B", "B", "A", "B", "A", "A", "A", "A", "B", "B", "B", "A", "B", "B", "A", "B", "B", "B", "A", "A", "A", "B", "A", "A", "A", "B", "B", "B", "A", "A", "B", "B", "B", "B", "B", "A", "A", "B", "A", "A", "B", "A", "A", "A", "A", "B", "B", "A", "B", "B", "A", "A", "A", "A", "B", "A", "A", "B", "A", "B", "B", "A", "A", "A", "A", "B", "A", "A", "B", "A", "B", "B", "A", "A", "A", "B", "B", "A", "B", "B", "A", "A", "B", "A", "B", "B", "A", "A", "B", "A", "A", "B", "B", "A", "B", "A", "A", "A", "B", "A", "B", "B", "B", "A", "B", "B", "A", "B", "B", "A", "B", "A", "A", "A", "B", "B", "B", "A", "B", "B", "B", "A", "B", "B", "B", "B", "A", "A", "B", "B", "A", "A", "A", "B", "A", "B", "A", "A", "A", "B", "B", "B", "B", "B", "B", "A", "B", "A", "B", "A", "A", "B", "A", "B", "A", "B", "B", "B", "B", "B", "A", "A", "A", "A", "A", "B", "A", "A", "B", "A", "A", "A", "B", "A", "A", "A", "A", "B", "A", "B", "B", "B", "A", "A", "B", "B", "B", "A", "B", "B", "B", "B", "B", "B", "B", "A", "A", "A", "A", "A", "A", "B", "A", "A", "B", "B", "A", "B", "A", "B", "B", "B", "B", "A", "B", "A", "A", "A", "A", "A", "B", "A", "A", "B", "B", "A", "A", "A", "B", "A", "A", "B", "A", "A", "B", "A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "A", "B", "B", "A", "B", "B", "B", "B", "A", "B", "B", "A", "A", "B", "B", "A", "A", "A", "B", "A", "B", "A", "A", "A", "A", "A", "B", "B", "B", "A", "A", "A", "A", "B", "B", "A", "B", "B", "B", "A", "B", "A", "A", "B", "B", "B", "A", "B", "A", "B", "B", "A", "A", "A", "A", "B", "B", "B", "A", "A", "B", "A", "B", "B", "A", "A", "B", "B", "B", "B", "A", "B", "A", "B", "A", "B", "B", "B", "B", "A", "A", "B", "B", "A", "B", "A", "B", "A", "B", "B", "B", "A", "B", "A", "B", "B", "A", "B", "A", "B", "B", "A", "B", "A", "A", "A", "A", "B", "A", "B", "B", "A", "B", "B", "B", "A", "A", "B", "B", "A", "A", "B", "A", "A", "B", "B", "A", "B", "B", "B", "B", "B", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "A", "B", "B", "A", "B", "A", "A", "A", "B", "B", "A", "B", "B", "B", "A", "A", "B", "A", "A", "A", "B", "A", "B", "A", "B", "A", "B", "B", "B", "B", "A", "A", "A", "B", "B", "B", "B", "A", "B", "A", "B", "A", "A", "B", "B", "B", "B", "A", "A", "B", "B", "A", "A", "A", "B", "B", "A", "A", "B", "B", "B", "B", "A", "B", "B", "A", "A", "A", "A", "B", "B", "A", "B", "B", "A", "A", "B", "B", "B", "A", "B", "A", "A", "A", "A", "B", "B", "A", "B", "B", "B", "A", "B", "A", "B", "A", "A", "A", "A", "A", "A", "B", "A", "A", "A", "B", "B", "B", "A", "A", "B", "A", "A", "A", "A", "A", "B", "A", "B", "A", "B", "B", "B", "B", "A", "B", "B", "A", "A", "B", "A", "B", "B", "A", "B", "A", "A", "B", "A", "A", "A", "B", "A", "A", "B", "A", "B", "A", "B", "B", "B", "B", "B", "A", "A", "A", "B", "A", "B", "B", "B", "B", "B", "B", "A", "B", "B", "A", "A", "B", "A", "B", "A", "A", "A", "B", "A", "A", "A", "A", "B", "B", "A", "A", "B", "A", "A", "B", "B", "A", "B", "B", "A", "B", "A", "A", "A", "A", "A", "B", "B", "B", "A", "A", "B", "B", "B", "A", "B", "A", "A", "A", "B", "A", "B", "B", "B", "A", "A", "A", "A", "B", "A", "B", "B", "A", "A", "B", "A", "A", "A", "B", "A", "B", "A", "B", "B", "A", "A", "A", "A", "B", "A", "A", "B", "B", "A", "A", "A", "A", "A", "A", "A", "B", "A", "B", "B", "B", "B", "A", "A", "A", "B", "B", "B", "B", "A", "B", "B", "B", "A", "B", "B", "B", "A", "A", "A", "A", "B", "A", "A", "B", "A", "A", "B", "B", "B", "A", "B", "B", "B", "A", "B", "B", "B", "A", "B", "B", "A", "B", "A", "B", "A", "B", "A", "B", "B", "A", "B", "B", "A", "A", "A", "A", "A", "A", "A", "A", "B", "B", "A", "A", "A", "B", "B", "A", "A", "B", "A", "B", "A", "A", "B", "B", "A", "B", "A", "B", "A", "B", "B", "B", "B", "B", "B", "B", "A", "A", "A", "B", "B", "B", "A", "A", "B", "A", "B", "A", "A", "A", "B", "B", "B", "A", "B", "A", "B", "A", "B", "B", "B", "B", "B", "B", "B", "A", "A", "B", "A", "B", "B", "B", "B", "A", "A", "B", "B", "A", "B", "B", "B", "B", "A", "A", "B", "B", "A", "B", "A", "A", "B", "B", "A", "B", "B", "A", "B", "B", "A", "A", "B", "A", "A", "A", "B", "B", "A", "B", "B", "A", "A", "B", "A", "A", "A", "A", "A", "B", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "A", "A", "A", "A", "B", "A", "A", "A", "B", "A", "B", "A", "B", "B", "B", "A", "B", "A", "A", "B", "B", "B", "A", "A", "B", "B", "A", "B", "B", "A", "A", "A", "B", "A", "A", "A", "B", "B", "B", "A", "B", "A", "B", "B", "A", "A", "A", "B", "A", "B", "A", "B", "A", "B", "A", "A", "A", "A", "B", "A", "A", "B", "A", "B", "A", "A", "B", "B", "A", "A", "A", "A", "A", "A", "B", "A", "A", "A", "A", "A", "B", "B", "B", "A", "B", "B", "A", "B", "B", "B", "B", "B", "B", "B", "B", "B", "A", "B", "B", "A", "B", "B", "B", "B", "B", "A", "B", "A", "A", "B", "B", "B", "B", "B", "A", "A", "B", "B", "B", "B", "A", "B", "A", "A", "A", "B", "B", "B", "A", "B", "B", "A", "A", "A", "B", "A", "A", "B", "A", "A", "B", "B", "A", "B", "A", "A", "A", "B", "A", "A", "A", "B", "A", "A", "A", "B", "A", "A", "B", "A", "B", "B", "A", "B", "B", "A", "B", "A", "B", "B", "B", "A", "B", "A", "B", "A", "A", "A", "A", "A", "B", "A", "B", "A", "A", "B", "B", "B", "A", "B", "B", "B", "A", "B", "A", "A", "B", "A", "A", "B", "B", "A", "B", "B", "B", "B", "B", "B", "A", "A", "B", "A", "B", "A", "A", "A", "A", "A", "B", "A", "B", "B", "A", "B", "A", "B", "A", "B", "A", "A", "B", "B", "B", "A", "B", "B", "B", "A", "A", "B", "A", "A", "A", "A", "B", "B", "B", "A", "B", "B", "A", "A", "A", "A", "A", "B", "A", "A", "A", "A", "B", "A", "A", "B", "B", "A", "A", "A", "A", "A", "B", "A", "A", "A", "B", "A", "B", "A", "B", "B", "A", "A", "A", "B", "B", "A", "A", "B", "B", "A", "A", "A", "B", "A", "B", "A", "A", "B", "B", "B", "B", "A", "A", "A", "B", "B", "B", "A", "A", "A", "B", "A", "A", "A", "A", "A", "B", "B", "A", "B", "A", "B", "A", "A", "B", "A", "A", "B", "B", "B", "A", "A", "B", "B", "A", "A", "B", "B", "A", "B", "A", "A", "B", "A", "B", "B", "B", "A", "B", "A", "B", "A", "B", "A", "A", "A", "B", "A", "A", "B", "B", "A", "A", "A", "A", "A", "B", "A", "B", "B", "B", "A", "A", "B", "A", "B", "A", "A", "A", "B", "B", "A", "B", "A", "A", "B", "A", "A", "A", "A", "B", "B", "B", "A", "B", "A", "B", "A", "B", "B", "B", "A", "A", "B", "B", "A", "A", "A", "B", "A", "B", "A", "B", "B", "A", "B", "A", "A", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "A", "B", "A", "B", "A", "B", "A", "A", "A", "B", "A", "B", "B", "B", "A", "A", "A", "B", "B", "A", "A", "B", "A", "B", "A", "A", "B", "B", "A", "A", "A", "B", "B", "A", "B", "B", "B", "B", "B", "A", "A", "B", "B", "A", "A", "B", "B", "A", "A", "A", "A", "B", "B", "A", "A", "B", "A", "A", "A", "A", "B", "A", "B", "A", "B", "A", "A", "A", "B", "B", "A", "B", "B", "B", "B", "A", "A", "B", "B", "A", "A", "B", "B", "B", "B", "A", "B", "A", "A", "A", "A", "A", "A", "B", "A", "A", "B", "B", "B", "A", "A", "B", "A", "B", "A", "B", "B", "B", "A", "A", "A", "A", "B", "B", "B", "B", "A", "A", "A", "A", "B", "B", "A", "A", "A", "B", "B", "B", "B", "A", "B", "A", "A", "B", "B", "B", "A", "A", "B", "B", "A", "B", "B", "A", "A", "A", "B", "A", "A", "A", "B", "B", "A", "B", "A", "A", "A", "A", "B", "B", "A", "A", "B", "A", "B", "B", "A", "B", "A", "B", "A", "B", "B", "B", "A", "B", "A", "A", "B", "A", "B", "A", "B", "A", "B", "B", "B", "A", "B", "A", "A", "A", "A", "A", "B", "A", "B", "A", "A", "A", "A", "A", "B", "B", "A", "B", "B", "A", "B", "A", "B", "A", "B", "B", "B", "A", "B", "A", "B", "A", "B", "B", "A", "B", "A", "B", "B", "A", "A", "B", "A", "A", "B", "A", "B", "B", "B", "B", "A", "A", "B", "B", "A", "B", "A", "A", "A", "A", "B", "B", "B", "A", "A", "B", "B", "A", "B", "B", "B", "A", "B", "B", "B", "A", "B", "A", "B", "B", "B", "A", "A", "A", "B", "B", "A", "A", "A", "A", "A", "A", "A", "A", "A", "B", "B", "B", "A", "A", "B", "A", "A", "A", "B", "B", "A", "A", "A", "A", "A", "A", "A", "A", "B", "A", "A", "A", "B", "A", "A", "B", "A", "A", "A", "B", "B", "B", "B", "B", "A", "A", "A", "B", "A", "A", "A", "B", "A", "A", "B", "B", "A", "A", "B", "A", "B", "B", "B", "A", "A", "B", "B", "A", "A", "B", "A", "B", "B", "B", "B", "A", "B", "B", "B", "A", "A", "A", "A", "A", "A", "A", "A", "B", "B", "B", "A", "B", "B", "A", "B", "A", "B", "B", "B", "B", "A", "B", "B", "B", "A", "B", "B", "A", "B", "A", "B", "B", "B", "B", "A", "A", "A", "A", "A", "B", "B", "A", "B", "A", "A", "B", "A", "A", "A", "A", "B", "A", "A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "A", "A", "B", "A", "B", "B", "A", "A", "B", "B", "B", "A", "A", "A", "B", "A", "A", "B", "B", "A", "B", "A", "B", "B", "B", "B", "B", "B", "B", "A", "A", "B", "A", "A", "B", "B", "A", "B", "A", "A", "B", "B", "A", "A", "B", "A", "B", "B", "A", "B", "B", "A", "A", "A", "B", "B", "B", "A", "B", "B", "A", "A", "B", "B", "A", "A", "B", "B", "B", "B", "B", "B", "A", "B", "B", "B", "B", "B", "A", "B", "A", "A", "A", "A", "A", "B", "A", "B", "B", "A", "A", "B", "A", "B", "A", "A", "B", "A", "A", "A", "A", "B", "B", "B", "A", "B", "A", "A", "A", "A", "A", "A", "A", "A", "B", "B", "A", "A", "B", "A", "B", "B", "B", "A", "A", "A", "B", "A", "A", "B", "B", "B", "A", "B", "B", "B", "A", "B", "A", "A", "B", "A", "A", "A", "B", "B", "B", "B", "A", "B", "B", "A", "B", "A", "B", "B", "B", "A", "A", "B", "B", "B", "B", "B", "B", "B", "B", "A", "B", "B", "A", "A", "A", "B", "B", "B", "A", "B", "A", "A", "A", "B", "A", "A", "B", "A", "A", "A", "B", "B", "A", "B", "A", "B", "B", "A", "A", "A", "B", "B", "B", "A", "B", "B", "A", "B", "A", "A", "A", "A", "B", "A", "A", "B", "B", "A", "B", "B", "A", "B", "B", "B", "B", "A", "A", "B", "A", "B", "B", "A", "A", "B", "B", "A", "A", "B", "A", "B", "B", "A", "B", "A", "A", "A", "A", "B", "B", "A", "B", "B", "A", "A", "B", "B", "B", "B", "B", "A", "B", "A", "A", "A", "A", "B", "A", "B", "B", "A", "A", "A", "B", "B", "A", "B", "A", "B", "A", "A", "B", "B", "A", "B", "B", "B", "A", "A", "A", "A", "A", "B", "A", "A", "B", "A", "A", "B", "B", "A", "A", "B", "A", "B", "B", "A", "B", "A", "A", "A", "B", "B", "B", "B", "B", "B", "A", "A", "B", "A", "A", "A", "B", "A", "A", "A", "B", "A", "A", "B", "B", "A", "B", "B", "B", "A", "B", "B", "A", "B", "B", "A", "B", "A", "A", "A", "B", "B", "A", "A", "B", "B", "A", "A", "A", "A", "B", "A", "B", "A", "B", "A", "B", "B", "B", "A", "B", "B", "A", "B", "B", "B", "B", "B", "B", "B", "B", "A", "B", "A", "A", "B", "B", "A", "B", "B", "A", "B", "B", "B", "B", "B", "A", "A", "B", "B", "B", "A", "B", "A", "A", "B", "B", "B", "B", "A", "B", "B", "B", "A", "B", "B", "B", "A", "A", "A", "A", "A", "B", "A", "A", "A", "A", "A", "A", "B", "B", "A", "A", "B", "B", "B", "B", "A", "A", "B", "A", "A", "B", "B", "B", "B", "A", "A", "B", "A", "B", "B", "B", "B", "B", "A", "B", "A", "B", "A", "B", "B", "B", "A", "B", "B", "B", "B", "A", "A", "B", "B", "A", "B", "B", "A", "A", "A", "B", "B", "B", "B", "B", "A", "A", "A", "A", "B", "B", "A", "B", "B", "B", "A", "B", "B", "A", "B", "B", "A", "B", "A", "A", "A", "B", "B", "A", "A", "B", "B", "A", "A", "A", "A", "A", "A", "A", "A", "B", "B", "B", "A", "B", "A", "B", "A", "A", "B", "A", "A", "A", "A", "A", "B", "B", "B", "B", "A", "B", "A", "A", "B", "A", "A", "B", "B", "B", "A", "A", "A", "B", "A", "B", "A", "A", "B", "B", "B", "B", "A", "A", "A", "B", "A", "A", "B", "B", "A", "B", "B", "B", "B", "B", "A", "A", "A", "B", "A", "B", "B", "B", "B", "A", "A", "A", "B", "A", "B", "B", "A", "B", "B", "A", "A", "A", "A", "B", "B", "A", "B", "A", "A", "B", "B", "B", "A", "A", "B", "A", "B", "A", "B", "A", "B", "A", "B", "A", "A", "A", "A", "B", "B", "B", "B", "A", "A", "B", "B", "B", "B", "A", "B", "A", "B", "A", "A", "B", "A", "A", "A", "B", "B", "B", "B", "B", "A", "B", "A", "A", "A", "B", "B", "B", "A", "B", "B", "A", "A", "A", "B", "B", "A", "A", "B", "B", "B", "B", "A", "B", "A", "B", "B", "A", "B", "B", "B", "A", "A", "B", "A", "A", "A", "A", "B", "B", "B", "B", "B", "A", "B", "B", "B", "B", "A", "B", "B", "A", "B", "A", "B", "A", "B", "A", "B", "B", "A", "B", "A", "A", "A", "A", "B", "A", "B", "A", "A", "A", "A", "A", "A", "A", "B", "A", "A", "B", "A", "A", "B", "B", "A", "B", "A", "B", "B", "A", "B", "A", "B", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "A", "A", "B", "A", "A", "B", "B", "A", "B", "A", "A", "A", "A", "A", "A", "A", "A", "B", "B", "A", "B", "B", "A", "B", "A", "B", "B", "B", "B", "A", "A", "B", "A", "B", "A", "A", "A", "A", "B", "B", "A", "A", "B", "B", "A", "A", "B", "B", "B", "B", "A", "A", "A", "A", "B", "A", "A", "A", "B", "B", "B", "B", "A", "B", "B", "B", "A", "A", "A", "B", "B", "A", "B", "A", "B", "B", "B", "A", "B", "B", "A", "A", "A", "B", "B", "A", "A", "B", "A", "B", "A", "A", "A", "B", "B", "B", "B", "B", "A", "A", "B", "B", "B", "A", "A", "B", "A", "A", "B", "B", "B", "A", "A", "A", "B", "A", "B", "A", "A", "B", "B", "B", "A", "B", "B", "B", "A", "A", "B", "A", "A", "A", "B", "A", "B", "A", "B", "A", "A", "A", "B", "B", "A", "A", "B", "A", "B", "B", "A", "B", "A", "B", "A", "A", "A", "B", "A", "A", "B", "A", "A", "B", "B", "B", "A", "B", "A", "A", "B", "A", "A", "B", "B", "A", "A", "A", "A", "B", "B", "A", "B", "A", "A", "B", "A", "B", "B", "A", "A", "B", "A", "A", "A", "A", "A", "B", "A", "B", "B", "A", "B", "A", "A", "A", "B", "A", "B", "B", "A", "A", "A", "A", "B", "A", "B", "B", "B", "A", "B", "A", "B", "A", "B", "A", "A", "B", "B", "B", "B", "A", "B", "A", "A", "A", "B", "A", "A", "A", "A", "B", "B", "B", "B", "A", "A", "B", "A", "B", "B", "B", "A", "A", "B", "A", "B", "B", "A", "A", "A", "A", "A", "B", "A", "A", "A", "B", "A", "B", "B", "B", "A", "A", "A", "A", "A", "B", "B", "B", "A", "A", "A", "B", "B", "A", "A", "A", "A", "A", "B", "A", "B", "B", "B", "A", "B", "B", "B", "B", "B", "A", "B", "A", "B", "B", "B", "A", "A", "B", "B", "A", "B", "A", "A", "A", "B", "A", "A", "B", "B", "B", "A", "B", "B", "A", "B", "A", "A", "B", "B", "A", "B", "B", "B", "A", "B", "A", "A", "B", "A", "A", "B", "A", "B", "B", "B", "B", "B", "A", "B", "A", "A", "B", "A", "B", "A", "B", "B", "B", "A", "B", "A", "B", "A", "A", "A", "A", "B", "A", "B", "A", "B", "B", "B", "A", "A", "A", "B", "A", "B", "A", "B", "B", "A", "B", "B", "A", "A", "B", "A", "B", "A", "B", "B", "A", "A", "B", "A", "A", "B", "B", "A", "B", "A", "A", "A", "B", "A", "B", "B", "B", "B", "B", "B", "B", "B", "A", "A", "A", "A", "B", "A", "B", "B", "A", "B", "A", "A", "A", "A", "B", "A", "A", "A", "B", "A", "B", "A", "B", "A", "B", "A", "B", "B", "A", "A", "B", "B", "A", "B", "A", "B", "B", "A", "A", "B", "A", "B", "A", "A", "B", "A", "B", "A", "B", "B", "A", "A", "B", "A", "A", "B", "B", "B", "A", "B", "B", "A", "B", "B", "A", "B", "B", "A", "B", "A", "A", "B", "A", "A", "B", "B", "A", "B", "A", "A", "B", "B", "A", "A", "A", "B", "A", "A", "B", "A", "B", "B", "A", "A", "A", "A", "B", "A", "A", "A", "B", "A", "A", "B", "B", "A", "B", "B", "A", "B", "A", "B", "B", "A", "A", "A", "A", "A", "A", "B", "B", "B", "A", "B", "B", "A", "B", "B", "A", "A", "A", "A", "A", "B", "B", "A", "B", "A", "B", "A", "B", "A", "A", "A", "A", "B", "B", "B", "B", "A", "A", "A", "A", "A", "B", "B", "B", "B", "A", "A", "B", "B", "A", "A", "B", "A", "B", "B", "B", "A", "A", "A", "B", "A", "A", "A", "A", "A", "B", "B", "A", "B", "B", "A", "A", "A", "A", "B", "A", "A", "A", "B", "B", "B", "A", "B", "B", "B", "A", "B", "B", "A", "B", "A", "A", "B", "B", "A", "B", "A", "B", "A", "B", "B", "A", "B", "A", "A", "B", "A", "A", "A", "A", "A", "B", "B", "B", "A", "B", "A", "B", "B", "B", "A", "A", "A", "A", "A", "A", "A", "A", "B", "B", "B", "A", "A", "B", "A", "B", "A", "A", "A", "B", "B", "B", "A", "B", "B", "A", "A", "B", "B", "A", "B", "B", "B", "A", "B", "A", "A", "B", "B", "B", "A", "A", "A", "B", "A", "B", "A", "A", "B", "A", "A", "A", "B", "B", "A", "A", "B", "A", "B", "A", "B", "B", "B", "B", "B", "A", "A", "A", "B", "B", "A", "B", "A", "A", "A", "B", "B", "B", "A", "B", "B", "A", "A", "A", "B", "A", "A", "A", "A", "A", "A", "B", "B", "A", "B", "B", "A", "A", "B", "A", "B", "B", "B", "A", "B", "B", "A", "B", "A", "B", "A", "A", "A", "B", "A", "B", "A", "A", "B", "A", "B", "A", "A", "B", "A", "B", "A", "A", "B", "B", "A", "B", "B", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "A", "B", "B", "A", "B", "B", "A", "B", "A", "B", "A", "B", "A", "A", "B", "A", "A", "A", "A", "A", "B", "A", "B", "B", "A", "B", "B", "B", "A", "A", "B", "A", "B", "B", "B", "A", "A", "A", "B", "B", "A", "B", "A", "B", "B", "B", "A", "B", "A", "A", "A", "A", "B", "B", "B", "A", "A", "A", "A", "B", "B", "B", "A", "B", "B", "A", "B", "B", "B", "A", "A", "B", "B", "A", "A", "B", "A", "B", "B", "A", "B", "A", "B", "B", "A", "A", "B", "A", "B", "B", "A", "B", "A", "A", "B", "B", "A", "B", "B", "B", "B", "B", "B", "A", "A", "B", "B", "A", "B", "B", "B", "A", "A", "B", "B", "B", "B", "A", "A", "B", "B", "A", "B", "A", "B", "A", "B", "A", "B", "A", "B", "A", "A", "A", "A", "A", "A", "A", "B", "A", "B", "B", "B", "B", "B", "A", "B", "B", "B", "B", "A", "A", "B", "A", "A", "A", "B", "B", "A", "A", "B", "B", "A", "B", "A", "A", "A", "A", "A", "A", "B", "A", "A", "B", "B", "A", "A", "A", "B", "A", "B", "B", "A", "B", "B", "B", "A", "B", "B", "B", "A", "B", "B", "B", "B", "B", "B", "B", "B", "B", "A", "B", "A", "A", "A", "B", "B", "A", "B", "B", "B", "B", "B", "B", "B", "A", "B", "A", "A", "B", "A", "A", "B", "A", "B", "B", "A", "A", "B", "B", "A", "B", "A", "B", "B", "A", "B", "B", "A", "A", "B", "B", "A", "A", "B", "B", "B", "B", "B", "A", "B", "A", "B", "B", "A", "B", "A", "B", "B", "B", "B", "B", "A", "A", "A", "A", "B", "B", "B", "B", "A", "A", "A", "A", "A", "A", "B", "B", "A", "A", "B", "A", "B", "A", "B", "B", "B", "B", "A", "A", "B", "B", "B", "A", "B", "A", "A", "A", "A", "B", "B", "A", "A", "B", "B", "B", "A", "B", "B", "B", "B", "B", "B", "A", "A", "B", "B", "B", "B", "A", "A", "B", "A", "B", "A", "A", "B", "A", "B", "B", "A", "A", "A", "A", "A", "B", "A", "A", "A", "B", "A", "B", "A", "B", "B", "B", "B", "B", "A", "B", "B", "A", "A", "A", "A", "B", "A", "A", "B", "A", "A", "A", "A", "B", "A", "A", "B", "B", "A", "A", "B", "A", "B", "A", "B", "A", "A", "A", "B", "B", "B", "B", "A", "A", "A", "B", "B", "B", "A", "B", "B", "B", "B", "A", "B", "A", "B", "B", "A", "A", "A", "A", "A", "B", "A", "A", "A", "B", "A", "A", "A", "B", "B", "B", "A", "A", "B", "A", "B", "B", "A", "A", "B", "A", "A", "A", "A", "B", "A", "B", "A", "A", "A", "B", "B", "B", "A", "B", "B", "A", "A", "B", "A", "B", "B", "A", "A", "A", "B", "A", "A", "A", "B", "A", "A", "B", "B", "A", "B", "A", "B", "B", "A", "B", "B", "A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "A", "A", "B", "A", "B", "A", "B", "A", "A", "A", "A", "B", "A", "B", "B", "B", "B", "B", "B", "B", "B", "A", "A", "B", "A", "A", "A", "A", "B", "A", "A", "B", "A", "B", "A", "A", "B", "A", "B", "A", "B", "A", "A", "A", "A", "B", "B", "B", "B", "A", "A", "A", "B", "A", "B", "B", "B", "A", "B", "B", "A", "B", "B", "B", "A", "A", "A", "A", "A", "A", "A", "B", "A", "B", "B", "B", "B", "A", "B", "A", "A", "A", "B", "A", "B", "B", "B", "B", "A", "A", "B", "B", "A", "A", "B", "B", "A", "A", "B", "B", "A", "B", "A", "A", "A", "A", "B", "A", "B", "B", "A", "A", "B", "B", "B", "A", "B", "A", "A", "B", "B", "B", "A", "A", "B", "A", "B", "B", "B", "B", "B", "A", "B", "A", "A", "A", "B", "B", "A", "B", "B", "B", "B", "B", "A", "B", "B", "A", "A", "A", "A", "B", "B", "B", "A", "B", "A", "B", "B", "B", "B", "A", "A", "A", "A", "B", "B", "B", "A", "B", "A", "A", "B", "B", "B", "B", "B", "A", "A", "B", "A", "A", "B", "B", "A", "A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "A", "A", "A", "B", "B", "B", "A", "A", "A", "B", "A", "A", "A", "B", "B", "B", "B", "A", "A", "A", "B", "B", "A", "A", "A", "A", "A", "B", "A", "B", "B", "A", "A", "B", "B", "A", "B", "B", "B", "A", "B", "A", "B", "A", "A", "B", "A", "B", "B", "B", "A", "A", "B", "A", "A", "B", "A", "A", "A", "A", "B", "B", "A", "A", "B", "A", "A", "B", "B", "A", "B", "B", "A", "B", "A", "B", "A", "B", "B", "B", "A", "A", "B", "B", "A", "B", "B", "A", "B", "A", "B", "B", "A", "B", "A", "A", "B", "B", "A", "B", "B", "B", "B", "B", "B", "B", "B", "A", "A", "B", "A", "A", "B", "B", "B", "A", "A", "A", "B", "B", "B", "A", "B", "B", "B", "A", "B", "A", "B", "B", "A", "B", "A", "A", "B", "B", "B", "A", "A", "B", "B", "B", "B", "B", "A", "B", "A", "A", "B", "B", "A", "A", "B", "A", "B", "A", "A", "A", "B", "A", "A", "B", "A", "B", "B", "A", "A", "B", "B", "A", "B", "A", "A", "B", "A", "B", "B", "B", "A", "B", "B", "B", "B", "B", "A", "B", "B", "B", "A", "B", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "B", "B", "A", "A", "A", "B", "B", "B", "A", "A", "B", "B", "B", "B", "B", "B", "B", "A", "A", "B", "B", "B", "A", "A", "A", "A", "A", "A", "B", "A", "A", "B", "A", "A", "B", "A", "B", "A", "A", "B", "A", "A", "A", "A", "B", "A", "B", "A", "A", "B", "A", "A", "A", "A", "B", "B", "B", "A", "A", "A", "B", "A", "B", "A", "B", "B", "A", "B", "A", "B", "A", "A", "A", "A", "A", "A", "B", "B", "A", "A", "B", "A", "A", "B", "B", "A", "B", "B", "A", "A", "B", "A", "A", "B", "B", "B", "B", "A", "A", "B", "A", "A", "B", "A", "A", "B", "B", "B", "A", "B", "B", "B", "B", "B", "B", "A", "B", "A", "B", "B", "B", "B", "A", "A", "B", "A", "A", "B", "A", "B", "A", "B", "A", "B", "A", "B", "B", "B", "A", "B", "A", "A", "B", "A", "A", "B", "A", "A", "B", "A", "B", "B", "A", "A", "A", "A", "A", "A", "A", "A", "A", "B", "B", "A", "B", "A", "B", "A", "B", "B", "A", "A", "A", "A", "B", "A", "B", "B", "B", "A", "A", "B", "B", "A", "B", "A", "B", "B", "A", "A", "A", "B", "A", "A", "B", "A", "B", "A", "A", "B", "A", "A", "A", "B", "A", "B", "B", "A", "A", "A", "A", "A", "A", "B", "A", "B", "B", "A", "A", "A", "A", "B", "B", "B", "B", "B", "A", "A", "B", "A", "A", "B", "B", "B", "A", "A", "B", "B", "A", "A", "A", "A", "B", "B", "A", "A", "B", "A", "A", "B", "A", "B", "B", "B", "B", "A", "A", "A", "B", "B", "B", "B", "A", "A", "A", "B", "B", "A", "A", "A", "B", "B", "B", "A", "A", "A", "B", "B", "A", "B", "B", "A", "A", "B", "A", "A", "A", "B", "A", "A", "A", "B", "B", "A", "B", "A", "A", "A", "B", "A", "A", "A", "B", "B", "B", "A", "A", "A", "A", "B", "A", "A", "A", "B", "A", "B", "A", "B", "B", "B", "A", "A", "B", "B", "B", "A", "B", "A", "B", "B", "B", "B", "A", "B", "A", "B", "A", "A", "A", "B", "A", "A", "A", "B", "B", "B", "A", "B", "A", "B", "A", "B", "A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "A", "A", "B", "B", "A", "B", "A", "B", "B", "A", "A", "B", "B", "B", "B", "B", "B", "A", "A", "B", "A", "A", "B", "A", "A", "B", "A", "B", "B", "A", "B", "A", "B", "B", "B", "A", "A", "A", "B", "A", "B", "B", "B", "A", "A", "A", "A", "A", "A", "B", "A", "B", "B", "B", "A", "B", "B", "A", "B", "A", "A", "A", "A", "A", "B", "B", "A", "B", "A", "A", "A", "B", "A", "B", "A", "A", "B", "A", "B", "A", "A", "A", "A", "A", "B", "B", "A", "A", "B", "A", "A", "A", "B", "B", "B", "B", "A", "A", "A", "A", "A", "A", "A", "B", "B", "A", "B", "B", "B", "B", "B", "A", "B", "B", "B", "B", "B", "B", "B", "A", "B", "A", "B", "A", "B", "B", "A", "B", "B", "B", "B", "B", "B", "A", "A", "A", "A", "B", "A", "B", "B", "A", "B", "B", "B", "A", "A", "B", "A", "B", "A", "B", "A", "A", "A", "B", "A", "A", "A", "A", "B", "B", "B", "B", "A", "B", "A", "A", "B", "A", "B", "B", "B", "A", "B", "B", "B", "A", "A", "A", "B", "B", "B", "B", "B", "B", "A", "B", "A", "A", "A", "A", "B", "A", "A", "B", "B", "B", "B", "A", "B", "A", "B", "B", "A", "A", "B", "A", "A", "B", "A", "A", "A", "B", "B", "A", "A", "A", "A", "B", "A", "A", "A", "B", "A", "B", "A", "A", "B", "A", "B", "A", "A", "B", "B", "A", "A", "A", "B", "A", "A", "A", "B", "B", "A", "A", "A", "B", "B", "B", "B", "A", "B", "A", "B", "A", "A", "B", "A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "B", "B", "A", "B", "B", "A", "A", "B", "B", "B", "B", "B", "A", "B", "A", "A", "A", "B", "A", "B", "A", "A", "B", "B", "A", "A", "A", "B", "A", "A", "A", "A", "A", "A", "B", "B", "A", "B", "A", "A", "B", "A", "B", "B", "B", "B", "A", "B", "A", "A", "B", "B", "A", "A", "B", "A", "A", "A", "A", "B", "B", "B", "B", "A", "B", "A", "B", "A", "A", "A", "B", "B", "A", "B", "B", "B", "A", "A", "B", "B", "B", "A", "B", "B", "B", "B", "B", "B", "A", "B", "A", "B", "A", "B", "B", "A", "B", "B", "B", "A", "A", "B", "B", "B", "A", "B", "B", "B", "B", "B", "B", "B", "B", "B", "A", "B", "B", "B", "B", "A", "A", "B", "A", "A", "B", "A", "A", "B", "B", "B", "B", "A", "A", "B", "A"]
data/fitted_paras_comparison/model_Advice_fitted_paras.jsonl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3effb54e3f63a9263908c7f5a14adf67c7fce88ef93e2953006a23c36888a45b
3
+ size 21846
data/fitted_paras_comparison/model_Code_fitted_paras.jsonl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bc811ec615dc4af871b650e0e631ab8e8b4a089b6586e6b711c8312ad7ec69c0
3
+ size 22222
data/fitted_paras_comparison/model_Communication_fitted_paras.jsonl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cf7c6e09f424cfe2435e6c7f157c5d704553d71ceecef94c427ba0bfdbd77de4
3
+ size 22020
data/fitted_paras_comparison/model_Creative Writing_fitted_paras.jsonl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:13d20e33a15727e8d218b73e3b0ea917bff52779e633c6a1eb8f6251206894b7
3
+ size 22030
data/fitted_paras_comparison/model_Daily Tasks_fitted_paras.jsonl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9fd8f1950135a69aa6daef1c81cc669027f25b0942133124ded3e44c2934a1a0
3
+ size 21822
data/fitted_paras_comparison/model_Exam Questions_fitted_paras.jsonl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:74de24910cdbc73a5899ada343d02caad10ff428e5b93b8ab87ad9b2ca068dab
3
+ size 22383
data/fitted_paras_comparison/model_Functional Writing_fitted_paras.jsonl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6728c1a05d2320333f725b0c7a87a4dc620c558deaa9057e95a037d466306124
3
+ size 21964
data/fitted_paras_comparison/model_Knowledge-aware_fitted_paras.jsonl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:77e38137d839aef1856a04a884e7f9f9b77e757efcf140ca3eb1d151ca77f991
3
+ size 21882
data/fitted_paras_comparison/model_NLP Tasks_fitted_paras.jsonl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:95f98402a4a38e4a86155095ccd3eb0a66485ce366927ae88919d190b5511791
3
+ size 22080
data/fitted_paras_comparison/model_Others_fitted_paras.jsonl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:770a3ac58eae03223ef80c01248f85b37cc7fd398b3faf4466dcfab724c24952
3
+ size 21912
data/fitted_paras_comparison/model_Unsafe Queries_fitted_paras.jsonl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ef67c3952fe7ed26adefc2b07ae1b219f66521f5ecb9afd6b9db20a67b159a4b
3
+ size 21848
data/fitted_paras_comparison/model_express_feeling_fitted_paras.jsonl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bbacbdba928857f6d2475b7d06e063efc09cd06faf457ceff83128b3b3eaba62
3
+ size 22024
data/fitted_paras_comparison/model_intent_unclear_fitted_paras.jsonl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:23913c13de19f05c307737938a09b2d0db75bf0fd62f309a9bbd66b0683f3371
3
+ size 21959
data/fitted_paras_comparison/model_w_constraints_fitted_paras.jsonl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:defe14ab0955bfb1677c88f6fa6ec4cf387fa5586f158e9e04a1ae9c00b6f720
3
+ size 21851
data/fitted_paras_comparison/model_w_mistakes_fitted_paras.jsonl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4f9d955a194bbce63a5872126040ff75407cafdf17642895405bd22feab1c73c
3
+ size 21961
data/fitted_paras_comparison/model_w_stances_fitted_paras.jsonl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5923021c3b02fc57d0248ab6c3a78836ea2dc7a690cdba813240a1fd3207f6d5
3
+ size 21802
data/query_aware_idxs.json ADDED
The diff for this file is too large to render. See raw diff
 
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ matplotlib==3.7.2
2
+ numpy==1.26.2
3
+ pandas==2.0.3
4
+ scipy==1.11.1
5
+ seaborn==0.12.2
6
+ shap==0.44.1
7
+ streamlit==1.30.0
8
+ jax==0.4.20
9
+ jaxlib==0.4.20
10
+ numpyro==0.13.2
utils.py ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ import pandas as pd
4
+
5
+
6
+ def print_colored_text(text, color="yellow", end=None):
7
+ colors = {
8
+ "red": "\033[91m",
9
+ "green": "\033[92m",
10
+ "yellow": "\033[93m",
11
+ "blue": "\033[94m",
12
+ "purple": "\033[95m",
13
+ "cyan": "\033[96m",
14
+ "white": "\033[97m",
15
+ "reset": "\033[0m",
16
+ }
17
+
18
+ color_code = colors.get(color.lower(), colors["reset"])
19
+ print(f"{color_code}{text}{colors['reset']}", end=end)
20
+
21
+
22
+ def read_parquet(parquet_file_path):
23
+ data = pd.read_parquet(parquet_file_path)
24
+ data = data.to_dict("records")
25
+ return data
26
+
27
+
28
+ def write_jsonl(data, jsonl_file_path, mode="w"):
29
+ # data is a list, each of the item is json-serilizable
30
+ assert isinstance(data, list)
31
+ if not os.path.exists(os.path.dirname(jsonl_file_path)):
32
+ os.makedirs(os.path.dirname(jsonl_file_path))
33
+ with open(jsonl_file_path, mode) as f:
34
+ for item in data:
35
+ f.write(json.dumps(item) + "\n")
36
+
37
+
38
+ def write_json(data, json_file_path):
39
+ if not os.path.exists(os.path.dirname(json_file_path)):
40
+ os.makedirs(os.path.dirname(json_file_path))
41
+ with open(json_file_path, "w") as f:
42
+ json.dump(data, f)
43
+
44
+
45
+ def read_jsonl(jsonl_file_path):
46
+ s = []
47
+ if not os.path.exists(jsonl_file_path):
48
+ print_colored_text("File not exists: " + jsonl_file_path, "red")
49
+ return s
50
+ with open(jsonl_file_path, "r") as f:
51
+ lines = f.readlines()
52
+ for line in lines:
53
+ linex = line.strip()
54
+ if linex == "":
55
+ continue
56
+ s.append(json.loads(linex))
57
+ return s
58
+
59
+
60
+ def read_json(json_file_path):
61
+ with open(json_file_path, "r") as f:
62
+ data = json.load(f)
63
+ return data
64
+
65
+
66
+ def read_all(file_path):
67
+ if file_path.endswith(".jsonl"):
68
+ return read_jsonl(file_path)
69
+ elif file_path.endswith(".json"):
70
+ return read_json(file_path)
71
+ elif file_path.endswith(".parquet"):
72
+ return read_parquet(file_path)
73
+ elif file_path.endswith(".txt"):
74
+ with open(file_path, "r") as f:
75
+ return [line.strip() for line in f.readlines() if line.strip() != ""]
76
+ else:
77
+ raise ValueError(f"Unrecognized file type: {file_path}")
78
+
79
+
80
+ # Function to convert JSON to Markdown formatted string with bold keys
81
+ def json_to_markdown_bold_keys(json_obj, depth=0):
82
+ markdown_str = ""
83
+ indent = "\t "
84
+ for key, value in json_obj.items():
85
+ if isinstance(value, dict):
86
+ markdown_str += f"**{key}** :\n\n{indent * (depth)}- {json_to_markdown_bold_keys(value, depth + 1)}\n\n"
87
+ elif isinstance(value, list):
88
+ if len(value) > 0:
89
+ markdown_str += (
90
+ f"**{key}** :\n\n "
91
+ + f"\n\n{indent * (depth)}- "
92
+ + f"\n\n{indent * (depth)}- ".join(
93
+ [
94
+ (
95
+ json_to_markdown_bold_keys(item, depth + 1)
96
+ if isinstance(item, dict)
97
+ else f"{indent * (depth + 1)}{item}"
98
+ )
99
+ for item in value
100
+ ]
101
+ )
102
+ + "\n\n"
103
+ )
104
+ else:
105
+ markdown_str += f"**{key}** : None\n\n"
106
+ else:
107
+ if depth == 0:
108
+ markdown_str += f"**{key}** : {value}\n\n"
109
+ else:
110
+ markdown_str += f"{indent * (depth)}- **{key}** : {value}\n\n"
111
+ return markdown_str
112
+
113
+
114
+ def custom_md_with_color(text, color):
115
+ return f"""
116
+ <div style="background-color:#{color};padding:10px;border-radius:5px;">
117
+ <p style="color:black;font-size:16px;">📑\n\n{text}</p>
118
+ </div>"""