openrunner-sdk 2.41.4__tar.gz → 2.41.6__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.
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/PKG-INFO +1 -1
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/CLAUDE.md +27 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/__init__.py +7 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/_native.py +4 -2
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/datasets.py +213 -3
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/install_commands.py +42 -2
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/pyproject.toml +1 -1
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_datasets_module.py +179 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/.gitignore +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/=6.0 +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/=8.1 +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/README.md +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/_retry_transport.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/_safepath.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/_secret_rules.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/api_client.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/artifact.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/autoresearch.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/buffer.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/cache.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/cli.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/config.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/cost.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/dataset.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/environment.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/evaluation.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/feedback.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/git_info.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/__init__.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/api_integration.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/cost_guard.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/gpu_types.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/price_compare.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/provider_base.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/providers/__init__.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/providers/forge_provider.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/providers/lambda_cloud.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/providers/modal_provider.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/providers/ovhcloud.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/providers/runpod.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/providers/vastai.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/runner.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/workspace_sync.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/guardrails.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/handover.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/hooks/patent-lab-post-commit +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/__init__.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/accelerate.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/anthropic_tracer.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/catboost.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/diffusers.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/fastai.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/forced_alignment.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/gladia.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/gymnasium.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/huggingface.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/hydra.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/ignite.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/jax.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/keras.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/langchain.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/lightgbm.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/lightning.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/llamaindex.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/openai_finetune.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/openai_tracer.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/optuna.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/pytorch.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/sb3.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/sklearn.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/skypilot.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/tensorflow.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/trl.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/tts.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/ultralytics.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/voice_agent.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/whisper.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/xgboost.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/launch.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/machine.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/mcp_server.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/media.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/migrate.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/model.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/model_card.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/offline.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/patent_scan.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/pii.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/plot.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/projects.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/prompt.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/query_api.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/redact.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/reload.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/research.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/research_policy.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/run.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/scorers.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/sender.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/session.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/settings.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/summary.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/sweep.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/sync.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/system_metrics.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/tensorboard.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/tools/__init__.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/tools/patent_report.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/trace.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/transcript_formatter.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/wal.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/wandb_compat/__init__.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/wandb_compat/_shim.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/wer.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/scripts/gen_betterleaks_rules.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/__init__.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/conftest.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-aaa/config.json +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-aaa/metadata.json +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-aaa/metrics.jsonl +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-aaa/summary.json +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/model-checkpoint/manifest.json +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/model-checkpoint/weights.bin +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/sample-image/manifest.json +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/sample-image/preview.png +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-bbb/config.json +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-bbb/metadata.json +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-bbb/metrics.jsonl +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-bbb/summary.json +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/integration/__init__.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/integration/conftest.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/integration/test_artifact_round_trip.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_alert.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_aliases.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_api_client.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_api_client_methods.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_api_client_transport.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_artifact.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_buffer.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_cache.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_class_scorers.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_cli.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_cli_artifact_sweep.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_cli_datasets.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_cli_gpu_registry_deploy.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_cli_infra.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_cli_remainder.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_cli_topup.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_config.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_evaluation.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_finish.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_git_info.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/__init__.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/conftest.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_cost_guard.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_engine_serverside.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_forge.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_governed_jobs.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_gpu_cluster.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_gpu_types.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_lambda.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_modal.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_ovh_training.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_ovhcloud.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_price_compare.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_provider_base.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_runner.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_runpod.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_sdk_gpu_api.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_vastai.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_workspace_sync.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu_modal_creds.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_init.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_init_facade.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_install_commands.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_fastai.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_huggingface.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_keras.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_langchain.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_lightning.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_pytorch.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_setA.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_setB.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_setC.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_sklearn.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_xgboost.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_launch.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_log.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_log_code.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_machine_migrate.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_mcp_decisions.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_mcp_monitor.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_mcp_predictions.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_mcp_server.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_media.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_media_extra.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_migrate.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_offline.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_offline_sync.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_patent_scan.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_pii.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_plot.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_plot_media_extra2.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_prompt_module.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_pure_modules.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_query_api.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_redact.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_reload_module.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_research_module.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_resume.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_retry_transport.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_run_module.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_sdk_cluster_j1.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_sdk_cluster_j2.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_sdk_cluster_j3.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_sdk_cluster_j4.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_sdk_core_edges.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_sdk_features.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_sender.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_session_module.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_session_sync.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_summary.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_sweep.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_system_metrics.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_topup_hi.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_trace.py +0 -0
- {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_wandb_compat.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openrunner-sdk
|
|
3
|
-
Version: 2.41.
|
|
3
|
+
Version: 2.41.6
|
|
4
4
|
Summary: OpenRunner SDK - W&B-compatible ML experiment tracking client
|
|
5
5
|
Project-URL: Homepage, https://github.com/jqueguiner/openrunner
|
|
6
6
|
Project-URL: Repository, https://github.com/jqueguiner/openrunner
|
|
@@ -84,6 +84,33 @@ CLI: `openrunner datasets index org/name --text-col en --text-col fr`,
|
|
|
84
84
|
combined `_text` column so one query spans all text fields; preview/search read
|
|
85
85
|
the LanceDB table on the dataset's own connection.
|
|
86
86
|
|
|
87
|
+
### Search modes + query-derived datasets
|
|
88
|
+
|
|
89
|
+
Beyond FTS, the client exposes semantic / lexical search and **derivation by
|
|
90
|
+
query** — build a child dataset from a SUBSET of a parent selected by a search
|
|
91
|
+
(only matching primary keys stored; no media copied; de-dup + lineage automatic).
|
|
92
|
+
These delegate to the native Rust core (`openrunner-core` wheel) when installed,
|
|
93
|
+
falling back to pure-Python httpx otherwise:
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
ord.search_dataset(repo, q, mode="mixed"|"exact", lang="fr") # BM25 / phrase, lang filter
|
|
97
|
+
ord.optimize_embedding_search(repo) # build ANN index (once)
|
|
98
|
+
ord.semantic_search(repo, q, lang="en,fr") # vector (cosine) search
|
|
99
|
+
ord.regex_search(repo, r"\bcancel(led)?\b", lang="en") # Python-re over the text column (bounded)
|
|
100
|
+
ord.word_lookup(repo, "medical,doctor", op="union"|"intersect", lang="fr") # lexical_map
|
|
101
|
+
ord.keyword_expand("medical terms in french", count=300) # LLM -> {keywords, csv, count}
|
|
102
|
+
|
|
103
|
+
# derive: mode = word (op union/intersect) | fts | exact | regex | semantic; lang filter; append via target_repo_id
|
|
104
|
+
child = ord.derive_by_query(parent, keywords_csv, name="org/medical-fr",
|
|
105
|
+
mode="word", lang="fr", limit=5000)
|
|
106
|
+
ord.derive_by_query(parent, "more,terms", target_repo_id="org/medical-fr", mode="word") # append, de-dup
|
|
107
|
+
ord.derived_rows("org/medical-fr", limit=50) # member keys + inherited parent fields
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
`word`+`op="union"` = rows matching ANY term; `op="intersect"` (via `word_lookup`)
|
|
111
|
+
= rows matching ALL. `semantic` needs `optimize_embedding_search` first. Slash
|
|
112
|
+
command: `/openrunner:derive-dataset` (query-derivation **or** computed-column).
|
|
113
|
+
|
|
87
114
|
# OpenRunner MCP Integration
|
|
88
115
|
|
|
89
116
|
When the user publishes a MODEL, or asks to write/update a model card:
|
|
@@ -101,8 +101,15 @@ from openrunner.datasets import (
|
|
|
101
101
|
link_project,
|
|
102
102
|
load_dataset,
|
|
103
103
|
add_derivation,
|
|
104
|
+
derive_by_query,
|
|
105
|
+
derived_rows,
|
|
106
|
+
keyword_expand,
|
|
107
|
+
optimize_embedding_search,
|
|
104
108
|
push_dataset,
|
|
105
109
|
search_dataset,
|
|
110
|
+
regex_search,
|
|
111
|
+
semantic_search,
|
|
112
|
+
word_lookup,
|
|
106
113
|
set_dataset_card,
|
|
107
114
|
set_storage_policy,
|
|
108
115
|
upload_file,
|
|
@@ -9,8 +9,10 @@ single-implementation point, never a hard dependency.
|
|
|
9
9
|
|
|
10
10
|
Covered surface today: projects (incl. linked repo), artifacts/versions,
|
|
11
11
|
presigned downloads (selective, GIL released during transfers), container
|
|
12
|
-
registries + broker login tokens,
|
|
13
|
-
(add column / set cell / edit row / get row — source columns stay read-only)
|
|
12
|
+
registries + broker login tokens, dataset editable-overlay columns
|
|
13
|
+
(add column / set cell / edit row / get row — source columns stay read-only),
|
|
14
|
+
and dataset search + query-derivation (full-text / semantic / regex / word
|
|
15
|
+
union·intersect, LLM keyword-expand, derive-by-query + derived rows).
|
|
14
16
|
"""
|
|
15
17
|
|
|
16
18
|
from __future__ import annotations
|
|
@@ -746,13 +746,188 @@ class DatasetsClient:
|
|
|
746
746
|
_check(r)
|
|
747
747
|
return r.json()
|
|
748
748
|
|
|
749
|
-
def search_dataset(
|
|
750
|
-
|
|
749
|
+
def search_dataset(
|
|
750
|
+
self,
|
|
751
|
+
repo_id: str,
|
|
752
|
+
query: str,
|
|
753
|
+
*,
|
|
754
|
+
limit: int = 20,
|
|
755
|
+
mode: str = "mixed",
|
|
756
|
+
lang: str = "",
|
|
757
|
+
) -> list[dict]:
|
|
758
|
+
"""Full-text search a dataset's index. Call ``index_dataset`` first.
|
|
759
|
+
|
|
760
|
+
``mode``: "mixed" (ranked tokens, default) or "exact" (phrase match).
|
|
761
|
+
``lang``: restrict to a language / CSV ("fr" or "fr,en"); "" = all.
|
|
762
|
+
Delegates to the native (Rust) core when the ``openrunner-core`` wheel is
|
|
763
|
+
installed, else pure-Python httpx.
|
|
764
|
+
"""
|
|
751
765
|
ds = self._resolve(repo_id)
|
|
752
|
-
|
|
766
|
+
nat = self._native_client()
|
|
767
|
+
if nat is not None:
|
|
768
|
+
return nat.dataset_search(str(ds.id), query, mode, lang, limit).get("rows", [])
|
|
769
|
+
params: dict[str, Any] = {"q": query, "limit": limit, "mode": mode}
|
|
770
|
+
if lang:
|
|
771
|
+
params["lang"] = lang
|
|
772
|
+
r = self._http.get(f"/datasets/{ds.id}/search", params=params)
|
|
753
773
|
_check(r)
|
|
754
774
|
return r.json().get("rows", [])
|
|
755
775
|
|
|
776
|
+
# -- semantic / lexical / query-derivation -------------------------------
|
|
777
|
+
def semantic_search(
|
|
778
|
+
self, repo_id: str, query: str, *, limit: int = 20, lang: str = ""
|
|
779
|
+
) -> list[dict]:
|
|
780
|
+
"""Vector (cosine ANN) search over a dataset's embeddings.
|
|
781
|
+
|
|
782
|
+
Requires the embedding index built first via
|
|
783
|
+
``optimize_embedding_search``. Native core when available, else httpx.
|
|
784
|
+
"""
|
|
785
|
+
ds = self._resolve(repo_id)
|
|
786
|
+
nat = self._native_client()
|
|
787
|
+
if nat is not None:
|
|
788
|
+
out = nat.semantic_search(str(ds.id), query, lang, limit)
|
|
789
|
+
return out.get("rows", out.get("hits", []))
|
|
790
|
+
params: dict[str, Any] = {"q": query, "limit": limit}
|
|
791
|
+
if lang:
|
|
792
|
+
params["lang"] = lang
|
|
793
|
+
r = self._http.get(f"/datasets/{ds.id}/semantic", params=params)
|
|
794
|
+
_check(r)
|
|
795
|
+
return r.json().get("rows", r.json().get("hits", []))
|
|
796
|
+
|
|
797
|
+
def regex_search(
|
|
798
|
+
self, repo_id: str, pattern: str, *, limit: int = 20, lang: str = ""
|
|
799
|
+
) -> list[dict]:
|
|
800
|
+
"""Regex search: match a Python-``re`` ``pattern`` against the dataset's
|
|
801
|
+
text column (streamed, bounded — no index needed). Case-insensitive is
|
|
802
|
+
opt-in via an inline ``(?i)`` flag. Native core when available, else httpx.
|
|
803
|
+
Pairs with ``derive_by_query(mode="regex")`` to build a regex-derived set.
|
|
804
|
+
"""
|
|
805
|
+
ds = self._resolve(repo_id)
|
|
806
|
+
nat = self._native_client()
|
|
807
|
+
if nat is not None:
|
|
808
|
+
return nat.regex_search(str(ds.id), pattern, lang, limit).get("rows", [])
|
|
809
|
+
params: dict[str, Any] = {"q": pattern, "limit": limit, "mode": "regex"}
|
|
810
|
+
if lang:
|
|
811
|
+
params["lang"] = lang
|
|
812
|
+
r = self._http.get(f"/datasets/{ds.id}/search", params=params)
|
|
813
|
+
_check(r)
|
|
814
|
+
return r.json().get("rows", [])
|
|
815
|
+
|
|
816
|
+
def optimize_embedding_search(
|
|
817
|
+
self,
|
|
818
|
+
repo_id: str,
|
|
819
|
+
*,
|
|
820
|
+
text_column: str | None = None,
|
|
821
|
+
max_rows: int = 200000,
|
|
822
|
+
model: str | None = None,
|
|
823
|
+
) -> dict:
|
|
824
|
+
"""Embed missing rows and build the ANN index that ``semantic_search``
|
|
825
|
+
(and derive ``mode="semantic"``) need. Native core when available."""
|
|
826
|
+
ds = self._resolve(repo_id)
|
|
827
|
+
nat = self._native_client()
|
|
828
|
+
if nat is not None:
|
|
829
|
+
return nat.optimize_embedding_search(str(ds.id), text_column, max_rows, model)
|
|
830
|
+
body = {"text_column": text_column, "max_rows": max_rows, "model": model}
|
|
831
|
+
r = self._http.post(
|
|
832
|
+
f"/datasets/{ds.id}/optimize-embedding-search", json=body, timeout=1800.0
|
|
833
|
+
)
|
|
834
|
+
_check(r)
|
|
835
|
+
return r.json()
|
|
836
|
+
|
|
837
|
+
def word_lookup(
|
|
838
|
+
self, repo_id: str, terms: str | list[str], *, op: str = "union", lang: str = ""
|
|
839
|
+
) -> dict:
|
|
840
|
+
"""Word(s) -> matching-row lookup via the ``lexical_map`` table.
|
|
841
|
+
|
|
842
|
+
``terms`` is one word, a CSV string, or a list. ``op`` combines
|
|
843
|
+
multi-term hits: "union" (ANY) or "intersect" (ALL). ``lang`` scopes to a
|
|
844
|
+
language / CSV. Returns per-term df + combined ids. Native core when
|
|
845
|
+
available, else httpx.
|
|
846
|
+
"""
|
|
847
|
+
ds = self._resolve(repo_id)
|
|
848
|
+
term = ",".join(terms) if isinstance(terms, (list, tuple)) else terms
|
|
849
|
+
nat = self._native_client()
|
|
850
|
+
if nat is not None:
|
|
851
|
+
return nat.word_lookup(str(ds.id), term, op, lang)
|
|
852
|
+
params: dict[str, Any] = {"term": term, "op": op}
|
|
853
|
+
if lang:
|
|
854
|
+
params["lang"] = lang
|
|
855
|
+
r = self._http.get(f"/datasets/{ds.id}/word-lookup", params=params)
|
|
856
|
+
_check(r)
|
|
857
|
+
return r.json()
|
|
858
|
+
|
|
859
|
+
def keyword_expand(
|
|
860
|
+
self, prompt: str, *, count: int = 500, model: str | None = None
|
|
861
|
+
) -> dict:
|
|
862
|
+
"""Expand a domain prompt into many search keywords via an LLM.
|
|
863
|
+
|
|
864
|
+
Returns ``{keywords, csv, count, model, prompt}`` — feed ``csv`` into
|
|
865
|
+
``word_lookup`` or ``derive_by_query(mode="word", q=csv)``. Native core
|
|
866
|
+
when available, else httpx.
|
|
867
|
+
"""
|
|
868
|
+
nat = self._native_client()
|
|
869
|
+
if nat is not None:
|
|
870
|
+
return nat.keyword_expand(prompt, count, model)
|
|
871
|
+
body = {"prompt": prompt, "count": count, "model": model}
|
|
872
|
+
r = self._http.post("/datasets/keyword-expand", json=body, timeout=120.0)
|
|
873
|
+
_check(r)
|
|
874
|
+
return r.json()
|
|
875
|
+
|
|
876
|
+
def derive_by_query(
|
|
877
|
+
self,
|
|
878
|
+
repo_id: str,
|
|
879
|
+
q: str,
|
|
880
|
+
*,
|
|
881
|
+
name: str | None = None,
|
|
882
|
+
mode: str = "semantic",
|
|
883
|
+
lang: str | None = None,
|
|
884
|
+
limit: int = 2000,
|
|
885
|
+
target_repo_id: str | None = None,
|
|
886
|
+
project_id: str | None = None,
|
|
887
|
+
) -> DatasetInfo:
|
|
888
|
+
"""Create (or append to) a dataset **derived from a query** over ``repo_id``.
|
|
889
|
+
|
|
890
|
+
``mode``: "word" (``q`` = term / CSV; pairs with LLM ``keyword_expand``),
|
|
891
|
+
"fts" (BM25), "exact" (phrase), "regex" (``q`` = a Python-``re`` pattern
|
|
892
|
+
matched over the text column, bounded), "semantic" (vector — needs
|
|
893
|
+
``optimize_embedding_search``). ``lang`` filters by language / CSV. Pass
|
|
894
|
+
``name`` to create, or ``target_repo_id`` to append (must derive from the
|
|
895
|
+
same parent). Lineage is recorded automatically. The query runs and
|
|
896
|
+
member keys are recorded natively when the core wheel is installed; the
|
|
897
|
+
parent/target resolution + DatasetInfo wrapping stay in Python.
|
|
898
|
+
"""
|
|
899
|
+
ds = self._resolve(repo_id)
|
|
900
|
+
body: dict[str, Any] = {"mode": mode, "q": q, "limit": limit}
|
|
901
|
+
if name:
|
|
902
|
+
body["name"] = name
|
|
903
|
+
if lang:
|
|
904
|
+
body["lang"] = lang
|
|
905
|
+
if project_id:
|
|
906
|
+
body["project_id"] = str(project_id)
|
|
907
|
+
if target_repo_id:
|
|
908
|
+
body["target_dataset_id"] = str(self._resolve(target_repo_id).id)
|
|
909
|
+
elif not name:
|
|
910
|
+
raise ValueError("derive_by_query needs either name= (create) or target_repo_id= (append)")
|
|
911
|
+
nat = self._native_client()
|
|
912
|
+
if nat is not None:
|
|
913
|
+
return DatasetInfo._from_json(nat.derive_dataset(str(ds.id), body))
|
|
914
|
+
r = self._http.post(f"/datasets/{ds.id}/derive", json=body, timeout=600.0)
|
|
915
|
+
_check(r)
|
|
916
|
+
return DatasetInfo._from_json(r.json())
|
|
917
|
+
|
|
918
|
+
def derived_rows(self, repo_id: str, *, limit: int = 50, offset: int = 0) -> dict:
|
|
919
|
+
"""Page a query-derived dataset's rows: member keys + inherited parent
|
|
920
|
+
fields (lineage-namespaced) + extra columns. Native core when available."""
|
|
921
|
+
ds = self._resolve(repo_id)
|
|
922
|
+
nat = self._native_client()
|
|
923
|
+
if nat is not None:
|
|
924
|
+
return nat.derived_rows(str(ds.id), limit, offset)
|
|
925
|
+
r = self._http.get(
|
|
926
|
+
f"/datasets/{ds.id}/derived-rows", params={"limit": limit, "offset": offset}
|
|
927
|
+
)
|
|
928
|
+
_check(r)
|
|
929
|
+
return r.json()
|
|
930
|
+
|
|
756
931
|
def update_dataset(self, repo_id: str, **fields: Any) -> DatasetInfo:
|
|
757
932
|
ds = self._resolve(repo_id)
|
|
758
933
|
if "card" in fields:
|
|
@@ -1132,6 +1307,41 @@ def search_dataset(repo_id: str, query: str, **kwargs: Any) -> list[dict]:
|
|
|
1132
1307
|
return _c().search_dataset(repo_id, query, **kwargs)
|
|
1133
1308
|
|
|
1134
1309
|
|
|
1310
|
+
def semantic_search(repo_id: str, query: str, **kwargs: Any) -> list[dict]:
|
|
1311
|
+
"""Vector (cosine ANN) search — needs ``optimize_embedding_search`` first."""
|
|
1312
|
+
return _c().semantic_search(repo_id, query, **kwargs)
|
|
1313
|
+
|
|
1314
|
+
|
|
1315
|
+
def regex_search(repo_id: str, pattern: str, **kwargs: Any) -> list[dict]:
|
|
1316
|
+
"""Regex search — Python-``re`` ``pattern`` over the text column (bounded)."""
|
|
1317
|
+
return _c().regex_search(repo_id, pattern, **kwargs)
|
|
1318
|
+
|
|
1319
|
+
|
|
1320
|
+
def optimize_embedding_search(repo_id: str, **kwargs: Any) -> dict:
|
|
1321
|
+
"""Embed rows + build the ANN index for semantic search / semantic-derive."""
|
|
1322
|
+
return _c().optimize_embedding_search(repo_id, **kwargs)
|
|
1323
|
+
|
|
1324
|
+
|
|
1325
|
+
def word_lookup(repo_id: str, terms: "str | list[str]", **kwargs: Any) -> dict:
|
|
1326
|
+
"""Word(s) -> rows via lexical_map; ``op`` union|intersect, ``lang`` filter."""
|
|
1327
|
+
return _c().word_lookup(repo_id, terms, **kwargs)
|
|
1328
|
+
|
|
1329
|
+
|
|
1330
|
+
def keyword_expand(prompt: str, **kwargs: Any) -> dict:
|
|
1331
|
+
"""LLM-expand a domain prompt into search keywords ({keywords, csv, count})."""
|
|
1332
|
+
return _c().keyword_expand(prompt, **kwargs)
|
|
1333
|
+
|
|
1334
|
+
|
|
1335
|
+
def derive_by_query(repo_id: str, q: str, **kwargs: Any) -> "DatasetInfo":
|
|
1336
|
+
"""Create/append a dataset derived from a word|fts|exact|semantic query."""
|
|
1337
|
+
return _c().derive_by_query(repo_id, q, **kwargs)
|
|
1338
|
+
|
|
1339
|
+
|
|
1340
|
+
def derived_rows(repo_id: str, **kwargs: Any) -> dict:
|
|
1341
|
+
"""Page a query-derived dataset's rows (member keys + inherited parent fields)."""
|
|
1342
|
+
return _c().derived_rows(repo_id, **kwargs)
|
|
1343
|
+
|
|
1344
|
+
|
|
1135
1345
|
def set_storage_policy(repo_id: str, tier: str) -> dict:
|
|
1136
1346
|
return _c().set_storage_policy(repo_id, tier)
|
|
1137
1347
|
|
|
@@ -2135,14 +2135,54 @@ Give the dataset **URL** (`<base>/datasets/<id>`), the modality/tasks/languages,
|
|
|
2135
2135
|
|
|
2136
2136
|
DERIVE_DATASET_CMD = """---
|
|
2137
2137
|
name: {prefix}derive-dataset
|
|
2138
|
-
description: Derive a dataset from an existing one by
|
|
2139
|
-
argument-hint: "[parent org/name] [child org/name] [--column NAME]"
|
|
2138
|
+
description: Derive a dataset from an existing one — either by a SEARCH QUERY (semantic / regex / word union·intersect / fts / exact, with language filter + LLM keyword expansion) or by adding a computed column. Keeps lineage, never re-uploads the parent's media.
|
|
2139
|
+
argument-hint: "[parent org/name] [child org/name] [--query ... | --column NAME]"
|
|
2140
2140
|
allowed-tools:
|
|
2141
2141
|
- Bash
|
|
2142
2142
|
- Read
|
|
2143
2143
|
- AskUserQuestion
|
|
2144
2144
|
---
|
|
2145
2145
|
|
|
2146
|
+
Two ways to derive a NEW dataset from a parent, both lineage-tracked and media-free:
|
|
2147
|
+
|
|
2148
|
+
- **A. Query-derivation** — select a SUBSET of the parent's rows by a search: `semantic`, `word` (term list, UNION or INTERSECT), `fts` (BM25), or `exact` (phrase), with an optional **language filter** and optional **LLM keyword expansion**. Only matching primary keys are stored — no rows/media copied, de-dup automatic. Use when the user says "make a dataset of the medical/french/... clips", "everything matching X", "semantically similar to X".
|
|
2149
|
+
- **B. Computed-column** — add one or more computed columns (e.g. a heuristic `suspicious` GT-quality flag) keyed 1:1 to the parent rows.
|
|
2150
|
+
|
|
2151
|
+
Pick by intent: **subset/select rows -> A**; **annotate/flag rows -> B**.
|
|
2152
|
+
|
|
2153
|
+
---
|
|
2154
|
+
|
|
2155
|
+
## A. Query-derivation (semantic / regex / word union·intersect / fts / exact + lang + LLM keywords)
|
|
2156
|
+
|
|
2157
|
+
All server-side; the SDK delegates to the native Rust core when installed. `PARENT` must be indexed (`ds.index_dataset(...)`; for `semantic`, also `ds.optimize_embedding_search(...)`).
|
|
2158
|
+
|
|
2159
|
+
```bash
|
|
2160
|
+
python3 -c "
|
|
2161
|
+
from openrunner import datasets as ds
|
|
2162
|
+
|
|
2163
|
+
kw = ds.keyword_expand('medical terms in french', count=300) # {{keywords, csv, count}}
|
|
2164
|
+
child = ds.derive_by_query('ORG/PARENT', kw['csv'],
|
|
2165
|
+
name='ORG/medical-fr', mode='word', lang='fr', limit=5000) # WORD union + lang filter
|
|
2166
|
+
print('created', child.name, child.id)
|
|
2167
|
+
|
|
2168
|
+
hit = ds.word_lookup('ORG/PARENT', 'medical,doctor,prescription', op='intersect', lang='fr') # ALL terms
|
|
2169
|
+
|
|
2170
|
+
ds.optimize_embedding_search('ORG/PARENT') # build ANN index once
|
|
2171
|
+
ds.derive_by_query('ORG/PARENT', 'patient describing symptoms',
|
|
2172
|
+
name='ORG/symptom-desc', mode='semantic', lang='en,fr') # SEMANTIC
|
|
2173
|
+
|
|
2174
|
+
ds.derive_by_query('ORG/PARENT', 'insurance claim', name='ORG/claims', mode='fts') # BM25
|
|
2175
|
+
ds.derive_by_query('ORG/PARENT', 'pharmacy,pharmacist', target_repo_id='ORG/medical-fr', mode='word') # append, de-dup
|
|
2176
|
+
print(ds.derived_rows('ORG/medical-fr', limit=10))
|
|
2177
|
+
"
|
|
2178
|
+
```
|
|
2179
|
+
|
|
2180
|
+
Query modes (`mode=`): `word` (CSV of terms; `op='union'|'intersect'`), `fts` (BM25), `exact` (phrase), `regex` (a Python-`re` pattern over the text column, e.g. `ds.regex_search('ORG/PARENT', r'\\bcancel(led)?\\b')` / `ds.derive_by_query('ORG/PARENT', r'\\brefund', name='ORG/refunds', mode='regex')`), `semantic` (vector ANN). `lang=` takes a language or CSV ("fr" / "en,fr"); "" = all. Lineage to `PARENT` is recorded automatically by `derive_by_query`.
|
|
2181
|
+
|
|
2182
|
+
---
|
|
2183
|
+
|
|
2184
|
+
## B. Computed-column derivation
|
|
2185
|
+
|
|
2146
2186
|
Derive a NEW dataset from an existing parent by adding one or more **computed columns** (e.g. a heuristic `suspicious` GT-quality flag), preserving lineage.
|
|
2147
2187
|
|
|
2148
2188
|
**Datasets are first-class — do NOT use `openrunner.Artifact` for this.** An Artifact is a model/file blob attached to a run; a dataset is a governed, queryable, lineage-tracked entity. Deriving = a child dataset linked to its parent via `add_derivation`, so the platform shows the lineage graph and **blocks deleting the parent while children exist**.
|
|
@@ -684,11 +684,155 @@ def test_index_dataset_truncated_warns(monkeypatch):
|
|
|
684
684
|
|
|
685
685
|
def test_search_dataset(monkeypatch):
|
|
686
686
|
c = _client(monkeypatch)
|
|
687
|
+
c._native = None # force httpx fallback (no native wheel)
|
|
687
688
|
c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
|
|
688
689
|
c._http.get.return_value = _resp(200, {"rows": [{"id": 1}]})
|
|
689
690
|
assert c.search_dataset("gladia/wmt", "hi") == [{"id": 1}]
|
|
690
691
|
|
|
691
692
|
|
|
693
|
+
def test_search_dataset_mode_and_lang(monkeypatch):
|
|
694
|
+
c = _client(monkeypatch)
|
|
695
|
+
c._native = None
|
|
696
|
+
c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
|
|
697
|
+
c._http.get.return_value = _resp(200, {"rows": []})
|
|
698
|
+
c.search_dataset("g/n", "hi", mode="exact", lang="fr")
|
|
699
|
+
params = c._http.get.call_args.kwargs["params"]
|
|
700
|
+
assert params["mode"] == "exact" and params["lang"] == "fr"
|
|
701
|
+
|
|
702
|
+
|
|
703
|
+
def test_search_dataset_native_delegates(monkeypatch):
|
|
704
|
+
c = _client(monkeypatch)
|
|
705
|
+
c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
|
|
706
|
+
nat = MagicMock()
|
|
707
|
+
nat.dataset_search.return_value = {"rows": [{"id": 42}]}
|
|
708
|
+
c._native = nat
|
|
709
|
+
assert c.search_dataset("g/n", "hi", mode="exact", lang="fr", limit=5) == [{"id": 42}]
|
|
710
|
+
nat.dataset_search.assert_called_once_with("ds-1", "hi", "exact", "fr", 5)
|
|
711
|
+
c._http.get.assert_not_called()
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+
def test_semantic_search(monkeypatch):
|
|
715
|
+
c = _client(monkeypatch)
|
|
716
|
+
c._native = None
|
|
717
|
+
c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
|
|
718
|
+
c._http.get.return_value = _resp(200, {"hits": [{"id": 9, "score": 0.8}]})
|
|
719
|
+
assert c.semantic_search("g/n", "symptoms", lang="en,fr")[0]["id"] == 9
|
|
720
|
+
assert "/semantic" in c._http.get.call_args.args[0]
|
|
721
|
+
|
|
722
|
+
|
|
723
|
+
def test_regex_search(monkeypatch):
|
|
724
|
+
c = _client(monkeypatch)
|
|
725
|
+
c._native = None
|
|
726
|
+
c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
|
|
727
|
+
c._http.get.return_value = _resp(200, {"rows": [{"debug_id": "r1"}]})
|
|
728
|
+
out = c.regex_search("g/n", r"\bcancel(led)?\b", lang="en", limit=5)
|
|
729
|
+
assert out[0]["debug_id"] == "r1"
|
|
730
|
+
params = c._http.get.call_args.kwargs["params"]
|
|
731
|
+
assert params["mode"] == "regex" and params["q"] == r"\bcancel(led)?\b"
|
|
732
|
+
assert params["lang"] == "en"
|
|
733
|
+
assert "/search" in c._http.get.call_args.args[0]
|
|
734
|
+
|
|
735
|
+
|
|
736
|
+
def test_regex_search_native_delegates(monkeypatch):
|
|
737
|
+
c = _client(monkeypatch)
|
|
738
|
+
c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
|
|
739
|
+
nat = MagicMock()
|
|
740
|
+
nat.regex_search.return_value = {"rows": [{"debug_id": "x"}]}
|
|
741
|
+
c._native = nat
|
|
742
|
+
assert c.regex_search("g/n", "foo.*bar", lang="fr", limit=7) == [{"debug_id": "x"}]
|
|
743
|
+
nat.regex_search.assert_called_once_with("ds-1", "foo.*bar", "fr", 7)
|
|
744
|
+
c._http.get.assert_not_called()
|
|
745
|
+
|
|
746
|
+
|
|
747
|
+
def test_derive_by_query_regex_mode(monkeypatch):
|
|
748
|
+
c = _client(monkeypatch)
|
|
749
|
+
c._native = None
|
|
750
|
+
c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
|
|
751
|
+
c._http.post.return_value = _resp(200, dict(_DS_JSON, name="cancels"))
|
|
752
|
+
c.derive_by_query("g/parent", r"\bcancel", name="g/cancels", mode="regex", lang="en")
|
|
753
|
+
body = c._http.post.call_args.kwargs["json"]
|
|
754
|
+
assert body["mode"] == "regex" and body["q"] == r"\bcancel" and body["lang"] == "en"
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
def test_optimize_embedding_search(monkeypatch):
|
|
758
|
+
c = _client(monkeypatch)
|
|
759
|
+
c._native = None
|
|
760
|
+
c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
|
|
761
|
+
c._http.post.return_value = _resp(200, {"status": "running"})
|
|
762
|
+
assert c.optimize_embedding_search("g/n")["status"] == "running"
|
|
763
|
+
|
|
764
|
+
|
|
765
|
+
def test_word_lookup_union_intersect(monkeypatch):
|
|
766
|
+
c = _client(monkeypatch)
|
|
767
|
+
c._native = None
|
|
768
|
+
c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
|
|
769
|
+
c._http.get.return_value = _resp(200, {"ids": [1, 2]})
|
|
770
|
+
c.word_lookup("g/n", ["a", "b"], op="intersect", lang="fr")
|
|
771
|
+
params = c._http.get.call_args.kwargs["params"]
|
|
772
|
+
assert params["term"] == "a,b" and params["op"] == "intersect" and params["lang"] == "fr"
|
|
773
|
+
|
|
774
|
+
|
|
775
|
+
def test_keyword_expand(monkeypatch):
|
|
776
|
+
c = _client(monkeypatch)
|
|
777
|
+
c._native = None
|
|
778
|
+
c._http.post.return_value = _resp(200, {"keywords": ["a", "b"], "csv": "a, b", "count": 2})
|
|
779
|
+
out = c.keyword_expand("medical terms in french", count=2)
|
|
780
|
+
assert out["count"] == 2
|
|
781
|
+
assert c._http.post.call_args.args[0] == "/datasets/keyword-expand"
|
|
782
|
+
|
|
783
|
+
|
|
784
|
+
def test_derive_by_query_create(monkeypatch):
|
|
785
|
+
c = _client(monkeypatch)
|
|
786
|
+
c._native = None
|
|
787
|
+
c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
|
|
788
|
+
c._http.post.return_value = _resp(200, dict(_DS_JSON, name="medical-fr"))
|
|
789
|
+
out = c.derive_by_query("g/parent", "a,b", name="g/medical-fr", mode="word", lang="fr")
|
|
790
|
+
assert out.name == "medical-fr"
|
|
791
|
+
body = c._http.post.call_args.kwargs["json"]
|
|
792
|
+
assert body["mode"] == "word" and body["name"] == "g/medical-fr" and body["lang"] == "fr"
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
def test_derive_by_query_native_delegates(monkeypatch):
|
|
796
|
+
c = _client(monkeypatch)
|
|
797
|
+
c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
|
|
798
|
+
nat = MagicMock()
|
|
799
|
+
nat.derive_dataset.return_value = dict(_DS_JSON, name="medical-fr")
|
|
800
|
+
c._native = nat
|
|
801
|
+
out = c.derive_by_query("g/parent", "a,b", name="g/medical-fr", mode="word")
|
|
802
|
+
assert out.name == "medical-fr"
|
|
803
|
+
nat.derive_dataset.assert_called_once()
|
|
804
|
+
c._http.post.assert_not_called()
|
|
805
|
+
|
|
806
|
+
|
|
807
|
+
def test_derive_by_query_append(monkeypatch):
|
|
808
|
+
c = _client(monkeypatch)
|
|
809
|
+
c._native = None
|
|
810
|
+
parent = DatasetInfo._from_json(_DS_JSON)
|
|
811
|
+
target = DatasetInfo._from_json(dict(_DS_JSON, id="ds-2", name="medical-fr"))
|
|
812
|
+
c._resolve = MagicMock(side_effect=[parent, target])
|
|
813
|
+
c._http.post.return_value = _resp(200, dict(_DS_JSON, id="ds-2"))
|
|
814
|
+
c.derive_by_query("g/parent", "c,d", target_repo_id="g/medical-fr", mode="word")
|
|
815
|
+
body = c._http.post.call_args.kwargs["json"]
|
|
816
|
+
assert body["target_dataset_id"] == "ds-2" and "name" not in body
|
|
817
|
+
|
|
818
|
+
|
|
819
|
+
def test_derive_by_query_requires_name_or_target(monkeypatch):
|
|
820
|
+
c = _client(monkeypatch)
|
|
821
|
+
c._native = None
|
|
822
|
+
c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
|
|
823
|
+
with pytest.raises(ValueError, match="name= .* target_repo_id="):
|
|
824
|
+
c.derive_by_query("g/parent", "q", mode="word")
|
|
825
|
+
|
|
826
|
+
|
|
827
|
+
def test_derived_rows(monkeypatch):
|
|
828
|
+
c = _client(monkeypatch)
|
|
829
|
+
c._native = None
|
|
830
|
+
c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
|
|
831
|
+
c._http.get.return_value = _resp(200, {"rows": [{"k": 1}], "total": 1, "offset": 0, "limit": 50})
|
|
832
|
+
assert c.derived_rows("g/n")["total"] == 1
|
|
833
|
+
assert "/derived-rows" in c._http.get.call_args.args[0]
|
|
834
|
+
|
|
835
|
+
|
|
692
836
|
# ===========================================================================
|
|
693
837
|
# update / card / preview / links / derivation / delete
|
|
694
838
|
# ===========================================================================
|
|
@@ -978,6 +1122,41 @@ def test_module_link_project(fake_singleton):
|
|
|
978
1122
|
assert ds_mod.link_project("g/n", "proj-1") == "P"
|
|
979
1123
|
|
|
980
1124
|
|
|
1125
|
+
def test_module_semantic_search(fake_singleton):
|
|
1126
|
+
fake_singleton.semantic_search.return_value = [{"id": 2}]
|
|
1127
|
+
assert ds_mod.semantic_search("g/n", "q", lang="fr") == [{"id": 2}]
|
|
1128
|
+
|
|
1129
|
+
|
|
1130
|
+
def test_module_regex_search(fake_singleton):
|
|
1131
|
+
fake_singleton.regex_search.return_value = [{"debug_id": "r1"}]
|
|
1132
|
+
assert ds_mod.regex_search("g/n", r"\bfoo", lang="en") == [{"debug_id": "r1"}]
|
|
1133
|
+
|
|
1134
|
+
|
|
1135
|
+
def test_module_optimize_embedding_search(fake_singleton):
|
|
1136
|
+
fake_singleton.optimize_embedding_search.return_value = {"status": "ready"}
|
|
1137
|
+
assert ds_mod.optimize_embedding_search("g/n") == {"status": "ready"}
|
|
1138
|
+
|
|
1139
|
+
|
|
1140
|
+
def test_module_word_lookup(fake_singleton):
|
|
1141
|
+
fake_singleton.word_lookup.return_value = {"ids": [1]}
|
|
1142
|
+
assert ds_mod.word_lookup("g/n", "a,b", op="union") == {"ids": [1]}
|
|
1143
|
+
|
|
1144
|
+
|
|
1145
|
+
def test_module_keyword_expand(fake_singleton):
|
|
1146
|
+
fake_singleton.keyword_expand.return_value = {"csv": "a, b", "count": 2}
|
|
1147
|
+
assert ds_mod.keyword_expand("prompt", count=2)["count"] == 2
|
|
1148
|
+
|
|
1149
|
+
|
|
1150
|
+
def test_module_derive_by_query(fake_singleton):
|
|
1151
|
+
fake_singleton.derive_by_query.return_value = DatasetInfo._from_json(_DS_JSON)
|
|
1152
|
+
assert ds_mod.derive_by_query("g/p", "q", name="g/c").name == "wmt"
|
|
1153
|
+
|
|
1154
|
+
|
|
1155
|
+
def test_module_derived_rows(fake_singleton):
|
|
1156
|
+
fake_singleton.derived_rows.return_value = {"total": 3}
|
|
1157
|
+
assert ds_mod.derived_rows("g/c")["total"] == 3
|
|
1158
|
+
|
|
1159
|
+
|
|
981
1160
|
def test_module_upload_file(fake_singleton):
|
|
982
1161
|
fake_singleton.upload_file.return_value = {"ok": True}
|
|
983
1162
|
assert ds_mod.upload_file("g/n", "f.txt") == {"ok": True}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|