langfuse-ruby 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,12 +2,12 @@ module Langfuse
2
2
  class Generation
3
3
  attr_reader :id, :trace_id, :name, :start_time, :end_time, :completion_start_time,
4
4
  :model, :model_parameters, :input, :output, :usage, :metadata, :level,
5
- :status_message, :parent_observation_id, :version, :client
5
+ :status_message, :parent_observation_id, :version, :as_type, :client
6
6
 
7
7
  def initialize(client:, trace_id:, id: nil, name: nil, start_time: nil, end_time: nil,
8
8
  completion_start_time: nil, model: nil, model_parameters: nil, input: nil,
9
9
  output: nil, usage: nil, metadata: nil, level: nil, status_message: nil,
10
- parent_observation_id: nil, version: nil, **kwargs)
10
+ parent_observation_id: nil, version: nil, as_type: nil, **kwargs)
11
11
  @client = client
12
12
  @id = id || Utils.generate_id
13
13
  @trace_id = trace_id
@@ -25,6 +25,7 @@ module Langfuse
25
25
  @status_message = status_message
26
26
  @parent_observation_id = parent_observation_id
27
27
  @version = version
28
+ @as_type = validate_as_type(as_type)
28
29
  @kwargs = kwargs
29
30
 
30
31
  # Create the generation
@@ -62,8 +63,9 @@ module Langfuse
62
63
  self
63
64
  end
64
65
 
66
+ # Create a child span
65
67
  def span(name: nil, start_time: nil, end_time: nil, input: nil, output: nil,
66
- metadata: nil, level: nil, status_message: nil, version: nil, **kwargs)
68
+ metadata: nil, level: nil, status_message: nil, version: nil, as_type: nil, **kwargs)
67
69
  @client.span(
68
70
  trace_id: @trace_id,
69
71
  name: name,
@@ -76,10 +78,12 @@ module Langfuse
76
78
  status_message: status_message,
77
79
  parent_observation_id: @id,
78
80
  version: version,
81
+ as_type: as_type,
79
82
  **kwargs
80
83
  )
81
84
  end
82
85
 
86
+ # Create a child generation
83
87
  def generation(name: nil, start_time: nil, end_time: nil, completion_start_time: nil,
84
88
  model: nil, model_parameters: nil, input: nil, output: nil, usage: nil,
85
89
  metadata: nil, level: nil, status_message: nil, version: nil, **kwargs)
@@ -103,6 +107,7 @@ module Langfuse
103
107
  )
104
108
  end
105
109
 
110
+ # Create a child event
106
111
  def event(name:, start_time: nil, input: nil, output: nil, metadata: nil,
107
112
  level: nil, status_message: nil, version: nil, **kwargs)
108
113
  @client.event(
@@ -120,6 +125,138 @@ module Langfuse
120
125
  )
121
126
  end
122
127
 
128
+ # Convenience methods for enhanced observation types
129
+
130
+ # Create a child agent observation
131
+ def agent(name: nil, start_time: nil, end_time: nil, input: nil, output: nil,
132
+ metadata: nil, level: nil, status_message: nil, version: nil, **kwargs)
133
+ span(
134
+ name: name,
135
+ start_time: start_time,
136
+ end_time: end_time,
137
+ input: input,
138
+ output: output,
139
+ metadata: metadata,
140
+ level: level,
141
+ status_message: status_message,
142
+ version: version,
143
+ as_type: ObservationType::AGENT,
144
+ **kwargs
145
+ )
146
+ end
147
+
148
+ # Create a child tool observation
149
+ def tool(name: nil, start_time: nil, end_time: nil, input: nil, output: nil,
150
+ metadata: nil, level: nil, status_message: nil, version: nil, **kwargs)
151
+ span(
152
+ name: name,
153
+ start_time: start_time,
154
+ end_time: end_time,
155
+ input: input,
156
+ output: output,
157
+ metadata: metadata,
158
+ level: level,
159
+ status_message: status_message,
160
+ version: version,
161
+ as_type: ObservationType::TOOL,
162
+ **kwargs
163
+ )
164
+ end
165
+
166
+ # Create a child chain observation
167
+ def chain(name: nil, start_time: nil, end_time: nil, input: nil, output: nil,
168
+ metadata: nil, level: nil, status_message: nil, version: nil, **kwargs)
169
+ span(
170
+ name: name,
171
+ start_time: start_time,
172
+ end_time: end_time,
173
+ input: input,
174
+ output: output,
175
+ metadata: metadata,
176
+ level: level,
177
+ status_message: status_message,
178
+ version: version,
179
+ as_type: ObservationType::CHAIN,
180
+ **kwargs
181
+ )
182
+ end
183
+
184
+ # Create a child retriever observation
185
+ def retriever(name: nil, start_time: nil, end_time: nil, input: nil, output: nil,
186
+ metadata: nil, level: nil, status_message: nil, version: nil, **kwargs)
187
+ span(
188
+ name: name,
189
+ start_time: start_time,
190
+ end_time: end_time,
191
+ input: input,
192
+ output: output,
193
+ metadata: metadata,
194
+ level: level,
195
+ status_message: status_message,
196
+ version: version,
197
+ as_type: ObservationType::RETRIEVER,
198
+ **kwargs
199
+ )
200
+ end
201
+
202
+ # Create a child embedding observation
203
+ def embedding(name: nil, start_time: nil, end_time: nil, input: nil, output: nil,
204
+ model: nil, usage: nil, metadata: nil, level: nil, status_message: nil,
205
+ version: nil, **kwargs)
206
+ merged_metadata = (metadata || {}).merge(
207
+ { model: model, usage: usage }.compact
208
+ )
209
+ span(
210
+ name: name,
211
+ start_time: start_time,
212
+ end_time: end_time,
213
+ input: input,
214
+ output: output,
215
+ metadata: merged_metadata.empty? ? nil : merged_metadata,
216
+ level: level,
217
+ status_message: status_message,
218
+ version: version,
219
+ as_type: ObservationType::EMBEDDING,
220
+ **kwargs
221
+ )
222
+ end
223
+
224
+ # Create a child evaluator observation
225
+ def evaluator(name: nil, start_time: nil, end_time: nil, input: nil, output: nil,
226
+ metadata: nil, level: nil, status_message: nil, version: nil, **kwargs)
227
+ span(
228
+ name: name,
229
+ start_time: start_time,
230
+ end_time: end_time,
231
+ input: input,
232
+ output: output,
233
+ metadata: metadata,
234
+ level: level,
235
+ status_message: status_message,
236
+ version: version,
237
+ as_type: ObservationType::EVALUATOR,
238
+ **kwargs
239
+ )
240
+ end
241
+
242
+ # Create a child guardrail observation
243
+ def guardrail(name: nil, start_time: nil, end_time: nil, input: nil, output: nil,
244
+ metadata: nil, level: nil, status_message: nil, version: nil, **kwargs)
245
+ span(
246
+ name: name,
247
+ start_time: start_time,
248
+ end_time: end_time,
249
+ input: input,
250
+ output: output,
251
+ metadata: metadata,
252
+ level: level,
253
+ status_message: status_message,
254
+ version: version,
255
+ as_type: ObservationType::GUARDRAIL,
256
+ **kwargs
257
+ )
258
+ end
259
+
123
260
  def score(name:, value:, data_type: nil, comment: nil, **kwargs)
124
261
  @client.score(
125
262
  observation_id: @id,
@@ -136,7 +273,7 @@ module Langfuse
136
273
  end
137
274
 
138
275
  def to_dict
139
- {
276
+ data = {
140
277
  id: @id,
141
278
  trace_id: @trace_id,
142
279
  name: @name,
@@ -153,11 +290,24 @@ module Langfuse
153
290
  status_message: @status_message,
154
291
  parent_observation_id: @parent_observation_id,
155
292
  version: @version
156
- }.merge(@kwargs).compact
293
+ }
294
+ data[:type] = @as_type if @as_type
295
+ data.merge(@kwargs).compact
157
296
  end
158
297
 
159
298
  private
160
299
 
300
+ def validate_as_type(type)
301
+ return nil if type.nil?
302
+
303
+ type_str = type.to_s
304
+ unless ObservationType.valid?(type_str)
305
+ raise ValidationError, "Invalid observation type: #{type}. Valid types are: #{ObservationType::ALL.join(', ')}"
306
+ end
307
+
308
+ type_str
309
+ end
310
+
161
311
  def create_generation
162
312
  @client.enqueue_event('generation-create', to_dict)
163
313
  end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Langfuse
4
+ # Valid observation types for Langfuse
5
+ # These types provide semantic meaning to observations in traces
6
+ module ObservationType
7
+ # Core observation types (existing)
8
+ SPAN = 'span'
9
+ GENERATION = 'generation'
10
+ EVENT = 'event'
11
+
12
+ # Enhanced observation types (new in 2025)
13
+ AGENT = 'agent' # Agent workflows and reasoning
14
+ TOOL = 'tool' # Tool/function calls
15
+ CHAIN = 'chain' # Chain operations (e.g., retrieval chains)
16
+ RETRIEVER = 'retriever' # Data retrieval (vector stores, databases)
17
+ EMBEDDING = 'embedding' # Embedding generation
18
+ EVALUATOR = 'evaluator' # Evaluation/scoring functions
19
+ GUARDRAIL = 'guardrail' # Safety filters and content moderation
20
+
21
+ # All valid observation types
22
+ ALL = [
23
+ SPAN,
24
+ GENERATION,
25
+ EVENT,
26
+ AGENT,
27
+ TOOL,
28
+ CHAIN,
29
+ RETRIEVER,
30
+ EMBEDDING,
31
+ EVALUATOR,
32
+ GUARDRAIL
33
+ ].freeze
34
+
35
+ # Types that are aliases for span (use span-create/span-update events)
36
+ SPAN_BASED = [
37
+ SPAN,
38
+ AGENT,
39
+ TOOL,
40
+ CHAIN,
41
+ RETRIEVER,
42
+ EMBEDDING,
43
+ EVALUATOR,
44
+ GUARDRAIL
45
+ ].freeze
46
+
47
+ # Validate if a type is valid
48
+ def self.valid?(type)
49
+ return true if type.nil? # nil is valid (defaults to base type)
50
+
51
+ ALL.include?(type.to_s)
52
+ end
53
+
54
+ # Check if type uses span events
55
+ def self.span_based?(type)
56
+ return true if type.nil?
57
+
58
+ SPAN_BASED.include?(type.to_s)
59
+ end
60
+ end
61
+ end
data/lib/langfuse/span.rb CHANGED
@@ -1,11 +1,12 @@
1
1
  module Langfuse
2
2
  class Span
3
3
  attr_reader :id, :trace_id, :name, :start_time, :end_time, :input, :output,
4
- :metadata, :level, :status_message, :parent_observation_id, :version, :client
4
+ :metadata, :level, :status_message, :parent_observation_id, :version,
5
+ :as_type, :client
5
6
 
6
7
  def initialize(client:, trace_id:, id: nil, name: nil, start_time: nil, end_time: nil,
7
8
  input: nil, output: nil, metadata: nil, level: nil, status_message: nil,
8
- parent_observation_id: nil, version: nil, **kwargs)
9
+ parent_observation_id: nil, version: nil, as_type: nil, **kwargs)
9
10
  @client = client
10
11
  @id = id || Utils.generate_id
11
12
  @trace_id = trace_id
@@ -19,6 +20,7 @@ module Langfuse
19
20
  @status_message = status_message
20
21
  @parent_observation_id = parent_observation_id
21
22
  @version = version
23
+ @as_type = validate_as_type(as_type)
22
24
  @kwargs = kwargs
23
25
 
24
26
  # Create the span
@@ -50,8 +52,9 @@ module Langfuse
50
52
  self
51
53
  end
52
54
 
55
+ # Create a child span
53
56
  def span(name: nil, start_time: nil, end_time: nil, input: nil, output: nil,
54
- metadata: nil, level: nil, status_message: nil, version: nil, **kwargs)
57
+ metadata: nil, level: nil, status_message: nil, version: nil, as_type: nil, **kwargs)
55
58
  @client.span(
56
59
  trace_id: @trace_id,
57
60
  name: name,
@@ -64,10 +67,12 @@ module Langfuse
64
67
  status_message: status_message,
65
68
  parent_observation_id: @id,
66
69
  version: version,
70
+ as_type: as_type,
67
71
  **kwargs
68
72
  )
69
73
  end
70
74
 
75
+ # Create a child generation
71
76
  def generation(name: nil, start_time: nil, end_time: nil, completion_start_time: nil,
72
77
  model: nil, model_parameters: nil, input: nil, output: nil, usage: nil,
73
78
  metadata: nil, level: nil, status_message: nil, version: nil, **kwargs)
@@ -91,6 +96,7 @@ module Langfuse
91
96
  )
92
97
  end
93
98
 
99
+ # Create a child event
94
100
  def event(name:, start_time: nil, input: nil, output: nil, metadata: nil,
95
101
  level: nil, status_message: nil, version: nil, **kwargs)
96
102
  @client.event(
@@ -108,6 +114,138 @@ module Langfuse
108
114
  )
109
115
  end
110
116
 
117
+ # Convenience methods for enhanced observation types
118
+
119
+ # Create a child agent observation
120
+ def agent(name: nil, start_time: nil, end_time: nil, input: nil, output: nil,
121
+ metadata: nil, level: nil, status_message: nil, version: nil, **kwargs)
122
+ span(
123
+ name: name,
124
+ start_time: start_time,
125
+ end_time: end_time,
126
+ input: input,
127
+ output: output,
128
+ metadata: metadata,
129
+ level: level,
130
+ status_message: status_message,
131
+ version: version,
132
+ as_type: ObservationType::AGENT,
133
+ **kwargs
134
+ )
135
+ end
136
+
137
+ # Create a child tool observation
138
+ def tool(name: nil, start_time: nil, end_time: nil, input: nil, output: nil,
139
+ metadata: nil, level: nil, status_message: nil, version: nil, **kwargs)
140
+ span(
141
+ name: name,
142
+ start_time: start_time,
143
+ end_time: end_time,
144
+ input: input,
145
+ output: output,
146
+ metadata: metadata,
147
+ level: level,
148
+ status_message: status_message,
149
+ version: version,
150
+ as_type: ObservationType::TOOL,
151
+ **kwargs
152
+ )
153
+ end
154
+
155
+ # Create a child chain observation
156
+ def chain(name: nil, start_time: nil, end_time: nil, input: nil, output: nil,
157
+ metadata: nil, level: nil, status_message: nil, version: nil, **kwargs)
158
+ span(
159
+ name: name,
160
+ start_time: start_time,
161
+ end_time: end_time,
162
+ input: input,
163
+ output: output,
164
+ metadata: metadata,
165
+ level: level,
166
+ status_message: status_message,
167
+ version: version,
168
+ as_type: ObservationType::CHAIN,
169
+ **kwargs
170
+ )
171
+ end
172
+
173
+ # Create a child retriever observation
174
+ def retriever(name: nil, start_time: nil, end_time: nil, input: nil, output: nil,
175
+ metadata: nil, level: nil, status_message: nil, version: nil, **kwargs)
176
+ span(
177
+ name: name,
178
+ start_time: start_time,
179
+ end_time: end_time,
180
+ input: input,
181
+ output: output,
182
+ metadata: metadata,
183
+ level: level,
184
+ status_message: status_message,
185
+ version: version,
186
+ as_type: ObservationType::RETRIEVER,
187
+ **kwargs
188
+ )
189
+ end
190
+
191
+ # Create a child embedding observation
192
+ def embedding(name: nil, start_time: nil, end_time: nil, input: nil, output: nil,
193
+ model: nil, usage: nil, metadata: nil, level: nil, status_message: nil,
194
+ version: nil, **kwargs)
195
+ merged_metadata = (metadata || {}).merge(
196
+ { model: model, usage: usage }.compact
197
+ )
198
+ span(
199
+ name: name,
200
+ start_time: start_time,
201
+ end_time: end_time,
202
+ input: input,
203
+ output: output,
204
+ metadata: merged_metadata.empty? ? nil : merged_metadata,
205
+ level: level,
206
+ status_message: status_message,
207
+ version: version,
208
+ as_type: ObservationType::EMBEDDING,
209
+ **kwargs
210
+ )
211
+ end
212
+
213
+ # Create a child evaluator observation
214
+ def evaluator(name: nil, start_time: nil, end_time: nil, input: nil, output: nil,
215
+ metadata: nil, level: nil, status_message: nil, version: nil, **kwargs)
216
+ span(
217
+ name: name,
218
+ start_time: start_time,
219
+ end_time: end_time,
220
+ input: input,
221
+ output: output,
222
+ metadata: metadata,
223
+ level: level,
224
+ status_message: status_message,
225
+ version: version,
226
+ as_type: ObservationType::EVALUATOR,
227
+ **kwargs
228
+ )
229
+ end
230
+
231
+ # Create a child guardrail observation
232
+ def guardrail(name: nil, start_time: nil, end_time: nil, input: nil, output: nil,
233
+ metadata: nil, level: nil, status_message: nil, version: nil, **kwargs)
234
+ span(
235
+ name: name,
236
+ start_time: start_time,
237
+ end_time: end_time,
238
+ input: input,
239
+ output: output,
240
+ metadata: metadata,
241
+ level: level,
242
+ status_message: status_message,
243
+ version: version,
244
+ as_type: ObservationType::GUARDRAIL,
245
+ **kwargs
246
+ )
247
+ end
248
+
111
249
  def score(name:, value:, data_type: nil, comment: nil, **kwargs)
112
250
  @client.score(
113
251
  observation_id: @id,
@@ -124,7 +262,7 @@ module Langfuse
124
262
  end
125
263
 
126
264
  def to_dict
127
- {
265
+ data = {
128
266
  id: @id,
129
267
  trace_id: @trace_id,
130
268
  name: @name,
@@ -137,11 +275,24 @@ module Langfuse
137
275
  status_message: @status_message,
138
276
  parent_observation_id: @parent_observation_id,
139
277
  version: @version
140
- }.merge(@kwargs).compact
278
+ }
279
+ data[:type] = @as_type if @as_type
280
+ data.merge(@kwargs).compact
141
281
  end
142
282
 
143
283
  private
144
284
 
285
+ def validate_as_type(type)
286
+ return nil if type.nil?
287
+
288
+ type_str = type.to_s
289
+ unless ObservationType.valid?(type_str)
290
+ raise ValidationError, "Invalid observation type: #{type}. Valid types are: #{ObservationType::ALL.join(', ')}"
291
+ end
292
+
293
+ type_str
294
+ end
295
+
145
296
  def create_span
146
297
  data = {
147
298
  id: @id,
@@ -156,7 +307,9 @@ module Langfuse
156
307
  status_message: @status_message,
157
308
  parent_observation_id: @parent_observation_id,
158
309
  version: @version
159
- }.merge(@kwargs).compact
310
+ }
311
+ data[:type] = @as_type if @as_type
312
+ data = data.merge(@kwargs).compact
160
313
 
161
314
  @client.enqueue_event('span-create', data)
162
315
  end
@@ -175,7 +328,9 @@ module Langfuse
175
328
  status_message: @status_message,
176
329
  parent_observation_id: @parent_observation_id,
177
330
  version: @version
178
- }.merge(@kwargs).compact
331
+ }
332
+ data[:type] = @as_type if @as_type
333
+ data = data.merge(@kwargs).compact
179
334
 
180
335
  @client.enqueue_event('span-update', data)
181
336
  end