Skip to content

Commit 19f4faa

Browse files
danostroskyclaude
andcommitted
feat(langfuse): add Score event support
Implement ScoreEventBody and CreateScore API to enable evaluation of LLM outputs via Langfuse scores (e.g., user satisfaction, accuracy metrics). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8f11ae8 commit 19f4faa

File tree

4 files changed

+66
-1
lines changed

4 files changed

+66
-1
lines changed

libs/acl/langfuse/event.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ type eventBodyUnion struct {
7979
Span *SpanEventBody `json:",inline,omitempty"`
8080
Generation *GenerationEventBody `json:",inline,omitempty"`
8181
Event *EventEventBody `json:",inline,omitempty"`
82+
Score *ScoreEventBody `json:",inline,omitempty"`
8283
Log *SDKLogEventBody `json:",inline,omitempty"`
8384
}
8485

@@ -91,6 +92,8 @@ func (e *eventBodyUnion) MarshalJSON() ([]byte, error) {
9192
return sonic.Marshal(e.Generation)
9293
} else if e.Event != nil {
9394
return sonic.Marshal(e.Event)
95+
} else if e.Score != nil {
96+
return sonic.Marshal(e.Score)
9497
}
9598
return nil, fmt.Errorf("event body is empty")
9699
}
@@ -104,6 +107,8 @@ func (e *eventBodyUnion) getTraceID() string {
104107
return e.Generation.TraceID
105108
} else if e.Event != nil {
106109
return e.Event.TraceID
110+
} else if e.Score != nil {
111+
return e.Score.TraceID
107112
}
108113
return ""
109114
}
@@ -115,6 +120,8 @@ func (e *eventBodyUnion) getObservationID() string {
115120
return e.Generation.ID
116121
} else if e.Event != nil {
117122
return e.Event.ID
123+
} else if e.Score != nil {
124+
return e.Score.ObservationID
118125
}
119126
return ""
120127
}
@@ -257,4 +264,14 @@ type SDKLogEventBody struct {
257264
Log string `json:"log"`
258265
}
259266

260-
// TODO: ScoreEvent
267+
type ScoreEventBody struct {
268+
ID string `json:"id,omitempty"`
269+
TraceID string `json:"traceId"`
270+
Name string `json:"name"`
271+
Value float64 `json:"value"`
272+
ObservationID string `json:"observationId,omitempty"`
273+
Comment string `json:"comment,omitempty"`
274+
DataType string `json:"dataType,omitempty"`
275+
ConfigID string `json:"configId,omitempty"`
276+
Environment string `json:"environment,omitempty"`
277+
}

libs/acl/langfuse/event_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,19 @@ func TestEventBodyUnion(t *testing.T) {
7777
assert.Equal(t, observationID, eventUnion.getObservationID())
7878
assert.Equal(t, map[string]string{"key": "value"}, eventUnion.getMetadata())
7979

80+
scoreUnion := &eventBodyUnion{Score: &ScoreEventBody{
81+
ID: "scoreID",
82+
TraceID: traceID,
83+
Name: "accuracy",
84+
Value: 0.95,
85+
ObservationID: observationID,
86+
}}
87+
assert.Equal(t, traceID, scoreUnion.getTraceID())
88+
assert.Equal(t, observationID, scoreUnion.getObservationID())
89+
assert.Equal(t, "", scoreUnion.getInput())
90+
assert.Equal(t, "", scoreUnion.getOutput())
91+
assert.Nil(t, scoreUnion.getMetadata())
92+
8093
generationUnion := &eventBodyUnion{Generation: &GenerationEventBody{
8194
BaseObservationEventBody: BaseObservationEventBody{
8295
BaseEventBody: BaseEventBody{

libs/acl/langfuse/langfuse.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ type Langfuse interface {
3737
CreateGeneration(body *GenerationEventBody) (string, error)
3838
EndGeneration(body *GenerationEventBody) error
3939
CreateEvent(body *EventEventBody) (string, error)
40+
CreateScore(body *ScoreEventBody) (string, error)
4041
Flush()
4142
}
4243

@@ -205,6 +206,25 @@ func (l *langfuseIns) CreateEvent(body *EventEventBody) (string, error) {
205206
})
206207
}
207208

209+
// CreateScore creates a new score for evaluating LLM outputs
210+
//
211+
// Parameters:
212+
// - body: The score event details. If ID is empty, a new UUID will be generated
213+
//
214+
// Returns:
215+
// - string: The ID of the created score
216+
// - error: Any error that occurred during creation
217+
func (l *langfuseIns) CreateScore(body *ScoreEventBody) (string, error) {
218+
if len(body.ID) == 0 {
219+
body.ID = uuid.NewString()
220+
}
221+
return body.ID, l.tm.push(&event{
222+
ID: uuid.NewString(),
223+
Type: EventTypeScoreCreate,
224+
Body: eventBodyUnion{Score: body},
225+
})
226+
}
227+
208228
// Flush waits for all queued events to be processed and uploaded to Langfuse
209229
//
210230
// This method blocks until all pending events in the queue have been processed

libs/acl/langfuse/mock/langfuse_mock.go

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)