update sdk with new adds - #467
Conversation
Benchmark-paradigm parity with the EvaluationV2 UI: - Benchmark resource + client CRUD (create from item_ids/items/slice/dataset, list, get, update, delete, paginated items) - create_benchmark_evaluation_v2 (uncovered items score as FN; label config via rollup_groups / legacy matches / preset) - RollupGroup as the primary label configuration, wired through presets - EvaluationV2 exposes benchmark_id + rollup_groups - Benchmark leaderboard_ranking / leaderboard_f1_curve and evaluation filter_schema (require the scaleapi REST mirrors to be deployed) - v0.19.0 + changelog Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pre-existing W0718 on the batch-create per-job catch made pylint exit nonzero. Use disable-next on its own line so black's 79-char wrap can't displace the pragma. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The platform moved to the benchmark paradigm; dataset/slice-scoped eval creation never shipped. Removes create_evaluation_v2, create_evaluations_v2_batch, BatchEvaluationResult, and only_items_with_predictions from the SDK surface, and consolidates the unreleased 0.18.9 changelog section into the single 0.19.0 entry. Reading old evals (slice_id, exclusion fields) still works. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Same pass as the weights branch: the docstrings are published API docs, so they shouldn't explain how the platform stores or validates things. - `evaluation_v2_exclusions`: dropped the reference to the server-side validator by name (`parseEvaluationV2ExclusionRulesWithDiagnostics`) — a TypeScript function name has no business in the Python docs — and said what a caller can actually observe: invalid rules are reported with a reason instead of silently excluding nothing. - `_parse_json_field`: no longer describes JSONB columns, raw DB rows, or driver behaviour; it just normalizes a field that may arrive as a string. - `_parse_allowed_label_matches` / `_parse_rollup_groups`: made private and reworded off "the shapes the backend may return". They had public names, so autoapi would have published these internal parsers regardless of wording. - Reworded the leftover storage vocabulary in user-visible text: "row offset" → "offset", "one row of a ranking" → "one entry", "match rows" → "results". - CHANGELOG: "requires a scaleapi server with the REST leaderboard endpoints deployed" → "requires a Nucleus deployment with leaderboard support". The constraint is real and worth keeping; the internals aren't. pylint 10.00/10, mypy clean, ruff/black/isort clean, 59 tests passing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
| ExclusionScope = str # "item" | "annotation" | ||
| ExclusionTarget = str # "groundTruth" | "prediction" | ||
| MetadataOp = str # "EQ" | "IN" | "GT" | "LT" |
There was a problem hiding this comment.
Should these be Literals (or StrEnums) instead of bare strs?
| @classmethod | ||
| def from_json( | ||
| cls, | ||
| payload: Dict[str, Any], |
There was a problem hiding this comment.
I have a general curiosity question for myself, that I think is outside the scope of this PR:
Is there a reason payload is a dict instead of a type-validated object? I guess the access/assignment of payload attributes by string keys just seems a little unsafe/random to me lol
Relatedly, I see that there's this convention in Claude.MD to add payload keys to constants.py:
nucleus-python-client/CLAUDE.md
Line 41 in 49289ab
And that the *_KEY constants are used with the payload, for example here:
nucleus-python-client/nucleus/dataset_item.py
Lines 181 to 189 in 49289ab
Is there a reason to do/not do that? Like on lines 57-70 below, for example.
| ``"prediction_labels"`` (model prediction labels). | ||
| """ | ||
| return self._client.make_request( | ||
| {}, f"dataset/{self.id}/labelSchema", requests.get |
There was a problem hiding this comment.
kind of nit / probably also outside the scope of this PR to fix - is there a reason to not use the existing .get() from connection.py instead? I see that a lot of existing syntax here is make_request so it makes sense that it's used here as well though the rest of the PR uses the wrappers lol
Summary — v0.19.0: EvaluationV2, benchmark paradigm
Brings the SDK to parity with the Nucleus EvaluationV2 UI. Evaluation creation is benchmark-scoped only — dataset/slice-scoped creation (an unreleased earlier iteration of this branch) was removed before release as the platform moved to the benchmark paradigm.
Added
create_benchmark()(members fromitem_ids,(dataset_id, ref_id)itemspairs, aslice_id, or adataset_id— exactly one required; membership frozen at creation),list_benchmarks(),get_benchmark(),update_benchmark(),delete_benchmark(),list_benchmark_items(), plus theBenchmarkresource (refresh()/update()/delete()/items()/create_evaluation_v2()) innucleus/benchmark.py.create_benchmark_evaluation_v2(benchmark_id, model_run_id, ...)— every benchmark item is scored (uncovered items count as FN, keeping leaderboard scores comparable).EvaluationV2exposesbenchmark_id,rollup_groups,exclusion_rules,exclusion_stats. Noonly_items_with_predictions/ eval-scopeslice_id(invalid in the benchmark paradigm; the server rejects the former).RollupGroup(class_name+labels) as the primary label configuration on benchmark eval create and presets (create/update_evaluation_v2_preset(rollup_groups=...), mutually exclusive with legacyallowed_label_matches; parsed from both key casings). Preset seeding prefersrollup_groups, falling back to legacy matches.MetadataExclusionRule/LabelExclusionRule/BoxAreaExclusionRuleviaexclusion_ruleson eval create and presets.list/create/update/delete_evaluation_v2_preset+EvaluationV2Presetresource;preset=seeds benchmark eval creation (explicit args override).EvaluationV2.charts()(mAP, per-class AP, confusion matrix, PR/F1 curves, TIDE, AP by size) andexamples()(paginated TP/FP/FN;match_typeoptional) withEvaluationV2FilterArgsfiltering;cancel()/retry();Dataset.evaluation_label_schema().leaderboard_ranking(metric_type, benchmark_ids, ...)(metrics:MAP_50,MAP_50_95,AP_SMALL/MEDIUM/LARGE,PRECISION,RECALL,F1;scope/collapse) andleaderboard_f1_curve(benchmark_ids, ..., top_n=5).EvaluationV2.filter_schema()/get_evaluation_v2_filter_schema()return the evaluation's filter vocabulary (gt_labels,pred_labels,metadata_fieldswith inferred value types).EvaluationV2FilterSchema,LeaderboardRankingEntry,LeaderboardF1CurveEntry,BenchmarkItemsPage.Removed (relative to earlier commits on this branch — never released)
create_evaluation_v2(dataset/slice-scoped),create_evaluations_v2_batch,BatchEvaluationResult,only_items_with_predictions. Reading existing evals (including old slice-scoped ones) still works.Fixed
build_testpylint failure (pre-existingW0718on the per-job catch) — suppressed with a black-stable# pylint: disable-nextline.Tests / Version
tests/test_benchmarks.py,tests/test_leaderboard.py, plus rollup/benchmark coverage in the eval/preset test files (59 unit tests, mock-based).pyproject.toml→ 0.19.0; single consolidated CHANGELOG entry (the unreleased 0.18.9 section was folded in).resolves https://linear.app/scale-epd/issue/DE-8209
Greptile Summary
This PR brings the Nucleus Python SDK to parity with the EvaluationV2 UI under the benchmark paradigm. It introduces benchmarks (frozen item sets for evaluation), benchmark evaluations with rollup groups, exclusion rules, presets, leaderboard ranking, filter-schema discovery, and the
cancel/retrylifecycle actions.nucleus/benchmark.py,nucleus/evaluation_v2_exclusions.py,nucleus/evaluation_v2_preset.py— each fully tested with 59 mock-based unit tests.create_evaluation_v2(dataset/slice-scoped) is gone;create_benchmark_evaluation_v2viabenchmarks/{id}/evaluationsV2is the sole creation path.patch()method mirrors the existingpost()andget()helpers, used forupdate_evaluation_v2_presetandupdate_benchmark.Confidence Score: 5/5
Safe to merge — all new functionality is additive, the existing evaluation path is untouched, and the 59 mock-based unit tests cover the key creation, preset-seeding, and edge-case paths.
The benchmark and evaluation changes are well-structured and well-tested. The previous-thread concerns about camelCase parsing and preset-override ordering both appear addressed in the current code. The remaining findings are all minor quality or consistency issues that do not affect the correctness of any live API call.
Files Needing Attention: nucleus/evaluation_v2_preset.py (or-vs-is-not-None inconsistency in from_json) and nucleus/evaluation_v2_exclusions.py (BoxAreaExclusionRule missing bounds guard).
Important Files Changed
orfallback which silently discards empty-list responses.Sequence Diagram
sequenceDiagram participant U as User participant NC as NucleusClient participant API as Nucleus API U->>NC: "create_benchmark(name, slice_id=...)" NC->>API: POST /benchmarks API-->>NC: "{benchmark_id, ...}" NC-->>U: Benchmark U->>NC: "create_benchmark_evaluation_v2(benchmark_id, model_run_id, preset=preset)" Note over NC: Seed from preset if no explicit label config NC->>API: "POST /benchmarks/{id}/evaluationsV2" API-->>NC: "{evaluation_id}" NC->>API: "GET /evaluationsV2/{id}" API-->>NC: EvaluationV2 payload NC-->>U: EvaluationV2 U->>NC: evaluation.wait_for_completion() loop poll NC->>API: "GET /evaluationsV2/{id}" API-->>NC: "{status: ...}" end NC-->>U: EvaluationV2 (succeeded) U->>NC: "evaluation.charts(iou_threshold=0.5)" NC->>API: "POST /evaluationsV2/{id}/charts" API-->>NC: EvaluationV2Charts NC-->>U: EvaluationV2Charts U->>NC: leaderboard_ranking("MAP_50", [benchmark_id]) NC->>API: POST /leaderboard/ranking API-->>NC: "[{rank, score, ...}]" NC-->>U: List[LeaderboardRankingEntry]Reviews (8): Last reviewed commit: "Make the eval/benchmark docstrings user-..." | Re-trigger Greptile