Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 23 additions & 54 deletions langfuse/_client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import re
import urllib.parse
import uuid
from datetime import datetime
from datetime import datetime, timezone
from hashlib import sha256
from time import time_ns
from typing import (
Expand Down Expand Up @@ -97,6 +97,7 @@
AsyncLangfuseAPI,
CreateChatPromptRequest,
CreateChatPromptType,
CreateScoreRequest,
CreateTextPromptRequest,
Dataset,
DatasetItem,
Expand All @@ -108,8 +109,6 @@
NotFoundError,
Prompt_Chat,
Prompt_Text,
ScoreBody,
TraceBody,
)
from langfuse.batch_evaluation import (
BatchEvaluationResult,
Expand Down Expand Up @@ -1940,28 +1939,34 @@ def create_score(

score_id = score_id or self._create_observation_id()

# The API rejects timestamps without a UTC offset; naive values are UTC.
if timestamp is not None and timestamp.tzinfo is None:
timestamp = timestamp.replace(tzinfo=timezone.utc)

try:
new_body = ScoreBody(
request = CreateScoreRequest(
id=score_id,
sessionId=session_id,
datasetRunId=dataset_run_id,
traceId=trace_id,
observationId=observation_id,
session_id=session_id,
dataset_run_id=dataset_run_id,
trace_id=trace_id,
observation_id=observation_id,
name=name,
value=value,
dataType=data_type, # type: ignore
data_type=data_type, # type: ignore
Comment thread
hassiebp marked this conversation as resolved.
comment=comment,
configId=config_id,
config_id=config_id,
environment=environment or self._environment,
metadata=metadata,
timestamp=timestamp or _get_timestamp(),
Comment thread
hassiebp marked this conversation as resolved.
)

event = {
"id": self.create_trace_id(),
"type": "score-create",
"timestamp": timestamp or _get_timestamp(),
"body": new_body,
# Fern's dict() keeps fields explicitly set to None, so drop them here.
score = {
key: value
for key, value in request.dict(by_alias=True).items()
if value is not None
}
# The API accepts any JSON value as metadata, the generated model only dicts.
if metadata is not None:
score["metadata"] = metadata

if self._resources is not None:
# Force the score to be in sample if it was for a legacy trace ID, i.e. non-32 hexchar
Expand All @@ -1970,7 +1975,7 @@ def create_score(
)

self._resources.add_score_task(
event,
score,
force_sample=force_sample,
)

Expand All @@ -1983,42 +1988,6 @@ def create_score(
e,
)

def _create_trace_tags_via_ingestion(
self,
*,
trace_id: str,
tags: List[str],
) -> None:
"""Private helper to enqueue trace tag updates via ingestion API events."""
if not self._tracing_enabled:
return

if len(tags) == 0:
return

try:
new_body = TraceBody(
id=trace_id,
tags=tags,
)

event = {
"id": self.create_trace_id(),
"type": "trace-create",
"timestamp": _get_timestamp(),
"body": new_body,
}

if self._resources is not None:
self._resources.add_trace_task(event)
except Exception as e:
langfuse_logger.exception(
"Error updating trace tags: Failed to process trace update event for "
"trace_id=%s. Error: %s",
trace_id,
e,
)

@overload
def score_current_span(
self,
Expand Down
Loading
Loading