cacheverifier 0.3.0__tar.gz → 0.3.1__tar.gz

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.
Files changed (22) hide show
  1. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/CHANGELOG.md +10 -0
  2. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/PKG-INFO +1 -1
  3. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/cacheverifier/_healthcheck/_finetune.py +10 -2
  4. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/cacheverifier/_healthcheck/cli.py +2 -2
  5. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/pyproject.toml +1 -1
  6. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/tests/test_healthcheck.py +25 -0
  7. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/.github/workflows/ci.yml +0 -0
  8. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/.github/workflows/publish.yml +0 -0
  9. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/.gitignore +0 -0
  10. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/LICENSE +0 -0
  11. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/README.md +0 -0
  12. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/cacheverifier/__init__.py +0 -0
  13. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/cacheverifier/__main__.py +0 -0
  14. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/cacheverifier/_healthcheck/__init__.py +0 -0
  15. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/cacheverifier/client.py +0 -0
  16. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/cacheverifier/integrations/__init__.py +0 -0
  17. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/cacheverifier/integrations/gptcache.py +0 -0
  18. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/cacheverifier/py.typed +0 -0
  19. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/examples/gptcache_example.py +0 -0
  20. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/examples/quickstart.py +0 -0
  21. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/tests/test_client.py +0 -0
  22. {cacheverifier-0.3.0 → cacheverifier-0.3.1}/tests/test_gptcache_integration.py +0 -0
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.1
4
+
5
+ `cacheverifier healthcheck` now actually fine-tunes. It passed no
6
+ `warmup_steps` to `CrossEncoder.fit`, whose default of 10000 kept a typical
7
+ run below a few percent of its learning rate, so `auc_tuned` came back equal
8
+ (or nearly equal) to `auc_baseline`. Warmup is now 10% of total steps and the
9
+ default is 3 epochs (`--epochs`), the same as the hosted service since
10
+ verifier-core 0.2.0. On a 500-row later holdout this took LmArena AUC from
11
+ 0.903 to 0.932 and AmazonHelp from 0.551 to 0.700. Runs take about 3x as long.
12
+
3
13
  ## 0.3.0
4
14
 
5
15
  Make the request-path defaults safe. `verify()` and `verify_batch()` now use a
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: cacheverifier
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Python client for the hosted CacheVerifier semantic-cache verification API
5
5
  Project-URL: Homepage, https://www.cacheverifier.com
6
6
  Project-URL: Documentation, https://www.cacheverifier.com/docs
@@ -43,6 +43,13 @@ _CONTENT_TOKEN_BUDGET = MAX_SEQUENCE_LENGTH - 3 # [CLS] + 2x [SEP]
43
43
  _MIN_QUERY_TOKENS = 32
44
44
 
45
45
  TRAIN_BATCH_SIZE = 4
46
+ TRAIN_EPOCHS = 3
47
+ TRAIN_WARMUP_FRACTION = 0.1
48
+ """Same as the hosted service (verifier-core 0.2.0). `CrossEncoder.fit`
49
+ defaults to `warmup_steps=10000`; without an explicit value a typical run
50
+ (a few hundred steps) never got past a few percent of its learning rate and
51
+ the "fine-tuned" model was a near monotone shift of the base model, so
52
+ `auc_tuned` came back equal to `auc_baseline`."""
46
53
  MIN_TRAIN_EXAMPLES = 20
47
54
  """Hard floor -- below this there aren't enough rows for one meaningful
48
55
  epoch plus a held-out split."""
@@ -183,7 +190,7 @@ def run_healthcheck(
183
190
  output_dir: str,
184
191
  *,
185
192
  base_model: str = DEFAULT_BASE_MODEL,
186
- epochs: int = 1,
193
+ epochs: int = TRAIN_EPOCHS,
187
194
  ) -> HealthCheckResult:
188
195
  """Fine-tune `base_model` on a chronological prefix of `examples` and
189
196
  measure held-out AUC for the stock vs. fine-tuned model.
@@ -233,7 +240,8 @@ def run_healthcheck(
233
240
  # whether or not torch's stubs are installed (base CI has no torch).
234
241
  loader: DataLoader[Any] = DataLoader(cast(Any, train_examples), shuffle=True, batch_size=TRAIN_BATCH_SIZE)
235
242
  t0 = time.time()
236
- tuned.fit(train_dataloader=loader, epochs=epochs, show_progress_bar=False)
243
+ warmup_steps = max(1, int(TRAIN_WARMUP_FRACTION * len(loader) * epochs))
244
+ tuned.fit(train_dataloader=loader, epochs=epochs, warmup_steps=warmup_steps, show_progress_bar=False)
237
245
  train_time_seconds = time.time() - t0
238
246
  tuned.save(output_dir)
239
247
 
@@ -48,8 +48,8 @@ def add_subparser(subparsers: argparse._SubParsersAction) -> None:
48
48
  p.add_argument(
49
49
  "--epochs",
50
50
  type=int,
51
- default=1,
52
- help="fine-tuning epochs (default: 1, matching the hosted service)",
51
+ default=3,
52
+ help="fine-tuning epochs (default: 3, matching the hosted service)",
53
53
  )
54
54
  p.add_argument(
55
55
  "--keep-model",
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "cacheverifier"
7
- version = "0.3.0"
7
+ version = "0.3.1"
8
8
  description = "Python client for the hosted CacheVerifier semantic-cache verification API"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -98,3 +98,28 @@ def test_run_healthcheck_end_to_end(tmp_path):
98
98
  assert result.n_train + result.n_calibrate + result.n_test == 36
99
99
  assert 0.0 <= result.auc_tuned <= 1.0
100
100
  assert (tmp_path / "model").is_dir()
101
+
102
+
103
+ @pytest.mark.skipif(not HAS_TORCH, reason="needs the healthcheck extra (torch)")
104
+ def test_run_healthcheck_warms_up_over_a_tenth_of_its_steps(tmp_path, monkeypatch):
105
+ # CrossEncoder.fit defaults to warmup_steps=10000, which kept a
106
+ # few-hundred-step run from ever reaching its learning rate.
107
+ from sentence_transformers import CrossEncoder
108
+
109
+ from cacheverifier._healthcheck import _finetune
110
+ from cacheverifier._healthcheck._finetune import GrayZoneExample, run_healthcheck
111
+
112
+ seen: dict = {}
113
+ real_fit = CrossEncoder.fit
114
+
115
+ def spy_fit(self, *args, **kwargs):
116
+ seen.update(kwargs, steps_per_epoch=len(kwargs["train_dataloader"]))
117
+ return real_fit(self, *args, **kwargs)
118
+
119
+ monkeypatch.setattr(CrossEncoder, "fit", spy_fit)
120
+ examples = [GrayZoneExample(f"question {i}", f"answer {i % 3}", i % 2 == 0) for i in range(40)]
121
+ run_healthcheck(examples, str(tmp_path / "model"))
122
+
123
+ assert seen["epochs"] == _finetune.TRAIN_EPOCHS == 3
124
+ expected = max(1, int(_finetune.TRAIN_WARMUP_FRACTION * seen["steps_per_epoch"] * seen["epochs"]))
125
+ assert seen["warmup_steps"] == expected
File without changes
File without changes
File without changes