langfuse-ruby 0.1.0

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 ADDED
@@ -0,0 +1,329 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative 'lib/langfuse'
4
+
5
+ puts "🚀 Testing Langfuse Ruby SDK (Offline Mode)..."
6
+
7
+ # Test 1: Basic configuration
8
+ puts "\n1. Testing configuration..."
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
14
+ end
15
+
16
+ puts "✅ Configuration successful"
17
+
18
+ # Test 2: Client initialization
19
+ puts "\n2. Testing client initialization..."
20
+ begin
21
+ client = Langfuse.new(
22
+ public_key: "test_key",
23
+ secret_key: "test_secret",
24
+ host: "https://test.langfuse.com",
25
+ debug: false
26
+ )
27
+ puts "✅ Client initialization successful"
28
+ rescue => e
29
+ puts "❌ Client initialization failed: #{e.message}"
30
+ end
31
+
32
+ # Test 3: Trace creation (no network)
33
+ puts "\n3. Testing trace creation..."
34
+ begin
35
+ trace = client.trace(
36
+ name: "test-trace",
37
+ user_id: "test-user",
38
+ input: { message: "Hello, world!" }
39
+ )
40
+ puts "✅ Trace creation successful"
41
+ puts " Trace ID: #{trace.id}"
42
+ rescue => e
43
+ puts "❌ Trace creation failed: #{e.message}"
44
+ end
45
+
46
+ # Test 4: Generation creation (no network)
47
+ puts "\n4. Testing generation creation..."
48
+ begin
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!" }
54
+ )
55
+ puts "✅ Generation creation successful"
56
+ puts " Generation ID: #{generation.id}"
57
+ rescue => e
58
+ puts "❌ Generation creation failed: #{e.message}"
59
+ end
60
+
61
+ # Test 5: Prompt template
62
+ puts "\n5. Testing prompt template..."
63
+ begin
64
+ template = Langfuse::PromptTemplate.from_template(
65
+ "Hello {{name}}! How are you feeling {{mood}} today?"
66
+ )
67
+
68
+ formatted = template.format(
69
+ name: "Alice",
70
+ mood: "happy"
71
+ )
72
+
73
+ puts "✅ Prompt template successful"
74
+ puts " Variables: #{template.input_variables}"
75
+ puts " Formatted: #{formatted}"
76
+ rescue => e
77
+ puts "❌ Prompt template failed: #{e.message}"
78
+ end
79
+
80
+ # Test 6: Chat prompt template
81
+ puts "\n6. Testing chat prompt template..."
82
+ begin
83
+ chat_template = Langfuse::ChatPromptTemplate.from_messages([
84
+ { role: "system", content: "You are a helpful {{role}} assistant." },
85
+ { role: "user", content: "{{user_input}}" }
86
+ ])
87
+
88
+ messages = chat_template.format(
89
+ role: "coding",
90
+ user_input: "Help me with Ruby"
91
+ )
92
+
93
+ puts "✅ Chat prompt template successful"
94
+ puts " Variables: #{chat_template.input_variables}"
95
+ puts " Messages: #{messages.length}"
96
+ rescue => e
97
+ puts "❌ Chat prompt template failed: #{e.message}"
98
+ end
99
+
100
+ # Test 7: Evaluators
101
+ puts "\n7. Testing evaluators..."
102
+ begin
103
+ # Exact match evaluator
104
+ exact_match = Langfuse::Evaluators::ExactMatchEvaluator.new
105
+ result = exact_match.evaluate(
106
+ "What is 2+2?",
107
+ "4",
108
+ expected: "4"
109
+ )
110
+ puts "✅ Exact match evaluator: #{result}"
111
+
112
+ # Similarity evaluator
113
+ similarity = Langfuse::Evaluators::SimilarityEvaluator.new
114
+ result = similarity.evaluate(
115
+ "What is AI?",
116
+ "Artificial Intelligence",
117
+ expected: "AI is artificial intelligence"
118
+ )
119
+ puts "✅ Similarity evaluator: #{result}"
120
+
121
+ # Length evaluator
122
+ length = Langfuse::Evaluators::LengthEvaluator.new(min_length: 5, max_length: 20)
123
+ result = length.evaluate(
124
+ "Test input",
125
+ "This is a test",
126
+ expected: nil
127
+ )
128
+ puts "✅ Length evaluator: #{result}"
129
+
130
+ # Contains evaluator
131
+ contains = Langfuse::Evaluators::ContainsEvaluator.new
132
+ result = contains.evaluate(
133
+ "Find Ruby",
134
+ "Ruby programming language",
135
+ expected: "Ruby"
136
+ )
137
+ puts "✅ Contains evaluator: #{result}"
138
+
139
+ # Regex evaluator
140
+ regex = Langfuse::Evaluators::RegexEvaluator.new(pattern: /\d+/)
141
+ result = regex.evaluate(
142
+ "Find numbers",
143
+ "There are 42 apples",
144
+ expected: nil
145
+ )
146
+ puts "✅ Regex evaluator: #{result}"
147
+
148
+ rescue => e
149
+ puts "❌ Evaluator failed: #{e.message}"
150
+ end
151
+
152
+ # Test 8: Utils
153
+ puts "\n8. Testing utilities..."
154
+ begin
155
+ id = Langfuse::Utils.generate_id
156
+ timestamp = Langfuse::Utils.current_timestamp
157
+
158
+ # Test data transformation
159
+ hash_data = { "key1" => "value1", "nested" => { "key2" => "value2" } }
160
+ symbolized = Langfuse::Utils.deep_symbolize_keys(hash_data)
161
+ stringified = Langfuse::Utils.deep_stringify_keys(symbolized)
162
+
163
+ puts "✅ Utils successful"
164
+ puts " ID: #{id[0..8]}..."
165
+ puts " Timestamp: #{timestamp}"
166
+ puts " Symbolized keys: #{symbolized.keys}"
167
+ puts " Stringified keys: #{stringified.keys}"
168
+ rescue => e
169
+ puts "❌ Utils failed: #{e.message}"
170
+ end
171
+
172
+ # Test 9: Event queue (without network)
173
+ puts "\n9. Testing event queue..."
174
+ begin
175
+ queue_size_before = client.instance_variable_get(:@event_queue).length
176
+
177
+ # Add some events
178
+ client.score(
179
+ trace_id: trace.id,
180
+ name: "test-score",
181
+ value: 0.9
182
+ )
183
+
184
+ trace.score(
185
+ name: "trace-score",
186
+ value: 0.8
187
+ )
188
+
189
+ generation.score(
190
+ name: "generation-score",
191
+ value: 0.95
192
+ )
193
+
194
+ queue_size_after = client.instance_variable_get(:@event_queue).length
195
+
196
+ puts "✅ Event queue successful"
197
+ puts " Events added: #{queue_size_after - queue_size_before}"
198
+ puts " Total events: #{queue_size_after}"
199
+ rescue => e
200
+ puts "❌ Event queue failed: #{e.message}"
201
+ end
202
+
203
+ # Test 10: Complex workflow
204
+ puts "\n10. Testing complex workflow..."
205
+ begin
206
+ # Create a complex trace with nested spans
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" },
212
+ metadata: {
213
+ environment: "test",
214
+ version: "1.0.0",
215
+ tags: ["physics", "computing"]
216
+ }
217
+ )
218
+
219
+ # Document retrieval span
220
+ retrieval_span = complex_trace.span(
221
+ name: "document-retrieval",
222
+ input: { query: "quantum computing basics" }
223
+ )
224
+
225
+ # Embedding generation
226
+ embedding_gen = retrieval_span.generation(
227
+ name: "embedding-generation",
228
+ model: "text-embedding-ada-002",
229
+ input: "quantum computing basics",
230
+ output: Array.new(1536) { rand(-1.0..1.0) }, # Mock embedding
231
+ usage: { prompt_tokens: 4, total_tokens: 4 }
232
+ )
233
+
234
+ retrieval_span.end(
235
+ output: {
236
+ documents: [
237
+ "Quantum computing uses quantum bits...",
238
+ "Quantum algorithms can solve certain problems..."
239
+ ]
240
+ }
241
+ )
242
+
243
+ # Answer generation span
244
+ answer_span = complex_trace.span(
245
+ name: "answer-generation",
246
+ input: {
247
+ query: "Explain quantum computing",
248
+ context: ["Quantum computing uses quantum bits...", "Quantum algorithms can solve certain problems..."]
249
+ }
250
+ )
251
+
252
+ # LLM generation
253
+ llm_gen = answer_span.generation(
254
+ name: "openai-completion",
255
+ model: "gpt-4",
256
+ input: [
257
+ { role: "system", content: "You are a physics expert." },
258
+ { role: "user", content: "Explain quantum computing based on the context." }
259
+ ],
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."
262
+ },
263
+ usage: {
264
+ prompt_tokens: 120,
265
+ completion_tokens: 45,
266
+ total_tokens: 165
267
+ },
268
+ model_parameters: {
269
+ temperature: 0.7,
270
+ max_tokens: 200
271
+ }
272
+ )
273
+
274
+ answer_span.end(
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."
283
+ }
284
+ )
285
+
286
+ puts "✅ Complex workflow successful"
287
+ puts " Trace ID: #{complex_trace.id}"
288
+ puts " Spans created: 2"
289
+ puts " Generations created: 2"
290
+
291
+ rescue => e
292
+ puts "❌ Complex workflow failed: #{e.message}"
293
+ end
294
+
295
+ # Test 11: Error handling
296
+ puts "\n11. Testing error handling..."
297
+ begin
298
+ # Test validation error
299
+ begin
300
+ Langfuse::Utils.validate_required_fields({ name: "test" }, [:name, :required_field])
301
+ rescue Langfuse::ValidationError => e
302
+ puts "✅ Validation error caught: #{e.message}"
303
+ end
304
+
305
+ # Test authentication error
306
+ begin
307
+ Langfuse.new(public_key: nil, secret_key: "secret")
308
+ rescue Langfuse::AuthenticationError => e
309
+ puts "✅ Authentication error caught: #{e.message}"
310
+ end
311
+
312
+ rescue => e
313
+ puts "❌ Error handling failed: #{e.message}"
314
+ end
315
+
316
+ # Final summary
317
+ puts "\n🎉 All offline tests completed successfully!"
318
+ puts " The Langfuse Ruby SDK is ready for use!"
319
+ puts " Total events in queue: #{client.instance_variable_get(:@event_queue).length}"
320
+
321
+ # Clean shutdown (kill background thread)
322
+ client.instance_variable_get(:@flush_thread)&.kill
323
+ puts " Background thread terminated"
324
+
325
+ 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"
metadata ADDED
@@ -0,0 +1,232 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: langfuse-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Your Name
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2025-07-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: concurrent-ruby
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: faraday-net_http
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: json
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '13.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '13.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: vcr
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '6.0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '6.0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: webmock
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '3.0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '3.0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: yard
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '0.9'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '0.9'
167
+ description: Ruby client library for Langfuse, providing tracing, prompt management,
168
+ and evaluation capabilities for LLM applications
169
+ email:
170
+ - your.email@example.com
171
+ executables: []
172
+ extensions: []
173
+ extra_rdoc_files: []
174
+ files:
175
+ - ".github/workflows/ci.yml"
176
+ - ".github/workflows/release.yml"
177
+ - ".gitignore"
178
+ - CHANGELOG.md
179
+ - FINAL_SUMMARY.md
180
+ - Gemfile
181
+ - Gemfile.lock
182
+ - LICENSE
183
+ - PROJECT_SUMMARY.md
184
+ - PUBLISH_GUIDE.md
185
+ - README.md
186
+ - RELEASE_CHECKLIST.md
187
+ - Rakefile
188
+ - examples/basic_tracing.rb
189
+ - examples/prompt_management.rb
190
+ - langfuse-ruby.gemspec
191
+ - lib/langfuse.rb
192
+ - lib/langfuse/client.rb
193
+ - lib/langfuse/errors.rb
194
+ - lib/langfuse/evaluation.rb
195
+ - lib/langfuse/generation.rb
196
+ - lib/langfuse/prompt.rb
197
+ - lib/langfuse/span.rb
198
+ - lib/langfuse/trace.rb
199
+ - lib/langfuse/utils.rb
200
+ - lib/langfuse/version.rb
201
+ - scripts/release.sh
202
+ - scripts/verify_release.rb
203
+ - test_basic.rb
204
+ - test_offline.rb
205
+ homepage: https://github.com/your-username/langfuse-ruby
206
+ licenses:
207
+ - MIT
208
+ metadata:
209
+ allowed_push_host: https://rubygems.org
210
+ homepage_uri: https://github.com/your-username/langfuse-ruby
211
+ source_code_uri: https://github.com/your-username/langfuse-ruby
212
+ changelog_uri: https://github.com/your-username/langfuse-ruby/blob/main/CHANGELOG.md
213
+ post_install_message:
214
+ rdoc_options: []
215
+ require_paths:
216
+ - lib
217
+ required_ruby_version: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - ">="
220
+ - !ruby/object:Gem::Version
221
+ version: 2.7.0
222
+ required_rubygems_version: !ruby/object:Gem::Requirement
223
+ requirements:
224
+ - - ">="
225
+ - !ruby/object:Gem::Version
226
+ version: '0'
227
+ requirements: []
228
+ rubygems_version: 3.5.11
229
+ signing_key:
230
+ specification_version: 4
231
+ summary: Ruby SDK for Langfuse - Open source LLM engineering platform
232
+ test_files: []