Skip to content

Commit 0a9a9a4

Browse files
committed
remove the requester_metadata stuff
1 parent 2dccc9c commit 0a9a9a4

2 files changed

Lines changed: 21 additions & 125 deletions

File tree

eval_protocol/adapters/langfuse.py

Lines changed: 5 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -85,29 +85,17 @@ def convert_trace_to_evaluation_row(
8585
execution_metadata = ExecutionMetadata()
8686
row_id = None
8787

88-
if trace.observations:
89-
for obs in trace.observations:
90-
if obs.metadata and "requester_metadata" in obs.metadata:
91-
req_meta = obs.metadata["requester_metadata"]
92-
if isinstance(req_meta, dict):
93-
execution_metadata.invocation_id = req_meta.get("invocation_id")
94-
execution_metadata.experiment_id = req_meta.get("experiment_id")
95-
execution_metadata.rollout_id = req_meta.get("rollout_id")
96-
execution_metadata.run_id = req_meta.get("run_id")
97-
row_id = req_meta.get("row_id")
98-
break # Only need to get first observation
99-
10088
if trace.tags:
10189
for tag in trace.tags:
102-
if tag.startswith("invocation_id:") and not execution_metadata.invocation_id:
90+
if tag.startswith("invocation_id:"):
10391
execution_metadata.invocation_id = tag.split(":", 1)[1]
104-
elif tag.startswith("experiment_id:") and not execution_metadata.experiment_id:
92+
elif tag.startswith("experiment_id:"):
10593
execution_metadata.experiment_id = tag.split(":", 1)[1]
106-
elif tag.startswith("rollout_id:") and not execution_metadata.rollout_id:
94+
elif tag.startswith("rollout_id:"):
10795
execution_metadata.rollout_id = tag.split(":", 1)[1]
108-
elif tag.startswith("run_id:") and not execution_metadata.run_id:
96+
elif tag.startswith("run_id:"):
10997
execution_metadata.run_id = tag.split(":", 1)[1]
110-
elif tag.startswith("row_id:") and not row_id:
98+
elif tag.startswith("row_id:"):
11199
row_id = tag.split(":", 1)[1]
112100

113101
if (
@@ -298,9 +286,6 @@ def get_evaluation_rows(
298286
max_retries: int = 3,
299287
span_name: Optional[str] = None,
300288
converter: Optional[TraceConverter] = None,
301-
metadata: Optional[Dict[str, Any]] = None,
302-
requester_metadata: Optional[Dict[str, Any]] = None,
303-
requester_metadata_contains: Optional[str] = None,
304289
) -> List[EvaluationRow]:
305290
"""Pull traces from Langfuse and convert to EvaluationRow format.
306291
@@ -335,10 +320,6 @@ def get_evaluation_rows(
335320
to_timestamp = datetime.now()
336321
from_timestamp = to_timestamp - timedelta(hours=hours_back)
337322

338-
# If filtering by metadata/requester_metadata, prefer fetching metadata fields
339-
if (metadata is not None or requester_metadata is not None or requester_metadata_contains) and not fields:
340-
fields = "core,metadata,observations"
341-
342323
# Collect trace summaries via pagination (up to limit)
343324
all_traces = []
344325
page = 1
@@ -420,74 +401,6 @@ def get_evaluation_rows(
420401
selected_traces = all_traces
421402
logger.debug("Processing all %d collected traces (no sampling)", len(all_traces))
422403

423-
# Helper to check if a trace matches provided metadata filters. We look in multiple places
424-
# to account for Langfuse moving fields (e.g., metadata vs requester_metadata) and SDK shape.
425-
def _trace_matches_metadata_filters(trace_obj: Any) -> bool:
426-
if metadata is None and requester_metadata is None:
427-
return True
428-
429-
def _as_dict(val: Any) -> Dict[str, Any]:
430-
if val is None:
431-
return {}
432-
if isinstance(val, dict):
433-
return val
434-
# Some SDK objects expose .model_dump() or behave like pydantic models
435-
dump = getattr(val, "model_dump", None)
436-
if callable(dump):
437-
try:
438-
return dump() # type: ignore[no-any-return]
439-
except Exception:
440-
return {}
441-
return {}
442-
443-
# Try common locations for metadata on full trace
444-
trace_meta = _as_dict(getattr(trace_obj, "metadata", None))
445-
trace_req_meta = _as_dict(getattr(trace_obj, "requester_metadata", None))
446-
# Some Langfuse deployments nest requester_metadata inside metadata
447-
nested_req_meta = {}
448-
try:
449-
if isinstance(trace_meta, dict) and isinstance(trace_meta.get("requester_metadata"), dict):
450-
nested_req_meta = _as_dict(trace_meta.get("requester_metadata"))
451-
except Exception:
452-
nested_req_meta = {}
453-
454-
# Fallbacks: sometimes metadata is embedded in input
455-
input_meta = {}
456-
try:
457-
inp = getattr(trace_obj, "input", None)
458-
if isinstance(inp, dict):
459-
input_meta = _as_dict(inp.get("metadata"))
460-
except Exception:
461-
input_meta = {}
462-
463-
# Combine for matching convenience (later keys override earlier for equality check only)
464-
combined_meta = {**trace_meta, **input_meta}
465-
combined_req_meta = {**trace_req_meta}
466-
467-
# Also merge nested requester metadata when present
468-
if nested_req_meta:
469-
combined_req_meta = {**combined_req_meta, **nested_req_meta}
470-
471-
def _is_subset(needle: Dict[str, Any], haystack: Dict[str, Any]) -> bool:
472-
for k, v in needle.items():
473-
if haystack.get(k) != v:
474-
return False
475-
return True
476-
477-
ok_meta = True
478-
ok_req_meta = True
479-
480-
if metadata is not None:
481-
# Accept match if found either in metadata or requester_metadata buckets
482-
ok_meta = _is_subset(metadata, combined_meta) or _is_subset(metadata, combined_req_meta)
483-
484-
if requester_metadata is not None:
485-
ok_req_meta = _is_subset(requester_metadata, combined_req_meta) or _is_subset(
486-
requester_metadata, combined_meta
487-
)
488-
489-
return ok_meta and ok_req_meta
490-
491404
# Process each selected trace with sleep and retry logic
492405
for trace_info in selected_traces:
493406
# Sleep between gets to avoid rate limits
@@ -524,39 +437,6 @@ def _is_subset(needle: Dict[str, Any], haystack: Dict[str, Any]) -> bool:
524437
break # Skip this trace
525438

526439
if trace_full:
527-
# If metadata filters are provided, skip non-matching traces early
528-
try:
529-
if not _trace_matches_metadata_filters(trace_full):
530-
continue
531-
except Exception:
532-
# Be permissive on filter errors; treat as non-match
533-
continue
534-
535-
# If observations carry requester_metadata, allow substring filtering
536-
if requester_metadata_contains:
537-
contains_val = requester_metadata_contains
538-
found_match = False
539-
try:
540-
for obs in getattr(trace_full, "observations", []) or []:
541-
obs_rmd = getattr(obs, "requester_metadata", None)
542-
if isinstance(obs_rmd, dict) and any(
543-
(isinstance(v, str) and contains_val in v) for v in obs_rmd.values()
544-
):
545-
found_match = True
546-
break
547-
obs_md = getattr(obs, "metadata", None)
548-
if isinstance(obs_md, dict):
549-
nested = obs_md.get("requester_metadata")
550-
if isinstance(nested, dict) and any(
551-
(isinstance(v, str) and contains_val in v) for v in nested.values()
552-
):
553-
found_match = True
554-
break
555-
except Exception:
556-
found_match = False
557-
if not found_match:
558-
continue
559-
560440
try:
561441
if converter:
562442
eval_row = converter(trace_full, include_tool_calls, span_name)

tests/chinook/langfuse/test_remote_langfuse_chinook.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@
1515
from eval_protocol.adapters.langfuse import create_langfuse_adapter
1616

1717
INVOCATION_ID = ""
18+
ASSERTION_EXECUTED = False
19+
20+
21+
@pytest.fixture(autouse=True)
22+
def check_assertion_executed():
23+
"""Ensure the test actually executed the Langfuse validation"""
24+
global ASSERTION_EXECUTED
25+
ASSERTION_EXECUTED = False # Reset before test
26+
yield
27+
# After test completes, verify the assertion was executed
28+
assert ASSERTION_EXECUTED, (
29+
"Test passed but never validated Langfuse data - check if output_data_loader returned empty results"
30+
)
1831

1932

2033
def fetch_trajectories(invocation_id: str) -> List[EvaluationRow]:
@@ -97,10 +110,13 @@ async def test_remote_rollout_and_fetch_langfuse(row: EvaluationRow) -> Evaluati
97110
- trigger remote rollout via RemoteRolloutProcessor (calls init/status)
98111
- fetch traces from Langfuse filtered by metadata via output_data_loader; FAIL if none found
99112
"""
113+
global ASSERTION_EXECUTED
114+
100115
# Sanity check: row should have an invocation_id since it came from Langfuse via output_data_loader
101116
assert row.messages[0].content == "Hello there! Please say hi back.", "Row should have correct message content"
102117
assert row.execution_metadata.invocation_id == INVOCATION_ID, "Row should have correct invocation_id set"
103118

119+
ASSERTION_EXECUTED = True
104120
print(f"✅ Successfully received row from Langfuse with invocation_id: {row.execution_metadata.invocation_id}")
105121

106122
return row

0 commit comments

Comments
 (0)