发布

  • [OPIK-6964] [SDK] [DOCS] feat: scope opik export/import to a project (v2) (#7145)

    frostbyte_neo 发布于 2026-06-23 12:48:42 +00:00

    • [NA] [SDK] [DOCS] feat: scope opik export/import to a project (v2)

    Move the opik export and opik import CLI commands to the Opik v2 model
    where every dataset, prompt, and experiment belongs to a project. Project is
    now a required positional (opik export WORKSPACE PROJECT ITEM), the on-disk
    layout is project-nested (projects//{datasets,prompts,experiments}
    plus traces), project_name is always threaded into the REST/SDK calls, and
    the v1 project-less code paths (Default Project fallbacks, per-trace project
    resolution) are removed. The old project item is renamed to traces.

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • [NA] [SDK] [DOCS] refactor: key export/import layout by ID, resolve names via project.json

    On-disk export artifacts are now named by ID instead of human names:
    projects/<project_id>/ with a project.json ({id, name}), and id-named
    dataset_.json / prompt_.json / experiment_.json / trace_.json.
    This removes the '/', ':' and whitespace problems of name-based paths (e.g. a
    project named "scout:comet-ml/opik"). Human names are stored as data inside the
    files. The CLI still takes project/item names; export resolves name->id and
    import resolves a project name back to its id-folder by scanning project.json.
    Adds --to-project to redirect the destination project on import.

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • [NA] [SDK] [DOCS] fix: make import --path symmetric with export (workspace segment)

    Import now resolves //projects// — the same layout export
    writes — instead of /projects//. This removes the asymmetry that
    forced users to pass --path <export-path>/<workspace> on import: the same
    --path (including the default opik_exports) now round-trips between export and
    import. Updated unit/e2e tests and docs accordingly.

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • [NA] [SDK] refactor: drop older-export 'input' fallback in dataset item mapping

    import/export targets Opik v2 project-specified data only — no backwards
    compatibility. Remove the item_data.get("input") fallback that tolerated
    pre-dataset_item_data export files when building the dataset-item id map.

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • [NA] [SDK] [DOCS] feat: support cross-workspace import via base-path fallback

    Import now resolves the source folder at //projects/ (symmetric
    with export, so the same --path round-trips within a workspace) and falls back to
    /projects/ when that workspace segment is absent. This enables importing
    into a different workspace than the data was exported from: point --path at the
    exported workspace directory. Adds resolve_import_base_path() + unit tests and a
    docs note.

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • [NA] [DOCS] docs: rename export/import positional TYPE -> ITEM to match CLI

    The CLI's positional after PROJECT is ITEM (subcommand metavar "ITEM [ARGS]...",
    "Missing ITEM" error, usage "WORKSPACE PROJECT ITEM [NAME]"). Align both docs to
    ITEM so users don't confuse it with a "type" field.

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • [NA] [SDK] fix: import exits non-zero when items fail to import

    Previously opik import reported per-item failures only as a warning and exited
    0, masking errors (e.g. invalid trace JSON, or the whole-directory failure path
    that reports under projects_errors). Both _import_by_type and import_all now
    sum every *_errors counter across all phases and exit 1 when any are present,
    so failures surface with a non-zero exit code. Adds a regression test.

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • [NA] [SDK] [DOCS] refactor: address PR review — harden project.json read, dedup import lookup, docs note
    • imports/utils._read_project_metadata_name: guard against non-object JSON and
      non-string "name" so a malformed project.json can't crash project discovery.
    • Extract resolve_import_project_root(path, workspace, project_name, to_project)
      shared by import_all and _import_by_type so the source lookup + not-found
      messaging + destination resolution stay in one place.
    • docs: add the "maintained by hand" maintenance note to the Example Workflow
      (covers the pandas CSV snippet).

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • [NA] [SDK] fix: don't mark import manifest complete on partial failure; count recreated-experiment errors

    Addresses PR review (manifest/error-handling):

    • Compute total_errors before manifest.complete() in both _import_by_type and
      import_all, and only complete() when total_errors == 0. A partial failure now
      leaves the manifest in_progress so a non---force rerun resumes/retries instead
      of short-circuiting on manifest.is_completed.
    • recreate_experiments() now returns (successful, failed); import_traces_from_directory
      surfaces experiments/experiments_errors in its stats so traces imports that
      recreate experiments don't exit 0 on a partial failure.
    • Add regression test that a failed import leaves the manifest incomplete.

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • [NA] [SDK] test: verify failed-import retryability via public behavior; fix comment typo

    Address PR review nits:

    • Rewrite the manifest-incomplete-on-failure test to assert observable behavior
      (a rerun without --force re-invokes the importer) instead of poking the
      internal MigrationManifest.is_completed, per .agents/skills/python-sdk/testing.md.
    • Fix a "non---force" typo in an imports/__init__.py comment.

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • [NA] [SDK] refactor: extract shared finalize_import() for import flush/complete

    Both _import_by_type and import_all ran identical flush + failed-upload checks
    and the total_errors==0 gate on manifest.complete(). Extract that into
    imports/utils.finalize_import(manifest, client, total_errors, dry_run) so
    resume/manifest behavior stays in one place (the per-type vs. aggregate summary
    messaging remains in each caller). No behavior change.

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • [NA] [SDK] [DOCS] fix: per-destination import manifest; address review

    Addresses JetoPistola review:

    • BLOCKER: the resume/completion manifest was keyed only to the source folder,
      so importing one export into different --to-project targets shared one manifest
      (a clean import into A made a later import into B short-circuit on
      "already completed"; a partial import into A would resume into B). The manifest
      is now keyed by destination via destination_manifest_dir(project_root, dest)
      (hashed, names may contain / :). Regression test: import into A then B both run.
    • Switch the import prompt path to client.create_prompt()/create_chat_prompt()
      instead of the deprecated opik.Prompt()/ChatPrompt() constructors.
    • Warn in find_project_export_dir when >1 exported folder records the same
      project name (ambiguous resolution).
    • Docs: manifest now lives under projects//import_manifests//.

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • [NA] [SDK] fix: keep migration manifest keyed to project_root; extract setup_import_manifest

    Fixes a regression from the per-destination manifest change: passing the
    per-destination subdir as MigrationManifest.base_path made file keys resolve
    relative_to() that subdir, but exported files live under project_root/... — so
    mark_file_completed()/is_file_completed() raised ValueError and broke resume
    tracking (mocked unit tests didn't catch it; live import would).

    • MigrationManifest gains an optional manifest_path so the SQLite file can live
      in the per-destination subdir while base_path stays project_root (the key root
      for relative file paths). mkdir the manifest file's parent, not base_path.
    • Extract setup_import_manifest(project_root, dest, dry_run, force) — used by
      both import_all and _import_by_type — which builds the manifest correctly and
      runs the start/resume/force lifecycle, returning (manifest, already_completed).
      This also dedups the manifest-lifecycle block flagged in review.
    • Add a regression test that files under project_root are keyable while the db
      lives in the per-destination subdir.

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • [NA] [SDK] fix: --force no longer resets a non-existent manifest; rename tests to convention

    Address PR review:

    • setup_import_manifest captured manifest existence AFTER constructing
      MigrationManifest, which creates the SQLite file — so a first --force run saw
      exists()==True and warned/reset against a manifest that never existed. Capture
      existence before construction. Tests cover both fresh-force (no warn/reset) and
      force-with-existing (warn/reset).
    • Rename the two new manifest tests to the required
      test_WHAT__CASE__EXPECTED_RESULT format.

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • test(cli): scope export/import e2e verification reads to the project

    The datasets/prompts/chat-prompts happy-flow e2e tests created data with
    project_name=source_project_name but verified it via project-less
    get_datasets()/search_prompts()/get_chat_prompt(), which resolve to the
    client's default project. The default project is never created, so
    get_datasets 404'd and search_prompts returned nothing — three failures
    in CI. Scope the verification reads to source_project_name to match the
    v2 project-scoped model the rest of the test already uses.

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com


    Co-authored-by: Douglas Blank doug@comet.com
    Co-authored-by: Claude Opus 4.8 (1M context) noreply@anthropic.com
    Co-authored-by: Alexander Kuzmik alexander.kuzmik99@gmail.com

    下载附件