provekit 0.7.0__tar.gz → 0.7.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.
- {provekit-0.7.0 → provekit-0.7.1}/PKG-INFO +1 -1
- {provekit-0.7.0 → provekit-0.7.1}/provekit/eval.py +21 -3
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/calibration.py +5 -4
- {provekit-0.7.0 → provekit-0.7.1}/provekit/trace.py +38 -7
- {provekit-0.7.0 → provekit-0.7.1}/provekit.egg-info/PKG-INFO +1 -1
- {provekit-0.7.0 → provekit-0.7.1}/provekit.egg-info/SOURCES.txt +1 -0
- {provekit-0.7.0 → provekit-0.7.1}/pyproject.toml +1 -1
- provekit-0.7.1/tests/test_self_trace.py +86 -0
- {provekit-0.7.0 → provekit-0.7.1}/README.md +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/__init__.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/auto.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/buffer.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/cli.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/config.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/conformance.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/database.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/demo.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/doctor.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/grpc_ingest.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/main.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/mcp.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/env.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/script.py.mako +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/9d2c06bfa4e6_baseline.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/a1b2c3d4e5f6_feedback_sessions.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/a2b3c4d5e6f7_usage_records.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/a3b4c5d6e7f8_metric_rollups.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/a7b8c9d0e1f2_replay_webhook_prompts.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/a9b0c1d2e3f4_digests.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/b0c1d2e3f4a5_automation_rules.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/b2c3d4e5f6a7_datasets.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/b3c4d5e6f7a8_export_schedules.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/b4c5d6e7f8a9_retention_events.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/b7c8d9e0f1a2_flow_studio.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/b8c9d0e1f2a3_span_notes.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/c1d2e3f4a5b6_prompts_and_turns.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/c3d4e5f6a7b8_experiments.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/c4d5e6f7a8b9_custom_scorers.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/c5d6e7f8a9b0_search_text.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/c8d9e0f1a2b3_dataset_snapshots.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/c9d0e1f2a3b4_idempotent_ingest.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/d0e1f2a3b4c5_alert_webhook.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/d4e5f6a7b8c9_alerts.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/d6e7f8a9b0c1_dataset_versioning.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/d9e0f1a2b3c4_note_threads.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/e0f1a2b3c4d5_tenant_suspend.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/e1f2a3b4c5d6_audit_log.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/e5f6a7b8c9d0_admin.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/e7f8a9b0c1d2_saved_views.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/f1a2b3c4d5e6_project_invites.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/f2a3b4c5d6e7_run_hot_path_indexes.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/f6a7b8c9d0e1_interactive_debugging.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/f8a9b0c1d2e3_webhook_subscriptions.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/models.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/observability.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/__init__.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/activity.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/admin.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/alerts.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/apikeys.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/auth.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/automation.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/dataset_writes.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/datasets.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/digests.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/evaluators.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/experiments.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/export.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/flows.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/metrics.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/playground.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/projects.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/prompts.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/review.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/scim.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/sso.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/traces.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/views.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/routers/webhooks.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/scorers.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/__init__.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/apikey.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/audit.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/auth.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/automation.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/custom_scorers.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/datasets.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/deploy.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/digests.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/email.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/errors.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/export.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/export_schedule.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/fleet.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/flow_trace.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/impersonation.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/invites.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/limits.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/llm_client.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/mentions.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/netguard.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/notify.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/oidc.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/otel.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/partitions.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/payloads.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/pricing.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/prompts.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/redact.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/replay.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/roles.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/rollups.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/scim.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/sealing.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/search.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/seed.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/share.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/spool.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/stats.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/tenant.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/usage.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/webhooks.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/services/workspace.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit/vcr.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit.egg-info/dependency_links.txt +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit.egg-info/entry_points.txt +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit.egg-info/requires.txt +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/provekit.egg-info/top_level.txt +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/setup.cfg +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_account_recovery.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_activity.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_admin.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_alerts.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_apikeys.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_auth.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_auth_hardening.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_autoinstrument.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_automation.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_buffer.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_calibration.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_cli.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_clock_skew.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_conformance.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_cov_limits_auth.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_coverage_extra.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_custom_scorers.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_dataset_snapshots.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_dataset_versioning.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_datasets.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_dialects.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_digests.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_doctor.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_error_messages.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_eval.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_evaluators.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_experiments.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_export.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_export_schedule.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_feedback.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_fleet.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_flows.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_grpc_ingest.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_hardening.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_impersonation.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_index_coverage.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_invites.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_key_read_api.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_mcp.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_mcp_writes.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_metrics.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_migrations.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_netguard.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_note_threads.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_notify.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_observability.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_onboarding.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_otel.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_partitions.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_payload_offload.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_playground.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_playground_depth.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_playground_stream.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_pricing.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_projects.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_prompts_and_sessions.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_provenance.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_quality_gates.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_quota.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_redact.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_redaction_corpus.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_regression_triage.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_reproducibility.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_retention.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_review.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_roles.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_rollups.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_scim.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_scorers.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_scorers_extra.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_search.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_share.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_share_redaction.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_spool.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_sso.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_stats.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_step_through.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_tenant.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_trace_cost.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_trace_sdk.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_traces_tree.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_usage_metering.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_vcr.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_views.py +0 -0
- {provekit-0.7.0 → provekit-0.7.1}/tests/test_webhooks.py +0 -0
|
@@ -18,6 +18,8 @@ import json
|
|
|
18
18
|
|
|
19
19
|
import httpx
|
|
20
20
|
|
|
21
|
+
from .trace import _no_self_trace
|
|
22
|
+
|
|
21
23
|
from . import scorers as _scorers
|
|
22
24
|
from . import trace as _trace
|
|
23
25
|
|
|
@@ -25,24 +27,40 @@ _TIMEOUT = 60
|
|
|
25
27
|
|
|
26
28
|
|
|
27
29
|
def _get(endpoint, headers, path):
|
|
28
|
-
|
|
30
|
+
with _no_self_trace():
|
|
31
|
+
r = httpx.get(f"{endpoint}{path}", headers=headers, timeout=_TIMEOUT, follow_redirects=False)
|
|
29
32
|
r.raise_for_status()
|
|
30
33
|
return r.json()
|
|
31
34
|
|
|
32
35
|
|
|
33
36
|
def _post(endpoint, headers, path, body):
|
|
34
|
-
|
|
37
|
+
with _no_self_trace():
|
|
38
|
+
r = httpx.post(f"{endpoint}{path}", headers=headers, json=body, timeout=_TIMEOUT,
|
|
39
|
+
follow_redirects=False)
|
|
35
40
|
r.raise_for_status()
|
|
36
41
|
return r.json()
|
|
37
42
|
|
|
38
43
|
|
|
39
44
|
def _resolve_dataset_id(endpoint, headers, dataset) -> int:
|
|
45
|
+
"""Accept an id or a name — and an id that arrived as a string.
|
|
46
|
+
|
|
47
|
+
The id is a number everywhere it is shown (the portal, `provekit datasets list`), and the
|
|
48
|
+
two places it is most often read from — an environment variable and a CLI argument — hand
|
|
49
|
+
it back as text. `evaluate("2", …)` then fell through to the name lookup and reported
|
|
50
|
+
`dataset '2' not found`, which is true and completely misleading: the dataset exists, and
|
|
51
|
+
nothing in the message suggests the type is what is wrong.
|
|
52
|
+
"""
|
|
40
53
|
if isinstance(dataset, int):
|
|
41
54
|
return dataset
|
|
55
|
+
if isinstance(dataset, str) and dataset.strip().isdigit():
|
|
56
|
+
return int(dataset.strip())
|
|
57
|
+
names = []
|
|
42
58
|
for d in _get(endpoint, headers, "/v1/datasets"):
|
|
43
59
|
if d.get("name") == dataset:
|
|
44
60
|
return d["id"]
|
|
45
|
-
|
|
61
|
+
names.append(d.get("name"))
|
|
62
|
+
raise ValueError(
|
|
63
|
+
f"dataset {dataset!r} not found — this project has: {', '.join(map(str, names)) or 'none'}")
|
|
46
64
|
|
|
47
65
|
|
|
48
66
|
def evaluate(dataset, target, scorers, *, name: str = "experiment") -> dict:
|
|
@@ -225,10 +225,11 @@ def calibrate(rows, *, pass_at: float = PASS_AT, judge_name: str = "", human_nam
|
|
|
225
225
|
# label more. The rates are the part that would get quoted as a credibility claim, so
|
|
226
226
|
# they are withheld rather than published with a disclaimer nobody carries forward.
|
|
227
227
|
out["caution"] = (
|
|
228
|
-
f"{n}
|
|
229
|
-
f"
|
|
230
|
-
f"
|
|
231
|
-
f"
|
|
228
|
+
f"Only {n} run{'' if n == 1 else 's'} {'has' if n == 1 else 'have'} been judged both "
|
|
229
|
+
f"ways — by you and by the scorer. We need at least {MIN_LABELLED_N} before the "
|
|
230
|
+
f"numbers mean anything. A score from a handful of examples looks solid and is not, "
|
|
231
|
+
f"and once someone quotes it the damage is done — so we show nothing instead. "
|
|
232
|
+
f"Judge a few more runs in the Review queue.")
|
|
232
233
|
return out
|
|
233
234
|
|
|
234
235
|
out["agreement"] = (a + d) / n
|
|
@@ -160,6 +160,33 @@ def _span_to_otlp(span) -> dict:
|
|
|
160
160
|
return out
|
|
161
161
|
|
|
162
162
|
|
|
163
|
+
@contextlib.contextmanager
|
|
164
|
+
def _no_self_trace():
|
|
165
|
+
"""Don't instrument ProveKit's own HTTP calls.
|
|
166
|
+
|
|
167
|
+
`provekit[http]` instruments httpx, and the SDK talks to the portal over httpx — so
|
|
168
|
+
exporting a batch, fetching a prompt and posting a score were each captured as spans, which
|
|
169
|
+
were then exported, which produced more spans. They arrive parentless, so they land in the
|
|
170
|
+
trace list as top-level runs named "GET" and "POST" carrying no model, no tokens and no
|
|
171
|
+
input: in a first real run of the demo agent, 19 of 24 traces were this noise.
|
|
172
|
+
|
|
173
|
+
It is worse than clutter. Those rows are counted: they drag the error rate and p95 toward
|
|
174
|
+
the latency of ProveKit's own API, and they push real runs off the first page of a list
|
|
175
|
+
people scan by eye.
|
|
176
|
+
|
|
177
|
+
Best-effort by design — the helper only exists once an instrumentation package is
|
|
178
|
+
installed, and tracing must never be the thing that breaks a customer's process, so a
|
|
179
|
+
missing import degrades to "no suppression" rather than raising.
|
|
180
|
+
"""
|
|
181
|
+
try:
|
|
182
|
+
from opentelemetry.instrumentation.utils import suppress_instrumentation
|
|
183
|
+
except Exception: # noqa: BLE001 — optional dependency
|
|
184
|
+
yield
|
|
185
|
+
return
|
|
186
|
+
with suppress_instrumentation():
|
|
187
|
+
yield
|
|
188
|
+
|
|
189
|
+
|
|
163
190
|
class _ProveKitExporter:
|
|
164
191
|
"""A minimal OTel SpanExporter that ships spans to ProveKit's /v1/traces as OTLP-JSON.
|
|
165
192
|
|
|
@@ -179,8 +206,9 @@ class _ProveKitExporter:
|
|
|
179
206
|
by never looking — silently drops exactly the spans the retry path exists for.
|
|
180
207
|
"""
|
|
181
208
|
import httpx
|
|
182
|
-
|
|
183
|
-
|
|
209
|
+
with _no_self_trace():
|
|
210
|
+
r = httpx.post(self._url, json=body, headers=self._headers, timeout=5,
|
|
211
|
+
follow_redirects=False)
|
|
184
212
|
if r.status_code >= 400:
|
|
185
213
|
log.debug("provekit trace export rejected: HTTP %s", r.status_code)
|
|
186
214
|
return False
|
|
@@ -453,9 +481,10 @@ def get_prompt(name: str, *, label: str = "", key: str = "", default=None) -> di
|
|
|
453
481
|
return default
|
|
454
482
|
try:
|
|
455
483
|
import httpx
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
484
|
+
with _no_self_trace():
|
|
485
|
+
r = httpx.get(f"{endpoint}/v1/prompts/{name}",
|
|
486
|
+
params={"label": label, "key": key},
|
|
487
|
+
headers={"Authorization": f"Bearer {api_key}"}, timeout=5)
|
|
459
488
|
if r.status_code >= 400:
|
|
460
489
|
log.debug("provekit: prompt %r fetch returned %s", name, r.status_code)
|
|
461
490
|
return default
|
|
@@ -499,8 +528,10 @@ def score(name: str, *, score: float | None = None, value: str | None = None,
|
|
|
499
528
|
body = {"name": name, "score": score, "value": value, "comment": comment, "source": "sdk"}
|
|
500
529
|
try:
|
|
501
530
|
import httpx
|
|
502
|
-
|
|
503
|
-
|
|
531
|
+
with _no_self_trace():
|
|
532
|
+
httpx.post(f"{_endpoint}/v1/traces/{trace_id}/feedback", json=body,
|
|
533
|
+
headers={"Authorization": f"Bearer {_api_key}"}, timeout=5,
|
|
534
|
+
follow_redirects=False)
|
|
504
535
|
return True
|
|
505
536
|
except Exception as exc: # never let a feedback post surface into the user's app
|
|
506
537
|
log.debug("provekit score post failed: %s", exc)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""The SDK must not trace its own calls to the portal (#noise).
|
|
2
|
+
|
|
3
|
+
`provekit[http]` instruments httpx, and the SDK talks to the portal over httpx. Without
|
|
4
|
+
suppression, exporting a batch, fetching a prompt and posting a score each produced their own
|
|
5
|
+
parentless span, which arrived in the customer's trace list as a top-level run named "GET" or
|
|
6
|
+
"POST" with no model, no tokens and no input. In a first real run of the bundled demo agent,
|
|
7
|
+
19 of 24 traces were this. They are also counted, so they drag error rate and p95 toward the
|
|
8
|
+
latency of ProveKit's own API.
|
|
9
|
+
"""
|
|
10
|
+
from provekit import trace as pk_trace
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_the_suppression_helper_is_a_context_manager():
|
|
14
|
+
with pk_trace._no_self_trace():
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_it_degrades_to_a_no_op_without_the_instrumentation_package(monkeypatch):
|
|
19
|
+
"""Tracing must never be the thing that breaks a customer's process, so a missing optional
|
|
20
|
+
import has to mean "no suppression", not an exception."""
|
|
21
|
+
import builtins
|
|
22
|
+
real = builtins.__import__
|
|
23
|
+
|
|
24
|
+
def _no_otel_utils(name, *a, **kw):
|
|
25
|
+
if name == "opentelemetry.instrumentation.utils":
|
|
26
|
+
raise ImportError("not installed")
|
|
27
|
+
return real(name, *a, **kw)
|
|
28
|
+
|
|
29
|
+
monkeypatch.setattr(builtins, "__import__", _no_otel_utils)
|
|
30
|
+
with pk_trace._no_self_trace():
|
|
31
|
+
pass # did not raise
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_every_sdk_call_to_the_portal_is_wrapped():
|
|
35
|
+
"""A drift guard. A new httpx call added to the SDK without suppression re-opens the bug,
|
|
36
|
+
and the symptom (junk traces in someone else's portal) never shows up in our own tests."""
|
|
37
|
+
import inspect
|
|
38
|
+
import re
|
|
39
|
+
|
|
40
|
+
from provekit import eval as pk_eval
|
|
41
|
+
|
|
42
|
+
for mod in (pk_trace, pk_eval):
|
|
43
|
+
src = inspect.getsource(mod)
|
|
44
|
+
for m in re.finditer(r'^(\s*)(?:r = )?httpx\.(get|post)\(', src, re.M):
|
|
45
|
+
line_no = src[:m.start()].count("\n") + 1
|
|
46
|
+
before = src[:m.start()].rsplit("\n", 3)[-3:]
|
|
47
|
+
assert any("_no_self_trace()" in b for b in before), (
|
|
48
|
+
f"{mod.__name__}:{line_no} calls httpx.{m.group(2)} outside _no_self_trace() — "
|
|
49
|
+
"it will appear as a junk trace in the customer's own portal")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# ---------------------------------------------------------------- dataset id as a string
|
|
53
|
+
|
|
54
|
+
def test_a_dataset_id_that_arrived_as_text_still_resolves():
|
|
55
|
+
"""An id read from os.environ or argv is a str. It used to fall through to the name lookup
|
|
56
|
+
and report `dataset '2' not found` — true, and entirely misleading, because the dataset is
|
|
57
|
+
right there and the type is what was wrong."""
|
|
58
|
+
from provekit.eval import _resolve_dataset_id
|
|
59
|
+
|
|
60
|
+
def _never_called(*a, **kw):
|
|
61
|
+
raise AssertionError("a numeric id must not need a network lookup")
|
|
62
|
+
|
|
63
|
+
import provekit.eval as ev
|
|
64
|
+
real = ev._get
|
|
65
|
+
ev._get = _never_called
|
|
66
|
+
try:
|
|
67
|
+
assert _resolve_dataset_id("http://x", {}, "2") == 2
|
|
68
|
+
assert _resolve_dataset_id("http://x", {}, " 7 ") == 7
|
|
69
|
+
assert _resolve_dataset_id("http://x", {}, 3) == 3
|
|
70
|
+
finally:
|
|
71
|
+
ev._get = real
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_an_unknown_name_says_what_the_project_does_have():
|
|
75
|
+
""""not found" alone leaves you guessing whether the name is wrong, the project is wrong,
|
|
76
|
+
or the key is. Listing what is actually there settles it in one line."""
|
|
77
|
+
import pytest
|
|
78
|
+
|
|
79
|
+
import provekit.eval as ev
|
|
80
|
+
real = ev._get
|
|
81
|
+
ev._get = lambda *a, **kw: [{"id": 1, "name": "support-qa"}, {"id": 2, "name": "billing"}]
|
|
82
|
+
try:
|
|
83
|
+
with pytest.raises(ValueError, match="support-qa, billing"):
|
|
84
|
+
ev._resolve_dataset_id("http://x", {}, "typo-name")
|
|
85
|
+
finally:
|
|
86
|
+
ev._get = real
|
|
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
|
{provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/a1b2c3d4e5f6_feedback_sessions.py
RENAMED
|
File without changes
|
{provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/a2b3c4d5e6f7_usage_records.py
RENAMED
|
File without changes
|
{provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/a3b4c5d6e7f8_metric_rollups.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/b0c1d2e3f4a5_automation_rules.py
RENAMED
|
File without changes
|
|
File without changes
|
{provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/b3c4d5e6f7a8_export_schedules.py
RENAMED
|
File without changes
|
{provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/b4c5d6e7f8a9_retention_events.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/c1d2e3f4a5b6_prompts_and_turns.py
RENAMED
|
File without changes
|
|
File without changes
|
{provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/c4d5e6f7a8b9_custom_scorers.py
RENAMED
|
File without changes
|
|
File without changes
|
{provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/c8d9e0f1a2b3_dataset_snapshots.py
RENAMED
|
File without changes
|
{provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/c9d0e1f2a3b4_idempotent_ingest.py
RENAMED
|
File without changes
|
{provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/d0e1f2a3b4c5_alert_webhook.py
RENAMED
|
File without changes
|
|
File without changes
|
{provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/d6e7f8a9b0c1_dataset_versioning.py
RENAMED
|
File without changes
|
|
File without changes
|
{provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/e0f1a2b3c4d5_tenant_suspend.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/f1a2b3c4d5e6_project_invites.py
RENAMED
|
File without changes
|
{provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/f2a3b4c5d6e7_run_hot_path_indexes.py
RENAMED
|
File without changes
|
{provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/f6a7b8c9d0e1_interactive_debugging.py
RENAMED
|
File without changes
|
{provekit-0.7.0 → provekit-0.7.1}/provekit/migrations/versions/f8a9b0c1d2e3_webhook_subscriptions.py
RENAMED
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|