IvoHoese commited on
Commit
35f622f
·
verified ·
1 Parent(s): f1c9d40

Upload task_template.py

Browse files
Files changed (1) hide show
  1. task_template.py +294 -0
task_template.py ADDED
@@ -0,0 +1,294 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import pandas as pd
3
+ import requests
4
+ import sys
5
+ import torchvision.models as models
6
+ import os
7
+
8
+ from transformers import AutoTokenizer, PreTrainedModel, AutoModelForSequenceClassification
9
+
10
+ import utils
11
+
12
+ # --------------------------------
13
+ # DATASET
14
+ # --------------------------------
15
+
16
+ """
17
+ Dataset contents:
18
+
19
+ - 100 subsets of text data, each subset stored under the key "subset_{i}" where i ranges from 0 to 99.
20
+ Each subset is a dictionary with:
21
+ -"prompts": List of 100 prompts in the subset
22
+ -"labels": Tensor of true labels for the prompts in the subset, has shape (100)
23
+ -"subset_id": Integer ID of the subset (from 0 to 99)
24
+ """
25
+
26
+ # Load the dataset
27
+ dataset = torch.load("fulltuning.pt")
28
+
29
+ # Example: Acessing subsets
30
+ subset_0 = dataset["subset_0"]
31
+
32
+ print("Subset 0 keys:", subset_0.keys())
33
+ print("Subset ID:", subset_0["subset_id"])
34
+ print("Labels length:", len(subset_0["labels"]))
35
+ print("First prompts:", subset_0["prompts"][:5])
36
+ print("First 5 labels:", subset_0["labels"][:5])
37
+
38
+ # --------------------------------
39
+ # QUERYING THE CLASSIFIER
40
+ # --------------------------------
41
+
42
+ # This Code can be used to load and query the fully fine-tuned models. You also need to the available utils.py file.
43
+
44
+ #|---------------------------------------------------------------------------------------------------|
45
+ #| NOTE: "Missing or unexpected params" warnings are no reason for concern. They stem from the |
46
+ #| fact that the model is first loaded without a classifier head, which is added afterwards. |
47
+ #|---------------------------------------------------------------------------------------------------|
48
+
49
+ # Use this tokenizer for OLMO...
50
+
51
+ tokenizer = AutoTokenizer.from_pretrained("allenai/OLMo-1B-hf", trust_remote_code=True)
52
+
53
+ # ...and this one for Pythia
54
+
55
+ tokenizer = AutoTokenizer.from_pretrained("EleutherAI/pythia-410m", trust_remote_code=True)
56
+
57
+
58
+ tokenizer.padding_side = "left"
59
+
60
+ if tokenizer.pad_token is None:
61
+ tokenizer.pad_token = tokenizer.eos_token
62
+
63
+
64
+ # Usage example (fulltuning):
65
+
66
+ model_path = "olmo-fulltuning"
67
+
68
+ model = utils.get_fulltuning_model(model_path, model_type="olmo") # model_type can be "olmo" or "pythia"
69
+
70
+ example_prompt = "I think, therefore I am.\n\nI am."
71
+
72
+ inputs = tokenizer(example_prompt, return_tensors="pt", truncation=True)
73
+ inputs = {k: v.to(model.device) for k, v in inputs.items()}
74
+ with torch.no_grad():
75
+ outputs = model(**inputs)
76
+
77
+ logits = outputs.logits
78
+
79
+ print(f"Logits shape: {logits.shape}")
80
+ print(f"Logits: {logits}")
81
+
82
+
83
+
84
+ # Usage example (softprompt):
85
+
86
+ model_path = "olmo-softprompt"
87
+
88
+ model = utils.get_peft_model(model_path, model_type="olmo") # model_type can be "olmo" or "pythia"
89
+
90
+ example_prompt = "I think, but do I exist?\n\nSince you think, you exist."
91
+
92
+ inputs = tokenizer(example_prompt, return_tensors="pt", truncation=True)
93
+ inputs = {k: v.to(model.device) for k, v in inputs.items()}
94
+ with torch.no_grad():
95
+ outputs = model(**inputs)
96
+
97
+ logits = outputs.logits
98
+
99
+ print(f"Logits shape: {logits.shape}")
100
+ print(f"Logits: {logits}")
101
+
102
+
103
+
104
+ # Usage example (lora):
105
+
106
+ model_path = "olmo-lora"
107
+
108
+ model = utils.get_peft_model(model_path, model_type="olmo") # model_type can be "olmo" or "pythia"
109
+
110
+ example_prompt = "Who am I?\n\nWhat am I?"
111
+
112
+ inputs = tokenizer(example_prompt, return_tensors="pt", truncation=True)
113
+ inputs = {k: v.to(model.device) for k, v in inputs.items()}
114
+ with torch.no_grad():
115
+ outputs = model(**inputs)
116
+
117
+ logits = outputs.logits
118
+
119
+ print(f"Logits shape: {logits.shape}")
120
+ print(f"Logits: {logits}")
121
+
122
+
123
+
124
+ # Usage example (lastlayer):
125
+
126
+ model_path = "olmo-lastlayer"
127
+
128
+ model = utils.get_peft_model(model_path, model_type="olmo") # model_type can be "olmo" or "pythia"
129
+
130
+ example_prompt = "I love to exist!"
131
+
132
+ inputs = tokenizer(example_prompt, return_tensors="pt", truncation=True)
133
+ inputs = {k: v.to(model.device) for k, v in inputs.items()}
134
+ with torch.no_grad():
135
+ outputs = model(**inputs)
136
+
137
+ logits = outputs.logits
138
+
139
+ print(f"Logits shape: {logits.shape}")
140
+ print(f"Logits: {logits}")
141
+
142
+ # --------------------------------
143
+ # SUBMISSION FORMAT
144
+ # --------------------------------
145
+
146
+ """
147
+ The submission must be a .csv file with the following format:
148
+
149
+ -"type": Name of the model (e.g., "softprompt", "fulltuning", etc.)
150
+ -"subset_id": ID of the subset (from 0 to 999, per type)
151
+ -"membership": Membership score for each subset (float)
152
+ """
153
+
154
+ # Example Submission:
155
+
156
+ types = ["softprompt", "fulltuning", "lora", "lastlayer"]
157
+ type_list = []
158
+
159
+ for t in types:
160
+ type_list.extend([t] * 1000)
161
+
162
+ subset_ids = []
163
+ for _ in types:
164
+ subset_ids.extend(list(range(1000)))
165
+
166
+ membership_scores = torch.rand(4000).tolist()
167
+ submission_df = pd.DataFrame({
168
+ "type": type_list,
169
+ "subset_id": subset_ids,
170
+ "membership": membership_scores
171
+ })
172
+ submission_df.to_csv("example_submission.csv", index=None)
173
+
174
+ # --------------------------------
175
+ # SUBMISSION PROCESS
176
+ # --------------------------------
177
+
178
+ """
179
+ Example submission script for the LLM Dataset Membership Inference Task.
180
+
181
+ Submission Requirements (read carefully to avoid automatic rejection):
182
+
183
+ 1. CSV FORMAT
184
+ ----------------
185
+ - The file **must be a CSV** with extension `.csv`.
186
+ - It must contain **exactly three columns**, named:
187
+ type, subset_id, membership
188
+ → Column names must match exactly (lowercase, no extra spaces).
189
+ → Column order does not matter, but all three must be present.
190
+
191
+ 2. ROW COUNT AND IDENTIFIERS
192
+ -------------------------------
193
+ - Your file must contain **exactly 4000 rows**.
194
+ - Each row corresponds to one unique `subset_id`/`type` pair, with ids in the range **0–999** (inclusive).
195
+ - Every subset_id must appear **exactly once** for each type.
196
+ - Do **not** add, remove, or rename any IDs.
197
+ - Do **not** include duplicates or missing entries.
198
+ - The evaluator checks:
199
+ subset_id.min() == 0
200
+ subset_id.max() == 999
201
+ subset_id.unique().size == 1000
202
+
203
+ 3. MEMBERSHIP SCORES
204
+ ----------------------
205
+ - The `membership` column must contain **numeric values** representing your model’s predicted confidence
206
+ that the corresponding subset is a **member** of the training set.
207
+
208
+ Examples of valid membership values:
209
+ - Probabilities: values in [0.0, 1.0]
210
+ - Raw model scores: any finite numeric values (will be ranked for TPR@FPR=0.05)
211
+
212
+ - Do **not** submit string labels like "yes"/"no" or "member"/"non-member".
213
+ - The evaluator converts your `membership` column to numeric using `pd.to_numeric()`.
214
+ → Any non-numeric, NaN, or infinite entries will cause automatic rejection.
215
+
216
+ 4. TECHNICAL LIMITS
217
+ ----------------------
218
+ - Maximum file size: **20 MB**
219
+ - Encoding: UTF-8 recommended.
220
+ - Avoid extra columns, blank lines, or formulas.
221
+ - Ensure all values are numeric and finite.
222
+ - Supported data types: int, float (e.g., float32, float64)
223
+
224
+ 5. VALIDATION SUMMARY
225
+ ------------------------
226
+ Your submission will fail if:
227
+ - Columns don’t match exactly ("type", "subset_id", "membership")
228
+ - Row count differs from 4000
229
+ - Any type name is unexpected or not in the allowed set
230
+ - Any subset_id is missing, duplicated, or outside [0, 999] for any type
231
+ - Any membership value is NaN, Inf, or non-numeric
232
+ - File is too large or not a valid CSV
233
+
234
+ Two key metrics are computed:
235
+ 1. **ROC-AUC (Area Under the ROC Curve)** — measures overall discriminative ability.
236
+ 2. **TPR@FPR=0.05** — true positive rate when the false positive rate is at 5%.
237
+
238
+ """
239
+
240
+ BASE_URL = "http://35.192.205.84:80"
241
+ API_KEY = "77ab4a807d03d48e1d85881b27496871" # replace with your actual API key
242
+
243
+ TASK_ID = "14-llm-dataset-inference"
244
+ FILE_PATH = "example_submission.csv" # replace with your actual file path
245
+
246
+ SUBMIT = False # Set to True to enable submission
247
+
248
+ def die(msg):
249
+ print(f"{msg}", file=sys.stderr)
250
+ sys.exit(1)
251
+
252
+ if SUBMIT:
253
+ if not os.path.isfile(FILE_PATH):
254
+ die(f"File not found: {FILE_PATH}")
255
+
256
+ try:
257
+ with open(FILE_PATH, "rb") as f:
258
+ files = {
259
+ # (fieldname) -> (filename, fileobj, content_type)
260
+ "file": (os.path.basename(FILE_PATH), f, "csv"),
261
+ }
262
+ resp = requests.post(
263
+ f"{BASE_URL}/submit/{TASK_ID}",
264
+ headers={"X-API-Key": API_KEY},
265
+ files=files,
266
+ timeout=(10, 120), # (connect timeout, read timeout)
267
+ )
268
+ # Helpful output even on non-2xx
269
+ try:
270
+ body = resp.json()
271
+ except Exception:
272
+ body = {"raw_text": resp.text}
273
+
274
+ if resp.status_code == 413:
275
+ die("Upload rejected: file too large (HTTP 413). Reduce size and try again.")
276
+
277
+ resp.raise_for_status()
278
+
279
+ submission_id = body.get("submission_id")
280
+ print("Successfully submitted.")
281
+ print("Server response:", body)
282
+ if submission_id:
283
+ print(f"Submission ID: {submission_id}")
284
+
285
+ except requests.exceptions.RequestException as e:
286
+ detail = getattr(e, "response", None)
287
+ print(f"Submission error: {e}")
288
+ if detail is not None:
289
+ try:
290
+ print("Server response:", detail.json())
291
+ except Exception:
292
+ print("Server response (text):", detail.text)
293
+ sys.exit(1)
294
+