Skip to content

Commit c978013

Browse files
harbor-langsmith: persist run tags (top-level) and dataset metadata (under extra) (harbor-framework#1808)
1 parent 8cfac6a commit c978013

2 files changed

Lines changed: 49 additions & 3 deletions

File tree

packages/harbor-langsmith/src/harbor_langsmith/plugin.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,9 @@ def _get_or_create_dataset(self, job: Any) -> str | None:
160160
payload = {
161161
"name": dataset_name,
162162
"description": f"Harbor dataset synced from job {job.config.job_name}",
163-
"metadata": {"source": "harbor"},
163+
# LangSmith stores dataset metadata under extra.metadata (matching the SDK);
164+
# a top-level "metadata" key is silently dropped.
165+
"extra": {"metadata": {"source": "harbor"}},
164166
}
165167
response = self._request(
166168
"POST", "/datasets", json=payload, ok_statuses={200, 201, 409}
@@ -239,9 +241,9 @@ def _create_root_run(self, event: TrialHookEvent) -> None:
239241
"start_time": self._format_time(event.timestamp),
240242
"session_id": self._experiment_id,
241243
"reference_example_id": reference_example_id,
244+
"tags": ["harbor", "harbor-trial"],
242245
"extra": {
243246
"metadata": self._trial_metadata(event),
244-
"tags": ["harbor", "harbor-trial"],
245247
},
246248
}
247249
if payload["reference_example_id"] is None:
@@ -270,9 +272,9 @@ def _create_phase_run(self, event: TrialHookEvent) -> None:
270272
"start_time": self._format_time(event.timestamp),
271273
"session_id": self._experiment_id,
272274
"parent_run_id": parent_run_id,
275+
"tags": ["harbor", "harbor-phase", event.event.value],
273276
"extra": {
274277
"metadata": self._trial_metadata(event),
275-
"tags": ["harbor", "harbor-phase", event.event.value],
276278
},
277279
}
278280
self._request("POST", "/runs", json=payload, ok_statuses={200, 201, 409})

packages/harbor-langsmith/tests/unit/test_plugin.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,47 @@ def test_stable_uuid_is_deterministic():
5757

5858
assert first == second
5959
assert first != third
60+
61+
62+
@pytest.mark.unit
63+
def test_root_run_tags_are_top_level(monkeypatch):
64+
plugin = LangSmithPlugin(api_key="test-key")
65+
plugin._experiment_id = "exp"
66+
monkeypatch.setattr(plugin, "_trial_metadata", lambda event: {})
67+
with patch.object(plugin, "_request") as request:
68+
plugin._create_root_run(MagicMock())
69+
70+
payload = request.call_args.kwargs["json"]
71+
assert payload["tags"] == ["harbor", "harbor-trial"]
72+
assert "tags" not in payload["extra"]
73+
74+
75+
@pytest.mark.unit
76+
def test_phase_run_tags_are_top_level(monkeypatch):
77+
plugin = LangSmithPlugin(api_key="test-key")
78+
plugin._experiment_id = "exp"
79+
monkeypatch.setattr(plugin, "_trial_metadata", lambda event: {})
80+
event = MagicMock()
81+
event.event.value = "agent_start"
82+
plugin._run_ids[event.config.trial_name] = "parent-run"
83+
with patch.object(plugin, "_request") as request:
84+
plugin._create_phase_run(event)
85+
86+
payload = request.call_args.kwargs["json"]
87+
assert payload["tags"] == ["harbor", "harbor-phase", "agent_start"]
88+
assert "tags" not in payload["extra"]
89+
90+
91+
@pytest.mark.unit
92+
def test_dataset_metadata_is_nested_under_extra(monkeypatch):
93+
plugin = LangSmithPlugin(api_key="test-key")
94+
plugin.dataset_name = "ds"
95+
monkeypatch.setattr(plugin, "_find_dataset", lambda name: None)
96+
response = MagicMock(status_code=201)
97+
response.json.return_value = {"id": "d1"}
98+
with patch.object(plugin, "_request", return_value=response) as request:
99+
plugin._get_or_create_dataset(MagicMock())
100+
101+
payload = request.call_args.kwargs["json"]
102+
assert payload["extra"]["metadata"] == {"source": "harbor"}
103+
assert "metadata" not in payload

0 commit comments

Comments
 (0)