tau-eval 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
tau_eval/__init__.py ADDED
@@ -0,0 +1,18 @@
1
+ """Top-level package for tau-eval."""
2
+
3
+ from . import (
4
+ logger,
5
+ models,
6
+ utils,
7
+ )
8
+ from .experiment import Experiment, ExperimentConfig
9
+
10
+
11
+ __all__ = [
12
+ "Experiment",
13
+ "ExperimentConfig",
14
+ "models",
15
+ "utils",
16
+ "logger",
17
+ ]
18
+ __version__ = "0.1.0"
tau_eval/experiment.py ADDED
@@ -0,0 +1,231 @@
1
+ import json
2
+ import os
3
+ from dataclasses import dataclass, field
4
+
5
+ import pandas as pd
6
+ from rich.table import Table
7
+ from tasknet import Task
8
+
9
+ from tau_eval.tasks.customtask import CustomTask
10
+
11
+ from .logger import logger
12
+ from .models import Anonymizer
13
+ from .utils import run_models_on_custom_task, run_models_on_task
14
+
15
+
16
+ def rich_display_dataframe(df, title="Dataframe") -> None:
17
+ """Display dataframe as table using rich library.
18
+ Args:
19
+ df (pd.DataFrame): dataframe to display
20
+ title (str, optional): title of the table. Defaults to "Dataframe".
21
+ Raises:
22
+ NotRenderableError: if dataframe cannot be rendered
23
+ Returns:
24
+ rich.table.Table: rich table
25
+ """
26
+ from rich import print
27
+
28
+ # ensure dataframe contains only string values
29
+ df = df.astype(str)
30
+
31
+ table = Table(title=title)
32
+ for col in df.columns:
33
+ table.add_column(col)
34
+ for row in df.values:
35
+ table.add_row(*row)
36
+ print(table)
37
+
38
+ @dataclass
39
+ class ExperimentConfig:
40
+ """Evaluation experiment config"""
41
+
42
+ exp_name: str = os.path.basename(__file__)[: -len(".py")]
43
+ classifier_name: str = "answerdotai/ModernBERT-base"
44
+ train_task_models: bool = False
45
+ train_with_generations: bool = False
46
+ device: str | None = "cuda"
47
+ classifier_args: dict = field(default_factory=dict)
48
+
49
+
50
+ class Experiment:
51
+ def __init__(
52
+ self,
53
+ models: list[Anonymizer],
54
+ metrics: list[str],
55
+ tasks: list[Task],
56
+ config: ExperimentConfig = ExperimentConfig(),
57
+ ):
58
+ self.models = models
59
+ self.metrics = metrics
60
+ self.tasks = tasks
61
+ self.args = config
62
+
63
+ def run(self, output_dir="", device="cuda"):
64
+ self.output_dir = output_dir
65
+ logger.info("Running experiment...")
66
+ out = {}
67
+
68
+ for i, task in enumerate(self.tasks):
69
+ logger.info(f"Running task: {i}")
70
+ if isinstance(task, CustomTask):
71
+ results = run_models_on_custom_task(self.models, task, self.metrics)
72
+ else:
73
+ results = run_models_on_task(
74
+ self.models,
75
+ task,
76
+ self.metrics,
77
+ self.args.classifier_name,
78
+ self.args.train_task_models,
79
+ self.args.train_with_generations,
80
+ device,
81
+ )
82
+ if hasattr(task, "name"):
83
+ out[f"{task.name}_{i}"] = results
84
+ else:
85
+ out[f"{task.__class__.__name__}_{i}"] = results
86
+
87
+ self.results = out
88
+ with open(self.output_dir, "w") as f:
89
+ json.dump(out, f)
90
+ logger.info("Results saved")
91
+
92
+ def summary(self, output_dir=None, to_rich=False):
93
+ if output_dir is not None:
94
+ results = json.load(open(output_dir))
95
+ else:
96
+ results = json.load(open(self.output_dir))
97
+
98
+ task_dataframes = {}
99
+
100
+ for task_name, task in results.items():
101
+ # Prepare columns for DataFrame
102
+ if isinstance(task, CustomTask):
103
+ columns = ["Model Name"] + task["metrics"]
104
+ rows = []
105
+
106
+ # Add original metrics
107
+ original_metrics = task.get("original_metrics", {})
108
+ if original_metrics:
109
+ original_row = ["Original"]
110
+ for m in task["metrics"]:
111
+ if m == "cola":
112
+ original_row.append(round(original_metrics.get("cola", 0), 4))
113
+ else:
114
+ original_row.append("-")
115
+ rows.append(original_row)
116
+ # Add rewritten metrics
117
+ for model_name, model in task.items():
118
+ if model_name in ["original_metrics", "metrics"]:
119
+ continue
120
+
121
+ row = [model_name]
122
+
123
+ for m in task["metrics"]:
124
+ row.append(round(model.get(m, 0), 4))
125
+
126
+ rows.append(row)
127
+
128
+ else:
129
+ columns = ["Model Name", "Accuracy", "F1"] + task["metrics"]
130
+ rows = []
131
+
132
+ # Add original metrics
133
+ original_metrics = task.get("original_metrics", {})
134
+ if original_metrics:
135
+ original_row = ["Original"]
136
+ original_row.append(round(original_metrics.get("test_accuracy", 0), 4))
137
+ original_row.append(round(original_metrics.get("test_f1", 0), 4))
138
+ for m in task["metrics"]:
139
+ if m == "cola":
140
+ original_row.append(round(original_metrics.get("cola", 0), 4))
141
+ else:
142
+ original_row.append("-")
143
+ rows.append(original_row)
144
+
145
+ # Add rewritten metrics
146
+ for model_name, model in task.items():
147
+ if model_name in ["original_metrics", "metrics"]:
148
+ continue
149
+
150
+ row = [model_name]
151
+ row.append(model.get("test_accuracy", 0))
152
+ row.append(model.get("test_f1", 0))
153
+
154
+ for m in task["metrics"]:
155
+ row.append(round(model.get(m, 0), 4))
156
+
157
+ rows.append(row)
158
+
159
+ # Create DataFrame for the task
160
+ task_dataframe = pd.DataFrame(rows, columns=columns)
161
+ task_dataframes[task_name] = task_dataframe
162
+ if to_rich:
163
+ for t, value in task_dataframes.items():
164
+ rich_display_dataframe(value)
165
+
166
+ return task_dataframes
167
+
168
+ def plot_tradeoff(
169
+ self,
170
+ task_name1,
171
+ target1,
172
+ task_name2,
173
+ target2,
174
+ x_label="Metric 1",
175
+ y_label="Metric 2",
176
+ title="Tradeoff Between Metrics",
177
+ figsize=(4, 4),
178
+ ):
179
+ from itertools import cycle
180
+
181
+ import matplotlib.pyplot as plt
182
+
183
+ task1 = self.results[task_name1]
184
+ task2 = self.results[task_name2]
185
+ model_names = []
186
+ x_vals = []
187
+ y_vals = []
188
+
189
+ for model_name, model in task1.items():
190
+ model_names.append(model_name)
191
+ if model_name in ["original_metrics", "metrics"]:
192
+ continue
193
+ else:
194
+ x_vals.append(model.get(target1))
195
+
196
+ for model_name, model in task2.items():
197
+ model_names.append(model_name)
198
+ if model_name in ["original_metrics", "metrics"]:
199
+ continue
200
+ else:
201
+ y_vals.append(model.get(target2))
202
+
203
+ markers = cycle(
204
+ ["o", "s", "D", "^", "v", "<", ">", "p", "*", "h", "H"]
205
+ ) # Cycle through different marker styles
206
+ plt.figure(figsize=figsize)
207
+
208
+ for i, (x_val, y_val) in enumerate(zip(x_vals, y_vals)):
209
+ marker = next(markers)
210
+ plt.scatter(
211
+ x_val,
212
+ y_val,
213
+ label=model_names[i] if model_names else f"Model {i + 1}",
214
+ marker=marker,
215
+ s=100,
216
+ alpha=0.7,
217
+ edgecolor="k",
218
+ )
219
+ # Annotate points with model names if provided
220
+ if model_names:
221
+ plt.text(x_val, y_val, model_names[i], fontsize=9, ha="right", va="bottom")
222
+
223
+ plt.axhline(0, color="gray", linewidth=0.5, linestyle="--")
224
+ plt.axvline(0, color="gray", linewidth=0.5, linestyle="--")
225
+ plt.grid(alpha=0.3)
226
+
227
+ plt.xlabel(x_label)
228
+ plt.ylabel(y_label)
229
+ plt.title(title)
230
+ plt.legend(loc="best", fontsize=9)
231
+ plt.tight_layout()
tau_eval/logger.py ADDED
@@ -0,0 +1,28 @@
1
+ import logging
2
+
3
+ from rich.logging import RichHandler
4
+
5
+
6
+ logger = logging.getLogger(__name__)
7
+
8
+ # the handler determines where the logs go: stdout/file
9
+ shell_handler = RichHandler()
10
+ file_handler = logging.FileHandler("debug.log")
11
+
12
+ logger.setLevel(logging.DEBUG)
13
+ shell_handler.setLevel(logging.DEBUG)
14
+ file_handler.setLevel(logging.DEBUG)
15
+
16
+ # the formatter determines what our logs will look like
17
+ fmt_shell = "%(message)s"
18
+ fmt_file = "%(levelname)s %(asctime)s [%(filename)s:%(funcName)s:%(lineno)d] %(message)s"
19
+
20
+ shell_formatter = logging.Formatter(fmt_shell)
21
+ file_formatter = logging.Formatter(fmt_file)
22
+
23
+ # here we hook everything together
24
+ shell_handler.setFormatter(shell_formatter)
25
+ file_handler.setFormatter(file_formatter)
26
+
27
+ logger.addHandler(shell_handler)
28
+ logger.addHandler(file_handler)
@@ -0,0 +1,35 @@
1
+ import evaluate
2
+
3
+
4
+ # Loading evaluation metric
5
+ bert = evaluate.load("bertscore")
6
+
7
+
8
+ def compute_bertscore(
9
+ input_texts: str | list[str],
10
+ output_texts: str | list[str],
11
+ model_id: str = "distilbert-base-uncased",
12
+ ) -> dict[str, list[float]]:
13
+ """
14
+ Computes BERTScore for a list of input and output text pairs.
15
+
16
+ Args:
17
+ input_texts: A string or a list of input text strings.
18
+ output_texts: A string or a list of output text strings.
19
+ model_id: Bert specification, HuggingFace model to use.
20
+
21
+ Returns:
22
+ A dictionary containing BERTScore scores for each input-output pair.
23
+ The dictionary will contain keys "precision", "recall", and "f1".
24
+ """
25
+ if not isinstance(input_texts, list):
26
+ input_texts = [input_texts]
27
+ if not isinstance(output_texts, list):
28
+ output_texts = [output_texts]
29
+ assert len(input_texts) == len(output_texts), "inputs are different lengths"
30
+
31
+ return bert.compute(
32
+ predictions=output_texts,
33
+ references=input_texts,
34
+ model_type=model_id,
35
+ )
@@ -0,0 +1,89 @@
1
+ import numpy as np
2
+ import torch
3
+ from nltk.tokenize import sent_tokenize
4
+
5
+ from transformers import (
6
+ AutoModelForSequenceClassification,
7
+ AutoTokenizer,
8
+ PreTrainedModel,
9
+ PreTrainedTokenizer,
10
+ )
11
+
12
+
13
+ def load_cola(
14
+ model_name: str = "textattack/roberta-base-CoLA", device: str = "cuda"
15
+ ) -> tuple[PreTrainedModel, PreTrainedTokenizer]:
16
+ """
17
+ Loads the CoLA (Corpus of Linguistic Acceptability) model and tokenizer.
18
+
19
+ Args:
20
+ model_name: HuggingFace model to load
21
+ device: The device to load the model onto ("cuda" or "cpu").
22
+
23
+ Returns:
24
+ A tuple containing the loaded model and tokenizer.
25
+ """
26
+ cola_tokenizer: PreTrainedTokenizer = AutoTokenizer.from_pretrained(model_name, map_location=device)
27
+ cola_model: PreTrainedModel = AutoModelForSequenceClassification.from_pretrained(model_name).to(device)
28
+ return (cola_tokenizer, cola_model)
29
+
30
+
31
+ def cola_score(
32
+ text: str,
33
+ cola_tokenizer: PreTrainedTokenizer,
34
+ cola_model: PreTrainedModel,
35
+ device: str = "cuda",
36
+ ) -> float:
37
+ """
38
+ Calculates the CoLA score for a single piece of text.
39
+
40
+ Args:
41
+ text: The text to score.
42
+ cola_tokenizer: The tokenizer for the CoLA model.
43
+ cola_model: The CoLA model.
44
+ device: The device to run the model on ("cuda" or "cpu").
45
+
46
+ Returns:
47
+ The CoLA score (a float between 0 and 1).
48
+ """
49
+ tokenize_input = cola_tokenizer.tokenize(text)
50
+ tensor_input = torch.tensor([cola_tokenizer.convert_tokens_to_ids(tokenize_input)]).to(device)
51
+ output = cola_model(tensor_input)
52
+ return output.logits.softmax(-1)[0][1].item()
53
+
54
+
55
+ def compute_cola(
56
+ output_texts: str | list[str],
57
+ cola_tokenizer: PreTrainedTokenizer,
58
+ cola_model: PreTrainedModel,
59
+ device: str = "cuda",
60
+ ) -> dict[str, list[float]]:
61
+ """
62
+ Computes CoLA scores for a list of input texts.
63
+
64
+ Args:
65
+ output_texts: A list of text strings.
66
+ cola_tokenizer: The tokenizer for the CoLA model.
67
+ cola_model: The CoLA model.
68
+ device: The device to run the model on ("cuda" or "cpu").
69
+
70
+ Returns:
71
+ A dictionary containing CoLA scores for each input text.
72
+ """
73
+ if not isinstance(output_texts, list):
74
+ output_texts = [output_texts]
75
+
76
+ cola_ls: list[float] = []
77
+ for i, text in enumerate(output_texts):
78
+ if text == "":
79
+ continue
80
+ # if text is too big, break it up
81
+ sentences = sent_tokenize(text)
82
+ cola_score_list: list[float] = []
83
+
84
+ for sent in sentences:
85
+ cola_score_list.append(cola_score(sent, cola_tokenizer, cola_model, device))
86
+
87
+ cola_ls.append(np.mean(cola_score_list))
88
+
89
+ return {"cola": cola_ls}
@@ -0,0 +1,54 @@
1
+ """Sentence transformers version of LUAR"""
2
+ import torch
3
+ from sentence_transformers import SentenceTransformer
4
+ from sentence_transformers.util import cos_sim
5
+
6
+
7
+ def load_luar(
8
+ model_name: str = "gabrielloiseau/LUAR-MUD-sentence-transformers",
9
+ device: str = "cuda",
10
+ ) -> SentenceTransformer:
11
+ """
12
+ Loads the LUAR (Language Understanding and Reasoning) sentence transformer model.
13
+
14
+ Args:
15
+ model_name: SentenceTransformers model to load.
16
+ device: The device to load the model onto ("cuda" or "cpu").
17
+
18
+ Returns:
19
+ The loaded SentenceTransformer model.
20
+ """
21
+ return SentenceTransformer(model_name, device=device)
22
+
23
+
24
+ def compute_luar(
25
+ input_texts: str | list[str],
26
+ output_texts: str | list[str],
27
+ sim_model: SentenceTransformer,
28
+ ) -> dict[str, list[float]]:
29
+ """
30
+ Computes LUAR scores based on cosine similarity between the embeddings of original and rewritten texts.
31
+
32
+ Args:
33
+ original: A string or list of original texts.
34
+ rewrites: A string or list of rewritten texts.
35
+ sim_model: The loaded SentenceTransformer model.
36
+
37
+ Returns:
38
+ A dictionary containing the LUAR scores for each pair of input texts.
39
+ The dictionary has the key "luar" with a list of float values.
40
+ """
41
+ if not isinstance(input_texts, list):
42
+ input_texts = [input_texts]
43
+ if not isinstance(output_texts, list):
44
+ output_texts = [output_texts]
45
+ assert len(input_texts) == len(output_texts), "inputs are different lengths"
46
+
47
+ outputs = []
48
+ embedding_orig: torch.Tensor = sim_model.encode(input_texts, convert_to_tensor=True, show_progress_bar=False)
49
+ embedding_rew: torch.Tensor = sim_model.encode(output_texts, convert_to_tensor=True, show_progress_bar=False)
50
+
51
+ for orig, new in zip(embedding_orig, embedding_rew):
52
+ outputs.append(cos_sim(orig, new).item())
53
+
54
+ return {"luar": outputs}
@@ -0,0 +1,46 @@
1
+ import evaluate
2
+
3
+
4
+ # Loading evaluation metric
5
+ meteor = evaluate.load("meteor")
6
+
7
+
8
+ def compute_meteor(
9
+ input_texts: str | list[str],
10
+ output_texts: str | list[str],
11
+ alpha: float = 0.9,
12
+ beta: float = 3,
13
+ gamma: float = 0.5,
14
+ ) -> dict[str, list[float]]:
15
+ """
16
+ Computes METEOR scores for a list of input and output text pairs.
17
+
18
+ Args:
19
+ input_texts: A list of input text strings.
20
+ output_texts: A list of output text strings.
21
+ alpha: Parameter for controlling relative weights of precision and recall.
22
+ beta: Parameter for controlling shape of penalty function.
23
+ gamma: Relative weight of fragmentation penalty.
24
+
25
+ Returns:
26
+ A dictionary containing METEOR scores for each input-output pair.
27
+ """
28
+ if not isinstance(input_texts, list):
29
+ input_texts = [input_texts] # type: ignore
30
+ if not isinstance(output_texts, list):
31
+ output_texts = [output_texts] # type: ignore
32
+ assert len(input_texts) == len(output_texts), "inputs are different lengths"
33
+
34
+ scores = []
35
+ for input_text, output_text in zip(input_texts, output_texts):
36
+ scores.append(
37
+ meteor.compute(
38
+ predictions=[output_text],
39
+ references=[input_text],
40
+ alpha=alpha,
41
+ beta=beta,
42
+ gamma=gamma,
43
+ )["meteor"]
44
+ )
45
+
46
+ return {"meteor": scores}
@@ -0,0 +1,78 @@
1
+ import torch
2
+
3
+ from transformers import (
4
+ AutoModelForSequenceClassification,
5
+ AutoTokenizer,
6
+ PreTrainedModel,
7
+ PreTrainedTokenizer,
8
+ )
9
+
10
+
11
+ def load_nli(
12
+ model_name: str = "alisawuffles/roberta-large-wanli", device: str = "cuda"
13
+ ) -> tuple[PreTrainedTokenizer, PreTrainedModel]:
14
+ """
15
+ Loads the NLI (Natural Language Inference) model and tokenizer.
16
+
17
+ Args:
18
+ model_name: HuggingFace model to load
19
+ device: The device to load the model onto ("cuda" or "cpu").
20
+
21
+ Returns:
22
+ A tuple containing the loaded tokenizer and model.
23
+ """
24
+ # Download necessary models for evaluation
25
+ nli_tokenizer: PreTrainedTokenizer = AutoTokenizer.from_pretrained(model_name, map_location=device)
26
+ nli_model: PreTrainedModel = AutoModelForSequenceClassification.from_pretrained(model_name).to(device)
27
+
28
+ return (nli_tokenizer, nli_model)
29
+
30
+
31
+ def compute_nli(
32
+ input_texts: str | list[str],
33
+ output_texts: str | list[str],
34
+ nli_tokenizer: PreTrainedTokenizer,
35
+ nli_model: PreTrainedModel,
36
+ batch_size: int = 16,
37
+ device: str = "cuda",
38
+ max_length: int = 128,
39
+ ) -> dict[str, list[float]]:
40
+ """
41
+ Computes the probability of entailment between two texts using the NLI model.
42
+
43
+ Args:
44
+ input_text: The premise text.
45
+ output_text: The hypothesis text.
46
+ nli_tokenizer: The tokenizer for the NLI model.
47
+ nli_model: The NLI model.
48
+
49
+ Returns:
50
+ A dictionary containing the probability of entailment.
51
+ The dictionary has the key "entailment" with a float value.
52
+ """
53
+ if not isinstance(input_texts, list):
54
+ input_texts = [input_texts] # type: ignore
55
+ if not isinstance(output_texts, list):
56
+ output_texts = [output_texts] # type: ignore
57
+ assert len(input_texts) == len(output_texts), "inputs are different lengths"
58
+
59
+ entailment_prob = []
60
+
61
+ for start_index in range(0, len(output_texts), batch_size):
62
+ end_index = min(start_index + batch_size, len(output_texts))
63
+ input_batch = input_texts[start_index:end_index]
64
+ output_batch = output_texts[start_index:end_index]
65
+
66
+ x = nli_tokenizer(
67
+ input_batch,
68
+ output_batch,
69
+ return_tensors="pt",
70
+ max_length=max_length,
71
+ padding=True,
72
+ truncation=True,
73
+ ).to(device)
74
+ with torch.no_grad():
75
+ logits = nli_model.to(device)(**x).logits
76
+ entailment_prob += logits.softmax(dim=1)[:, 1].tolist()
77
+
78
+ return {"entailment": entailment_prob}
@@ -0,0 +1,24 @@
1
+ import evaluate
2
+
3
+
4
+ # Loading evaluation metric
5
+ perplexity = evaluate.load("perplexity", module_type="metric")
6
+
7
+
8
+ def compute_perplexity(output_texts: str | list[str], model_id: str = "gpt2") -> dict[str, list[float]]:
9
+ """
10
+ Computes perplexity scores for a list of output texts.
11
+
12
+ Args:
13
+ output_texts: A string or list of output text strings.
14
+ model_id: HuggingFace model to use
15
+
16
+ Returns:
17
+ A dictionary containing perplexity scores for each input text.
18
+ """
19
+ if not isinstance(output_texts, list):
20
+ output_texts = [output_texts]
21
+
22
+ result = perplexity.compute(predictions=output_texts, model_id=model_id)
23
+
24
+ return result
@@ -0,0 +1,28 @@
1
+ import evaluate
2
+
3
+
4
+ # Loading evaluation metric
5
+ rouge = evaluate.load("rouge")
6
+
7
+
8
+ def compute_rouge(
9
+ input_texts: str | list[str],
10
+ output_texts: str | list[str],
11
+ ) -> dict[str, list[float]]:
12
+ """
13
+ Computes ROUGE scores for a list of input and output text pairs.
14
+
15
+ Args:
16
+ input_texts: A list of input text strings.
17
+ output_texts: A list of output text strings.
18
+
19
+ Returns:
20
+ A dictionary containing ROUGE scores for each input-output pair.
21
+ """
22
+ if not isinstance(input_texts, list):
23
+ input_texts = [input_texts] # type: ignore
24
+ if not isinstance(output_texts, list):
25
+ output_texts = [output_texts] # type: ignore
26
+ assert len(input_texts) == len(output_texts), "inputs are different lengths"
27
+
28
+ return rouge.compute(predictions=output_texts, references=input_texts, use_aggregator=False)
@@ -0,0 +1,52 @@
1
+ import torch
2
+ from sentence_transformers import SentenceTransformer
3
+ from sentence_transformers.util import cos_sim
4
+
5
+
6
+ def load_sbert(
7
+ model_name: str = "sentence-transformers/all-MiniLM-L6-v2", device: str = "cuda"
8
+ ) -> SentenceTransformer:
9
+ """
10
+ Loads the sentence similarity model.
11
+
12
+ Args:
13
+ model_name: SentenceTransformers model to load.
14
+ device: The device to load the model onto ("cuda" or "cpu").
15
+
16
+ Returns:
17
+ The loaded SentenceTransformer model.
18
+ """
19
+ return SentenceTransformer(model_name, device=device)
20
+
21
+
22
+ def compute_sbert(
23
+ input_texts: str | list[str],
24
+ output_texts: str | list[str],
25
+ sim_model: SentenceTransformer,
26
+ ) -> dict[str, list[float]]:
27
+ """
28
+ Computes the cosine similarity between the embeddings of original and rewritten texts.
29
+
30
+ Args:
31
+ original: A string or a list of original texts.
32
+ rewrites: A string or a list of rewritten texts.
33
+ sim_model: The loaded SentenceTransformer model.
34
+
35
+ Returns:
36
+ A dictionary containing the similarity scores for each input text pair.
37
+ The dictionary has the key "similarity" with a list of float values.
38
+ """
39
+ if not isinstance(input_texts, list):
40
+ input_texts = [input_texts]
41
+ if not isinstance(output_texts, list):
42
+ output_texts = [output_texts]
43
+ assert len(input_texts) == len(output_texts), "inputs are different lengths"
44
+
45
+ outputs = []
46
+ embedding_orig: torch.Tensor = sim_model.encode(input_texts, convert_to_tensor=True, show_progress_bar=False)
47
+ embedding_rew: torch.Tensor = sim_model.encode(output_texts, convert_to_tensor=True, show_progress_bar=False)
48
+
49
+ for orig, new in zip(embedding_orig, embedding_rew):
50
+ outputs.append(cos_sim(orig, new).item())
51
+
52
+ return {"sbert": outputs}
@@ -0,0 +1,4 @@
1
+ from .anonymizer import Anonymizer
2
+
3
+
4
+ __all__ = ["Anonymizer"]