From 2311af3c21919ddde4b1d3664cf0d9e5ee4f33e7 Mon Sep 17 00:00:00 2001 From: Aftabbs Date: Thu, 23 Jul 2026 15:58:10 +0530 Subject: [PATCH] [issue-7462] [SDK] fix: use direct workspace-scoped URL for experiment link in evaluate() Replaces the legacy session-redirect URL with the same direct URL pattern used by get_dataset_url_by_id and get_test_suite_url_by_id. The session-redirect URL surfaces the experiment under the wrong scope; the direct URL opens the compare page immediately in the correct workspace. Closes #7462 --- sdks/python/src/opik/evaluation/evaluator.py | 15 ++++--- sdks/python/src/opik/url_helpers.py | 13 +++--- sdks/python/tests/unit/test_url_helpers.py | 44 ++++++++++++++++++++ 3 files changed, 59 insertions(+), 13 deletions(-) diff --git a/sdks/python/src/opik/evaluation/evaluator.py b/sdks/python/src/opik/evaluation/evaluator.py index 0a4336b33b2..b1d7560b3c4 100644 --- a/sdks/python/src/opik/evaluation/evaluator.py +++ b/sdks/python/src/opik/evaluation/evaluator.py @@ -409,7 +409,8 @@ def _validated_task(data: Dict[str, Any]) -> Any: experiment_url = url_helpers.get_experiment_url_by_id( experiment_id=experiment_.id, dataset_id=suite_dataset.id, - url_override=client.config.url_override, + base_url=client.config.url_override, + workspace=client._workspace, ) report.display_evaluation_in_progress(experiment_url) @@ -604,7 +605,8 @@ def _evaluate_task( experiment_url = url_helpers.get_experiment_url_by_id( experiment_id=experiment.id, dataset_id=dataset.id, - url_override=client.config.url_override, + base_url=client.config.url_override, + workspace=client._workspace, ) report.display_experiment_link(experiment_url=experiment_url) @@ -737,7 +739,8 @@ def _evaluate_test_suite_task( experiment_url = url_helpers.get_experiment_url_by_id( experiment_id=experiment.id, dataset_id=dataset.id, - url_override=client.config.url_override, + base_url=client.config.url_override, + workspace=client._workspace, ) evaluation_result_ = evaluation_result.EvaluationResult( @@ -883,7 +886,8 @@ def evaluate_experiment( experiment_url = url_helpers.get_experiment_url_by_id( experiment_id=experiment.id, dataset_id=dataset_.id, - url_override=client.config.url_override, + base_url=client.config.url_override, + workspace=client._workspace, ) report.display_experiment_link(experiment_url=experiment_url) @@ -1188,7 +1192,8 @@ def evaluate_prompt( experiment_url = url_helpers.get_experiment_url_by_id( experiment_id=experiment.id, dataset_id=dataset.id, - url_override=client.config.url_override, + base_url=client.config.url_override, + workspace=client._workspace, ) report.display_experiment_link(experiment_url=experiment_url) diff --git a/sdks/python/src/opik/url_helpers.py b/sdks/python/src/opik/url_helpers.py index beeef9fb6d0..92a14ac5969 100644 --- a/sdks/python/src/opik/url_helpers.py +++ b/sdks/python/src/opik/url_helpers.py @@ -1,4 +1,5 @@ import base64 +import json import urllib.parse from typing import Final @@ -28,15 +29,11 @@ def get_ui_url() -> str: def get_experiment_url_by_id( - dataset_id: str, experiment_id: str, url_override: str + dataset_id: str, experiment_id: str, base_url: str, workspace: str ) -> str: - encoded_opik_url = base64.b64encode(url_override.encode("utf-8")).decode("utf-8") - - project_path = urllib.parse.quote( - f"v1/session/redirect/experiments/?experiment_id={experiment_id}&dataset_id={dataset_id}&path={encoded_opik_url}", - safe=ALLOWED_URL_CHARACTERS, - ) - return urllib.parse.urljoin(ensure_ending_slash(url_override), project_path) + domain_root = get_base_url(base_url) + experiments_param = urllib.parse.quote(json.dumps([experiment_id])) + return f"{domain_root}opik/{workspace}/experiments/{dataset_id}/compare?experiments={experiments_param}" def get_project_url_by_workspace( diff --git a/sdks/python/tests/unit/test_url_helpers.py b/sdks/python/tests/unit/test_url_helpers.py index 9fd7603c8f3..e6efdbcb9e1 100644 --- a/sdks/python/tests/unit/test_url_helpers.py +++ b/sdks/python/tests/unit/test_url_helpers.py @@ -138,3 +138,47 @@ def test_get_test_suite_url_by_id__returns_direct_project_scoped_url( ) == expected_test_suite_url ) + + +@pytest.mark.parametrize( + ("base_url", "workspace", "dataset_id", "experiment_id", "expected_url"), + [ + ( + "http://localhost:5173/api", + "default", + "dataset-abc123", + "exp-xyz789", + "http://localhost:5173/opik/default/experiments/dataset-abc123/compare?experiments=%5B%22exp-xyz789%22%5D", + ), + ( + "http://localhost:5173/api/", + "default", + "dataset-abc123", + "exp-xyz789", + "http://localhost:5173/opik/default/experiments/dataset-abc123/compare?experiments=%5B%22exp-xyz789%22%5D", + ), + ( + "https://www.comet.com/opik/api", + "my-team", + "ds-id-001", + "exp-id-002", + "https://www.comet.com/opik/my-team/experiments/ds-id-001/compare?experiments=%5B%22exp-id-002%22%5D", + ), + ], +) +def test_get_experiment_url_by_id__returns_direct_workspace_scoped_url( + base_url: str, + workspace: str, + dataset_id: str, + experiment_id: str, + expected_url: str, +) -> None: + assert ( + url_helpers.get_experiment_url_by_id( + base_url=base_url, + workspace=workspace, + dataset_id=dataset_id, + experiment_id=experiment_id, + ) + == expected_url + )