Skip to content

Commit bcd8a40

Browse files
authored
Merge pull request #71 from PriorLabs/disable-pseudo-tracking
Drop install ID tracking
2 parents 8923f2a + 6f4416c commit bcd8a40

7 files changed

Lines changed: 5 additions & 147 deletions

File tree

src/tabpfn_common_utils/telemetry/core/events.py

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
nvmlShutdown,
1717
)
1818
from .runtime import get_execution_context
19-
from .state import get_property, set_property
2019

2120

2221
def _uuid4() -> str:
@@ -256,50 +255,6 @@ def _get_runtime_environment() -> Optional[str]:
256255
return exec_context.environment
257256

258257

259-
@lru_cache(maxsize=1)
260-
def _get_install_id() -> str:
261-
"""Get or create the install ID. If not set in disk-cached
262-
state, generate a new one and store it in the state.
263-
264-
Returns:
265-
str: The install ID.
266-
"""
267-
install_id = get_property("install_id")
268-
269-
# Fallback to new install ID
270-
if install_id is None:
271-
install_id = _uuid4()
272-
set_property("install_id", install_id)
273-
274-
return install_id
275-
276-
277-
@lru_cache(maxsize=1)
278-
def _get_install_date() -> str:
279-
"""Return the install date as YYYY-MM-DD.
280-
281-
In case the user was using TabPFN before this change was made,
282-
the install date will not correspond to the actual install date,
283-
but rather when the user upgraded the page and made a first call.
284-
285-
Returns:
286-
str: The install date as YYYY-MM-DD.
287-
"""
288-
value = get_property("install_date")
289-
290-
if isinstance(value, str):
291-
try:
292-
dt = datetime.fromisoformat(value.replace("Z", "+00:00"))
293-
return dt.date().isoformat()
294-
except ValueError:
295-
pass
296-
297-
# Fallback to current date
298-
value = _utc_now_date()
299-
set_property("install_date", value)
300-
return value
301-
302-
303258
@dataclass
304259
class BaseTelemetryEvent:
305260
"""
@@ -355,12 +310,6 @@ class SessionEvent(BaseTelemetryEvent):
355310
is a single init call to TabPFNClassifier or TabPFNRegressor.
356311
"""
357312

358-
# Install ID of the user
359-
install_id: str = field(default_factory=_get_install_id, init=False)
360-
361-
# Install date of the user
362-
install_date: str = field(default_factory=_get_install_date, init=False)
363-
364313
@property
365314
def name(self) -> str:
366315
return "session"
@@ -375,9 +324,6 @@ class ModelLoadEvent(BaseTelemetryEvent):
375324
# Status of the model download attempt
376325
status: Literal["success", "failed"]
377326

378-
# Install ID of the user
379-
install_id: str = field(default_factory=_get_install_id, init=False)
380-
381327
# Name of the model, may be a HuggingFace repo ID
382328
model_name: Optional[str] = field(default=None)
383329

@@ -439,9 +385,6 @@ class ModelCallEvent(BaseTelemetryEvent):
439385
# Task associated with the model call
440386
task: Literal["classification", "regression"]
441387

442-
# Install ID of the user
443-
install_id: str = field(default_factory=_get_install_id, init=False)
444-
445388
# Version of the PyTorch
446389
torch_version: str = field(default_factory=_get_torch_version, init=False)
447390

src/tabpfn_common_utils/telemetry/core/state.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,6 @@
3131
_DEFAULT_STATE: dict[str, Any] = {
3232
# Date and time when state file was created
3333
"created_at": None,
34-
# Anonymous user ID, only with consent
35-
"user_id": None,
36-
# Email address, only with consent
37-
"email": None,
3834
# Number of times prompts were shown
3935
"nr_prompts": 0,
4036
# Date and time when last prompt was shown

src/tabpfn_common_utils/telemetry/interactive/flows.py

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from datetime import datetime, timedelta, timezone
66

77
from typing import List
8-
from ..core.config import download_config
98
from ..core.state import get_property, set_property
109
from ..core import PingEvent, SessionEvent, capture_event
1110
from .prompts.base import PromptSpec
@@ -76,52 +75,6 @@ def _trigger_prompts(delta_days: int, max_prompts: int) -> bool:
7675
Returns:
7776
True if a prompt should be shown, False otherwise.
7877
"""
79-
utc_now = datetime.now(timezone.utc)
80-
81-
# Download prompt configuration
82-
config = download_config()
83-
84-
# By default, don't prompt
85-
if not config.get("prompt_user", False):
86-
return False
87-
88-
# If new installation, don't prompt
89-
install_date = get_property("install_date", data_type=datetime)
90-
if not install_date:
91-
set_property("install_date", utc_now)
92-
return False
93-
94-
# Avoid prompt in first 24 hours
95-
delta_hours = config.get("prompt_delta_hours", 24)
96-
97-
# Ensure timezone-aware datetime
98-
if install_date.tzinfo is None:
99-
install_date = install_date.replace(tzinfo=timezone.utc)
100-
101-
if utc_now - install_date <= timedelta(hours=delta_hours):
102-
return False
103-
104-
# If used <= 5 times, don't prompt
105-
nr_usages = get_property("nr_usages", 0, data_type=int)
106-
set_property("nr_usages", nr_usages + 1)
107-
108-
if nr_usages < config.get("prompt_nr_usages", 5):
109-
return False
110-
111-
# If last prompted > 30 days, prompt
112-
last_prompted_at = get_property("last_prompted_at", data_type=datetime)
113-
if not last_prompted_at:
114-
return True
115-
116-
# Check if the maximum number of prompts has been reached
117-
nr_prompts = get_property("nr_prompts", 0, data_type=int)
118-
if nr_prompts >= max_prompts:
119-
return False
120-
121-
# Check if the time since the last prompt is greater than the delta days
122-
if utc_now - last_prompted_at >= timedelta(days=delta_days):
123-
return True
124-
12578
return False
12679

12780

src/tabpfn_common_utils/telemetry/interactive/prompts/identity.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import logging
2-
import uuid
32
import textwrap
43

54
from typing import Any, Dict, Optional
65
from .base import render_html, PromptResult, Outcome, parse_input, PromptSpec
7-
from ...core.state import get_property, set_property
86

97

108
# Logger
@@ -69,8 +67,7 @@ def _should_prompt() -> bool:
6967
"""
7068
Check if the user should be prompted to subscribe to the newsletter.
7169
"""
72-
user_id = get_property("user_id")
73-
return user_id is None
70+
return False
7471

7572

7673
def _on_done(res: PromptResult) -> None:
@@ -79,11 +76,7 @@ def _on_done(res: PromptResult) -> None:
7976
Args:
8077
res: The prompt result.
8178
"""
82-
if res.outcome != "accepted":
83-
return
84-
85-
user_id = str(uuid.uuid4())
86-
set_property("user_id", user_id)
79+
return None
8780

8881

8982
class IdentityPrompt:

src/tabpfn_common_utils/telemetry/interactive/prompts/newsletter.py

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@
22
import os
33
import re
44

5-
import requests
65
import textwrap
76
from typing import Any, Dict, Optional
87
from .base import render_html, PromptResult, Outcome, parse_input, PromptSpec
9-
from ...core.state import get_property, set_property
108

119

1210
# Logger
@@ -90,19 +88,14 @@ def _subscribe_user(email: str) -> None:
9088
Args:
9189
email: The email of the user to opt_in.
9290
"""
93-
endpoint = _API_URL + "/newsletter/subscribe"
94-
r = requests.post(endpoint, json={"email": email.lower()}, timeout=5)
95-
if r.status_code != 200:
96-
_logger.debug(f"Failed to subscribe user {email}: {r.text}")
97-
return
91+
return None
9892

9993

10094
def _should_prompt() -> bool:
10195
"""
10296
Check if the user should be prompted to subscribe to the newsletter.
10397
"""
104-
email = get_property("email")
105-
return email is None
98+
return False
10699

107100

108101
def _on_done(res: PromptResult) -> None:
@@ -111,22 +104,7 @@ def _on_done(res: PromptResult) -> None:
111104
Args:
112105
res: The prompt result.
113106
"""
114-
if res.outcome != "accepted":
115-
return
116-
117-
payload = res.data or {}
118-
email = payload.get("email")
119-
if not email:
120-
return
121-
122-
try:
123-
# Subscribe the user to the newsletter using the API
124-
_subscribe_user(email)
125-
except Exception:
126-
# best-effort; don't disrupt host process
127-
pass
128-
129-
set_property("email", email)
107+
return None
130108

131109

132110
class NewsletterPrompt:

tests/telemetry/core/test_events.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,6 @@ def test_model_load_event_inherits_base_properties(self):
402402
assert isinstance(event.tabpfn_version, str)
403403
assert isinstance(event.timestamp, datetime)
404404
assert event.source == "sdk"
405-
assert isinstance(event.install_id, str)
406405

407406
def test_model_load_event_properties_method(self):
408407
"""Test ModelLoadEvent properties method"""
@@ -420,7 +419,6 @@ def test_model_load_event_properties_method(self):
420419
assert props["failure_reason"] == "Download timeout"
421420
assert "python_version" in props
422421
assert "tabpfn_version" in props
423-
assert "install_id" in props
424422

425423

426424
class TestExtensionEntryEvent:

tests/telemetry/core/test_state.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@ def test_filelock_availability(self):
4141
def test_default_state_schema(self):
4242
assert isinstance(_DEFAULT_STATE, dict)
4343
assert "created_at" in _DEFAULT_STATE
44-
assert "user_id" in _DEFAULT_STATE
45-
assert "email" in _DEFAULT_STATE
4644
assert "nr_prompts" in _DEFAULT_STATE
4745
assert "last_prompted_at" in _DEFAULT_STATE
4846

@@ -311,7 +309,6 @@ def test_load_state_non_existing_file(self):
311309
with patch(name, return_value=non_existent_path):
312310
result = load_state()
313311
assert "created_at" in result
314-
assert result["user_id"] is None
315312

316313

317314
class TestSaveState:

0 commit comments

Comments
 (0)