langfuse-ruby 0.1.2 → 0.1.4

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.
data/test_offline.rb CHANGED
@@ -2,30 +2,30 @@
2
2
 
3
3
  require_relative 'lib/langfuse'
4
4
 
5
- puts "šŸš€ Testing Langfuse Ruby SDK (Offline Mode)..."
5
+ puts 'šŸš€ Testing Langfuse Ruby SDK (Offline Mode)...'
6
6
 
7
7
  # Test 1: Basic configuration
8
8
  puts "\n1. Testing configuration..."
9
9
  Langfuse.configure do |config|
10
- config.public_key = "test_key"
11
- config.secret_key = "test_secret"
12
- config.host = "https://test.langfuse.com"
13
- config.debug = false # Turn off debug to avoid network calls
10
+ config.public_key = 'test_key'
11
+ config.secret_key = 'test_secret'
12
+ config.host = 'https://test.langfuse.com'
13
+ config.debug = false # Turn off debug to avoid network calls
14
14
  end
15
15
 
16
- puts "āœ… Configuration successful"
16
+ puts 'āœ… Configuration successful'
17
17
 
18
18
  # Test 2: Client initialization
19
19
  puts "\n2. Testing client initialization..."
20
20
  begin
21
21
  client = Langfuse.new(
22
- public_key: "test_key",
23
- secret_key: "test_secret",
24
- host: "https://test.langfuse.com",
22
+ public_key: 'test_key',
23
+ secret_key: 'test_secret',
24
+ host: 'https://test.langfuse.com',
25
25
  debug: false
26
26
  )
27
- puts "āœ… Client initialization successful"
28
- rescue => e
27
+ puts 'āœ… Client initialization successful'
28
+ rescue StandardError => e
29
29
  puts "āŒ Client initialization failed: #{e.message}"
30
30
  end
31
31
 
@@ -33,13 +33,13 @@ end
33
33
  puts "\n3. Testing trace creation..."
34
34
  begin
35
35
  trace = client.trace(
36
- name: "test-trace",
37
- user_id: "test-user",
38
- input: { message: "Hello, world!" }
36
+ name: 'test-trace',
37
+ user_id: 'test-user',
38
+ input: { message: 'Hello, world!' }
39
39
  )
40
- puts "āœ… Trace creation successful"
40
+ puts 'āœ… Trace creation successful'
41
41
  puts " Trace ID: #{trace.id}"
42
- rescue => e
42
+ rescue StandardError => e
43
43
  puts "āŒ Trace creation failed: #{e.message}"
44
44
  end
45
45
 
@@ -47,14 +47,14 @@ end
47
47
  puts "\n4. Testing generation creation..."
48
48
  begin
49
49
  generation = trace.generation(
50
- name: "test-generation",
51
- model: "gpt-3.5-turbo",
52
- input: [{ role: "user", content: "Hello!" }],
53
- output: { content: "Hi there!" }
50
+ name: 'test-generation',
51
+ model: 'gpt-3.5-turbo',
52
+ input: [{ role: 'user', content: 'Hello!' }],
53
+ output: { content: 'Hi there!' }
54
54
  )
55
- puts "āœ… Generation creation successful"
55
+ puts 'āœ… Generation creation successful'
56
56
  puts " Generation ID: #{generation.id}"
57
- rescue => e
57
+ rescue StandardError => e
58
58
  puts "āŒ Generation creation failed: #{e.message}"
59
59
  end
60
60
 
@@ -62,18 +62,18 @@ end
62
62
  puts "\n5. Testing prompt template..."
63
63
  begin
64
64
  template = Langfuse::PromptTemplate.from_template(
65
- "Hello {{name}}! How are you feeling {{mood}} today?"
65
+ 'Hello {{name}}! How are you feeling {{mood}} today?'
66
66
  )
67
67
 
68
68
  formatted = template.format(
69
- name: "Alice",
70
- mood: "happy"
69
+ name: 'Alice',
70
+ mood: 'happy'
71
71
  )
72
72
 
73
- puts "āœ… Prompt template successful"
73
+ puts 'āœ… Prompt template successful'
74
74
  puts " Variables: #{template.input_variables}"
75
75
  puts " Formatted: #{formatted}"
76
- rescue => e
76
+ rescue StandardError => e
77
77
  puts "āŒ Prompt template failed: #{e.message}"
78
78
  end
79
79
 
@@ -81,19 +81,20 @@ end
81
81
  puts "\n6. Testing chat prompt template..."
82
82
  begin
83
83
  chat_template = Langfuse::ChatPromptTemplate.from_messages([
84
- { role: "system", content: "You are a helpful {{role}} assistant." },
85
- { role: "user", content: "{{user_input}}" }
86
- ])
84
+ { role: 'system',
85
+ content: 'You are a helpful {{role}} assistant.' },
86
+ { role: 'user', content: '{{user_input}}' }
87
+ ])
87
88
 
88
89
  messages = chat_template.format(
89
- role: "coding",
90
- user_input: "Help me with Ruby"
90
+ role: 'coding',
91
+ user_input: 'Help me with Ruby'
91
92
  )
92
93
 
93
- puts "āœ… Chat prompt template successful"
94
+ puts 'āœ… Chat prompt template successful'
94
95
  puts " Variables: #{chat_template.input_variables}"
95
96
  puts " Messages: #{messages.length}"
96
- rescue => e
97
+ rescue StandardError => e
97
98
  puts "āŒ Chat prompt template failed: #{e.message}"
98
99
  end
99
100
 
@@ -103,26 +104,26 @@ begin
103
104
  # Exact match evaluator
104
105
  exact_match = Langfuse::Evaluators::ExactMatchEvaluator.new
105
106
  result = exact_match.evaluate(
106
- "What is 2+2?",
107
- "4",
108
- expected: "4"
107
+ 'What is 2+2?',
108
+ '4',
109
+ expected: '4'
109
110
  )
110
111
  puts "āœ… Exact match evaluator: #{result}"
111
112
 
112
113
  # Similarity evaluator
113
114
  similarity = Langfuse::Evaluators::SimilarityEvaluator.new
114
115
  result = similarity.evaluate(
115
- "What is AI?",
116
- "Artificial Intelligence",
117
- expected: "AI is artificial intelligence"
116
+ 'What is AI?',
117
+ 'Artificial Intelligence',
118
+ expected: 'AI is artificial intelligence'
118
119
  )
119
120
  puts "āœ… Similarity evaluator: #{result}"
120
121
 
121
122
  # Length evaluator
122
123
  length = Langfuse::Evaluators::LengthEvaluator.new(min_length: 5, max_length: 20)
123
124
  result = length.evaluate(
124
- "Test input",
125
- "This is a test",
125
+ 'Test input',
126
+ 'This is a test',
126
127
  expected: nil
127
128
  )
128
129
  puts "āœ… Length evaluator: #{result}"
@@ -130,22 +131,21 @@ begin
130
131
  # Contains evaluator
131
132
  contains = Langfuse::Evaluators::ContainsEvaluator.new
132
133
  result = contains.evaluate(
133
- "Find Ruby",
134
- "Ruby programming language",
135
- expected: "Ruby"
134
+ 'Find Ruby',
135
+ 'Ruby programming language',
136
+ expected: 'Ruby'
136
137
  )
137
138
  puts "āœ… Contains evaluator: #{result}"
138
139
 
139
140
  # Regex evaluator
140
141
  regex = Langfuse::Evaluators::RegexEvaluator.new(pattern: /\d+/)
141
142
  result = regex.evaluate(
142
- "Find numbers",
143
- "There are 42 apples",
143
+ 'Find numbers',
144
+ 'There are 42 apples',
144
145
  expected: nil
145
146
  )
146
147
  puts "āœ… Regex evaluator: #{result}"
147
-
148
- rescue => e
148
+ rescue StandardError => e
149
149
  puts "āŒ Evaluator failed: #{e.message}"
150
150
  end
151
151
 
@@ -156,16 +156,16 @@ begin
156
156
  timestamp = Langfuse::Utils.current_timestamp
157
157
 
158
158
  # Test data transformation
159
- hash_data = { "key1" => "value1", "nested" => { "key2" => "value2" } }
159
+ hash_data = { 'key1' => 'value1', 'nested' => { 'key2' => 'value2' } }
160
160
  symbolized = Langfuse::Utils.deep_symbolize_keys(hash_data)
161
161
  stringified = Langfuse::Utils.deep_stringify_keys(symbolized)
162
162
 
163
- puts "āœ… Utils successful"
163
+ puts 'āœ… Utils successful'
164
164
  puts " ID: #{id[0..8]}..."
165
165
  puts " Timestamp: #{timestamp}"
166
166
  puts " Symbolized keys: #{symbolized.keys}"
167
167
  puts " Stringified keys: #{stringified.keys}"
168
- rescue => e
168
+ rescue StandardError => e
169
169
  puts "āŒ Utils failed: #{e.message}"
170
170
  end
171
171
 
@@ -177,26 +177,26 @@ begin
177
177
  # Add some events
178
178
  client.score(
179
179
  trace_id: trace.id,
180
- name: "test-score",
180
+ name: 'test-score',
181
181
  value: 0.9
182
182
  )
183
183
 
184
184
  trace.score(
185
- name: "trace-score",
185
+ name: 'trace-score',
186
186
  value: 0.8
187
187
  )
188
188
 
189
189
  generation.score(
190
- name: "generation-score",
190
+ name: 'generation-score',
191
191
  value: 0.95
192
192
  )
193
193
 
194
194
  queue_size_after = client.instance_variable_get(:@event_queue).length
195
195
 
196
- puts "āœ… Event queue successful"
196
+ puts 'āœ… Event queue successful'
197
197
  puts " Events added: #{queue_size_after - queue_size_before}"
198
198
  puts " Total events: #{queue_size_after}"
199
- rescue => e
199
+ rescue StandardError => e
200
200
  puts "āŒ Event queue failed: #{e.message}"
201
201
  end
202
202
 
@@ -205,28 +205,28 @@ puts "\n10. Testing complex workflow..."
205
205
  begin
206
206
  # Create a complex trace with nested spans
207
207
  complex_trace = client.trace(
208
- name: "complex-workflow",
209
- user_id: "user-456",
210
- session_id: "session-789",
211
- input: { query: "Explain quantum computing" },
208
+ name: 'complex-workflow',
209
+ user_id: 'user-456',
210
+ session_id: 'session-789',
211
+ input: { query: 'Explain quantum computing' },
212
212
  metadata: {
213
- environment: "test",
214
- version: "1.0.0",
215
- tags: ["physics", "computing"]
213
+ environment: 'test',
214
+ version: '1.0.0',
215
+ tags: %w[physics computing]
216
216
  }
217
217
  )
218
218
 
219
219
  # Document retrieval span
220
220
  retrieval_span = complex_trace.span(
221
- name: "document-retrieval",
222
- input: { query: "quantum computing basics" }
221
+ name: 'document-retrieval',
222
+ input: { query: 'quantum computing basics' }
223
223
  )
224
224
 
225
225
  # Embedding generation
226
226
  embedding_gen = retrieval_span.generation(
227
- name: "embedding-generation",
228
- model: "text-embedding-ada-002",
229
- input: "quantum computing basics",
227
+ name: 'embedding-generation',
228
+ model: 'text-embedding-ada-002',
229
+ input: 'quantum computing basics',
230
230
  output: Array.new(1536) { rand(-1.0..1.0) }, # Mock embedding
231
231
  usage: { prompt_tokens: 4, total_tokens: 4 }
232
232
  )
@@ -234,31 +234,31 @@ begin
234
234
  retrieval_span.end(
235
235
  output: {
236
236
  documents: [
237
- "Quantum computing uses quantum bits...",
238
- "Quantum algorithms can solve certain problems..."
237
+ 'Quantum computing uses quantum bits...',
238
+ 'Quantum algorithms can solve certain problems...'
239
239
  ]
240
240
  }
241
241
  )
242
242
 
243
243
  # Answer generation span
244
244
  answer_span = complex_trace.span(
245
- name: "answer-generation",
245
+ name: 'answer-generation',
246
246
  input: {
247
- query: "Explain quantum computing",
248
- context: ["Quantum computing uses quantum bits...", "Quantum algorithms can solve certain problems..."]
247
+ query: 'Explain quantum computing',
248
+ context: ['Quantum computing uses quantum bits...', 'Quantum algorithms can solve certain problems...']
249
249
  }
250
250
  )
251
251
 
252
252
  # LLM generation
253
253
  llm_gen = answer_span.generation(
254
- name: "openai-completion",
255
- model: "gpt-4",
254
+ name: 'openai-completion',
255
+ model: 'gpt-4',
256
256
  input: [
257
- { role: "system", content: "You are a physics expert." },
258
- { role: "user", content: "Explain quantum computing based on the context." }
257
+ { role: 'system', content: 'You are a physics expert.' },
258
+ { role: 'user', content: 'Explain quantum computing based on the context.' }
259
259
  ],
260
260
  output: {
261
- content: "Quantum computing is a revolutionary approach to computation that leverages quantum mechanical phenomena like superposition and entanglement to process information in fundamentally different ways than classical computers."
261
+ content: 'Quantum computing is a revolutionary approach to computation that leverages quantum mechanical phenomena like superposition and entanglement to process information in fundamentally different ways than classical computers.'
262
262
  },
263
263
  usage: {
264
264
  prompt_tokens: 120,
@@ -273,57 +273,75 @@ begin
273
273
 
274
274
  answer_span.end(
275
275
  output: {
276
- answer: "Quantum computing is a revolutionary approach to computation that leverages quantum mechanical phenomena like superposition and entanglement to process information in fundamentally different ways than classical computers."
277
- }
278
- )
279
-
280
- complex_trace.update(
281
- output: {
282
- answer: "Quantum computing is a revolutionary approach to computation that leverages quantum mechanical phenomena like superposition and entanglement to process information in fundamentally different ways than classical computers."
276
+ answer: 'Quantum computing is a revolutionary approach to computation that leverages quantum mechanical phenomena like superposition and entanglement to process information in fundamentally different ways than classical computers.'
283
277
  }
284
278
  )
285
279
 
286
- puts "āœ… Complex workflow successful"
280
+ puts 'āœ… Complex workflow successful'
287
281
  puts " Trace ID: #{complex_trace.id}"
288
- puts " Spans created: 2"
289
- puts " Generations created: 2"
290
-
291
- rescue => e
282
+ puts ' Spans created: 2'
283
+ puts ' Generations created: 2'
284
+ rescue StandardError => e
292
285
  puts "āŒ Complex workflow failed: #{e.message}"
293
286
  end
294
287
 
295
288
  # Test 11: Error handling
296
289
  puts "\n11. Testing error handling..."
297
290
  begin
298
- # Test validation error
291
+ # Save current configuration
292
+ original_public_key = Langfuse.configuration.public_key
293
+ original_secret_key = Langfuse.configuration.secret_key
294
+
295
+ # Test authentication error - missing public key
299
296
  begin
300
- Langfuse::Utils.validate_required_fields({ name: "test" }, [:name, :required_field])
301
- rescue Langfuse::ValidationError => e
302
- puts "āœ… Validation error caught: #{e.message}"
297
+ Langfuse.configuration.public_key = nil
298
+ ENV.delete('LANGFUSE_PUBLIC_KEY')
299
+ Langfuse.new(public_key: nil, secret_key: 'secret')
300
+ puts 'āŒ Expected AuthenticationError but none was raised'
301
+ rescue Langfuse::AuthenticationError => e
302
+ puts "āœ… Authentication error caught: #{e.message}"
303
+ ensure
304
+ Langfuse.configuration.public_key = original_public_key
303
305
  end
304
306
 
305
- # Test authentication error
307
+ # Test authentication error - missing secret key
306
308
  begin
307
- Langfuse.new(public_key: nil, secret_key: "secret")
309
+ Langfuse.configuration.secret_key = nil
310
+ ENV.delete('LANGFUSE_SECRET_KEY')
311
+ Langfuse.new(public_key: 'public', secret_key: nil)
312
+ puts 'āŒ Expected AuthenticationError but none was raised'
308
313
  rescue Langfuse::AuthenticationError => e
309
314
  puts "āœ… Authentication error caught: #{e.message}"
315
+ ensure
316
+ Langfuse.configuration.secret_key = original_secret_key
317
+ end
318
+
319
+ # Test validation error through prompt template
320
+ begin
321
+ template = Langfuse::PromptTemplate.from_template('Hello {{name}}!')
322
+ # This should work fine
323
+ result = template.format(name: 'World')
324
+ puts "āœ… Prompt template validation passed: #{result}"
325
+ rescue Langfuse::ValidationError => e
326
+ puts "āœ… Validation error caught: #{e.message}"
310
327
  end
311
328
 
312
- rescue => e
329
+ puts 'āœ… Error handling tests completed'
330
+ rescue StandardError => e
313
331
  puts "āŒ Error handling failed: #{e.message}"
314
332
  end
315
333
 
316
334
  # Final summary
317
335
  puts "\nšŸŽ‰ All offline tests completed successfully!"
318
- puts " The Langfuse Ruby SDK is ready for use!"
336
+ puts ' The Langfuse Ruby SDK is ready for use!'
319
337
  puts " Total events in queue: #{client.instance_variable_get(:@event_queue).length}"
320
338
 
321
339
  # Clean shutdown (kill background thread)
322
340
  client.instance_variable_get(:@flush_thread)&.kill
323
- puts " Background thread terminated"
341
+ puts ' Background thread terminated'
324
342
 
325
343
  puts "\nšŸ“š Next steps:"
326
- puts " 1. Set your real Langfuse API keys"
327
- puts " 2. Configure the correct host URL"
328
- puts " 3. Start using the SDK in your application"
329
- puts " 4. Check the examples/ directory for more usage patterns"
344
+ puts ' 1. Set your real Langfuse API keys'
345
+ puts ' 2. Configure the correct host URL'
346
+ puts ' 3. Start using the SDK in your application'
347
+ puts ' 4. Check the examples/ directory for more usage patterns'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: langfuse-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Sun
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-07-12 00:00:00.000000000 Z
11
+ date: 2025-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -28,30 +28,42 @@ dependencies:
28
28
  name: faraday
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '2.0'
33
+ version: '1.8'
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: '3.0'
34
37
  type: :runtime
35
38
  prerelease: false
36
39
  version_requirements: !ruby/object:Gem::Requirement
37
40
  requirements:
38
- - - "~>"
41
+ - - ">="
39
42
  - !ruby/object:Gem::Version
40
- version: '2.0'
43
+ version: '1.8'
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: '3.0'
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: faraday-net_http
43
49
  requirement: !ruby/object:Gem::Requirement
44
50
  requirements:
45
- - - "~>"
51
+ - - ">="
46
52
  - !ruby/object:Gem::Version
47
- version: '3.0'
53
+ version: '1.0'
54
+ - - "<"
55
+ - !ruby/object:Gem::Version
56
+ version: '4.0'
48
57
  type: :runtime
49
58
  prerelease: false
50
59
  version_requirements: !ruby/object:Gem::Requirement
51
60
  requirements:
52
- - - "~>"
61
+ - - ">="
53
62
  - !ruby/object:Gem::Version
54
- version: '3.0'
63
+ version: '1.0'
64
+ - - "<"
65
+ - !ruby/object:Gem::Version
66
+ version: '4.0'
55
67
  - !ruby/object:Gem::Dependency
56
68
  name: json
57
69
  requirement: !ruby/object:Gem::Requirement
@@ -185,14 +197,18 @@ files:
185
197
  - docs/PUBLISH_GUIDE.md
186
198
  - docs/README.md
187
199
  - docs/RELEASE_CHECKLIST.md
200
+ - docs/TYPE_VALIDATION_TROUBLESHOOTING.md
201
+ - examples/auto_flush_control.rb
188
202
  - examples/basic_tracing.rb
189
203
  - examples/connection_config_demo.rb
204
+ - examples/event_usage.rb
190
205
  - examples/prompt_management.rb
191
206
  - langfuse-ruby.gemspec
192
207
  - lib/langfuse.rb
193
208
  - lib/langfuse/client.rb
194
209
  - lib/langfuse/errors.rb
195
210
  - lib/langfuse/evaluation.rb
211
+ - lib/langfuse/event.rb
196
212
  - lib/langfuse/generation.rb
197
213
  - lib/langfuse/prompt.rb
198
214
  - lib/langfuse/span.rb