langfuse-ruby 0.1.2 → 0.1.3
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/Gemfile.lock +1 -1
- data/README.md +111 -20
- data/docs/TYPE_VALIDATION_TROUBLESHOOTING.md +202 -0
- data/examples/auto_flush_control.rb +205 -0
- data/examples/basic_tracing.rb +0 -12
- data/examples/connection_config_demo.rb +15 -1
- data/examples/event_usage.rb +145 -0
- data/lib/langfuse/client.rb +161 -52
- data/lib/langfuse/event.rb +63 -0
- data/lib/langfuse/generation.rb +19 -40
- data/lib/langfuse/span.rb +17 -0
- data/lib/langfuse/trace.rb +17 -34
- data/lib/langfuse/utils.rb +23 -1
- data/lib/langfuse/version.rb +1 -1
- data/lib/langfuse.rb +4 -1
- data/test_offline.rb +93 -101
- metadata +6 -3
- data/.github/workflows/ci.yml +0 -47
data/lib/langfuse/trace.rb
CHANGED
@@ -24,23 +24,6 @@ module Langfuse
|
|
24
24
|
create_trace
|
25
25
|
end
|
26
26
|
|
27
|
-
def update(name: nil, user_id: nil, session_id: nil, version: nil, release: nil,
|
28
|
-
input: nil, output: nil, metadata: nil, tags: nil, **kwargs)
|
29
|
-
@name = name if name
|
30
|
-
@user_id = user_id if user_id
|
31
|
-
@session_id = session_id if session_id
|
32
|
-
@version = version if version
|
33
|
-
@release = release if release
|
34
|
-
@input = input if input
|
35
|
-
@output = output if output
|
36
|
-
@metadata.merge!(metadata) if metadata
|
37
|
-
@tags.concat(tags) if tags
|
38
|
-
@kwargs.merge!(kwargs)
|
39
|
-
|
40
|
-
update_trace
|
41
|
-
self
|
42
|
-
end
|
43
|
-
|
44
27
|
def span(name: nil, start_time: nil, end_time: nil, input: nil, output: nil,
|
45
28
|
metadata: nil, level: nil, status_message: nil, parent_observation_id: nil,
|
46
29
|
version: nil, **kwargs)
|
@@ -84,6 +67,23 @@ module Langfuse
|
|
84
67
|
)
|
85
68
|
end
|
86
69
|
|
70
|
+
def event(name:, start_time: nil, input: nil, output: nil, metadata: nil,
|
71
|
+
level: nil, status_message: nil, parent_observation_id: nil, version: nil, **kwargs)
|
72
|
+
@client.event(
|
73
|
+
trace_id: @id,
|
74
|
+
name: name,
|
75
|
+
start_time: start_time,
|
76
|
+
input: input,
|
77
|
+
output: output,
|
78
|
+
metadata: metadata,
|
79
|
+
level: level,
|
80
|
+
status_message: status_message,
|
81
|
+
parent_observation_id: parent_observation_id,
|
82
|
+
version: version,
|
83
|
+
**kwargs
|
84
|
+
)
|
85
|
+
end
|
86
|
+
|
87
87
|
def score(name:, value:, data_type: nil, comment: nil, **kwargs)
|
88
88
|
@client.score(
|
89
89
|
trace_id: @id,
|
@@ -134,22 +134,5 @@ module Langfuse
|
|
134
134
|
|
135
135
|
@client.enqueue_event('trace-create', data)
|
136
136
|
end
|
137
|
-
|
138
|
-
def update_trace
|
139
|
-
data = {
|
140
|
-
id: @id,
|
141
|
-
name: @name,
|
142
|
-
user_id: @user_id,
|
143
|
-
session_id: @session_id,
|
144
|
-
version: @version,
|
145
|
-
release: @release,
|
146
|
-
input: @input,
|
147
|
-
output: @output,
|
148
|
-
metadata: @metadata,
|
149
|
-
tags: @tags
|
150
|
-
}.merge(@kwargs).compact
|
151
|
-
|
152
|
-
@client.enqueue_event('trace-update', data)
|
153
|
-
end
|
154
137
|
end
|
155
138
|
end
|
data/lib/langfuse/utils.rb
CHANGED
@@ -26,12 +26,34 @@ module Langfuse
|
|
26
26
|
return hash unless hash.is_a?(Hash)
|
27
27
|
|
28
28
|
hash.each_with_object({}) do |(key, value), result|
|
29
|
-
new_key = key.to_s
|
29
|
+
new_key = camelize_key(key.to_s)
|
30
30
|
new_value = value.is_a?(Hash) ? deep_stringify_keys(value) : value
|
31
31
|
result[new_key] = new_value
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
+
# 将哈希的键名转换为小驼峰格式
|
36
|
+
def deep_camelize_keys(hash)
|
37
|
+
return hash unless hash.is_a?(Hash)
|
38
|
+
|
39
|
+
hash.each_with_object({}) do |(key, value), result|
|
40
|
+
new_key = camelize_key(key.to_s)
|
41
|
+
new_value = value.is_a?(Hash) ? deep_camelize_keys(value) : value
|
42
|
+
result[new_key] = new_value
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# 将蛇形命名转换为小驼峰命名
|
49
|
+
def camelize_key(key)
|
50
|
+
return key if key.empty? || !key.include?('_')
|
51
|
+
|
52
|
+
key.split('_').map.with_index do |part, index|
|
53
|
+
index.zero? ? part.downcase : part.capitalize
|
54
|
+
end.join
|
55
|
+
end
|
56
|
+
|
35
57
|
def validate_required_fields(data, required_fields)
|
36
58
|
missing_fields = required_fields.select { |field| data[field].nil? || data[field].to_s.empty? }
|
37
59
|
raise ValidationError, "Missing required fields: #{missing_fields.join(', ')}" unless missing_fields.empty?
|
data/lib/langfuse/version.rb
CHANGED
data/lib/langfuse.rb
CHANGED
@@ -5,6 +5,7 @@ require_relative 'langfuse/client'
|
|
5
5
|
require_relative 'langfuse/trace'
|
6
6
|
require_relative 'langfuse/span'
|
7
7
|
require_relative 'langfuse/generation'
|
8
|
+
require_relative 'langfuse/event'
|
8
9
|
require_relative 'langfuse/prompt'
|
9
10
|
require_relative 'langfuse/evaluation'
|
10
11
|
require_relative 'langfuse/errors'
|
@@ -30,7 +31,7 @@ module Langfuse
|
|
30
31
|
|
31
32
|
# Configuration class for Langfuse client settings
|
32
33
|
class Configuration
|
33
|
-
attr_accessor :public_key, :secret_key, :host, :debug, :timeout, :retries
|
34
|
+
attr_accessor :public_key, :secret_key, :host, :debug, :timeout, :retries, :flush_interval, :auto_flush
|
34
35
|
|
35
36
|
def initialize
|
36
37
|
@public_key = nil
|
@@ -39,6 +40,8 @@ module Langfuse
|
|
39
40
|
@debug = false
|
40
41
|
@timeout = 30
|
41
42
|
@retries = 3
|
43
|
+
@flush_interval = 5
|
44
|
+
@auto_flush = true
|
42
45
|
end
|
43
46
|
end
|
44
47
|
end
|
data/test_offline.rb
CHANGED
@@ -2,30 +2,30 @@
|
|
2
2
|
|
3
3
|
require_relative 'lib/langfuse'
|
4
4
|
|
5
|
-
puts
|
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 =
|
11
|
-
config.secret_key =
|
12
|
-
config.host =
|
13
|
-
config.debug = false
|
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
|
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:
|
23
|
-
secret_key:
|
24
|
-
host:
|
22
|
+
public_key: 'test_key',
|
23
|
+
secret_key: 'test_secret',
|
24
|
+
host: 'https://test.langfuse.com',
|
25
25
|
debug: false
|
26
26
|
)
|
27
|
-
puts
|
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:
|
37
|
-
user_id:
|
38
|
-
input: { message:
|
36
|
+
name: 'test-trace',
|
37
|
+
user_id: 'test-user',
|
38
|
+
input: { message: 'Hello, world!' }
|
39
39
|
)
|
40
|
-
puts
|
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:
|
51
|
-
model:
|
52
|
-
input: [{ role:
|
53
|
-
output: { content:
|
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
|
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
|
-
|
65
|
+
'Hello {{name}}! How are you feeling {{mood}} today?'
|
66
66
|
)
|
67
67
|
|
68
68
|
formatted = template.format(
|
69
|
-
name:
|
70
|
-
mood:
|
69
|
+
name: 'Alice',
|
70
|
+
mood: 'happy'
|
71
71
|
)
|
72
72
|
|
73
|
-
puts
|
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
|
-
|
85
|
-
|
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:
|
90
|
-
user_input:
|
90
|
+
role: 'coding',
|
91
|
+
user_input: 'Help me with Ruby'
|
91
92
|
)
|
92
93
|
|
93
|
-
puts
|
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
|
-
|
107
|
-
|
108
|
-
expected:
|
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
|
-
|
116
|
-
|
117
|
-
expected:
|
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
|
-
|
125
|
-
|
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
|
-
|
134
|
-
|
135
|
-
expected:
|
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
|
-
|
143
|
-
|
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 = {
|
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
|
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:
|
180
|
+
name: 'test-score',
|
181
181
|
value: 0.9
|
182
182
|
)
|
183
183
|
|
184
184
|
trace.score(
|
185
|
-
name:
|
185
|
+
name: 'trace-score',
|
186
186
|
value: 0.8
|
187
187
|
)
|
188
188
|
|
189
189
|
generation.score(
|
190
|
-
name:
|
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
|
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:
|
209
|
-
user_id:
|
210
|
-
session_id:
|
211
|
-
input: { query:
|
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:
|
214
|
-
version:
|
215
|
-
tags: [
|
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:
|
222
|
-
input: { query:
|
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:
|
228
|
-
model:
|
229
|
-
input:
|
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
|
-
|
238
|
-
|
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:
|
245
|
+
name: 'answer-generation',
|
246
246
|
input: {
|
247
|
-
query:
|
248
|
-
context: [
|
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:
|
255
|
-
model:
|
254
|
+
name: 'openai-completion',
|
255
|
+
model: 'gpt-4',
|
256
256
|
input: [
|
257
|
-
{ role:
|
258
|
-
{ role:
|
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:
|
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,22 +273,15 @@ begin
|
|
273
273
|
|
274
274
|
answer_span.end(
|
275
275
|
output: {
|
276
|
-
answer:
|
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
277
|
}
|
278
278
|
)
|
279
279
|
|
280
|
-
|
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"
|
280
|
+
puts '✅ Complex workflow successful'
|
287
281
|
puts " Trace ID: #{complex_trace.id}"
|
288
|
-
puts
|
289
|
-
puts
|
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
|
|
@@ -297,33 +290,32 @@ puts "\n11. Testing error handling..."
|
|
297
290
|
begin
|
298
291
|
# Test validation error
|
299
292
|
begin
|
300
|
-
Langfuse::Utils.validate_required_fields({ name:
|
293
|
+
Langfuse::Utils.validate_required_fields({ name: 'test' }, %i[name required_field])
|
301
294
|
rescue Langfuse::ValidationError => e
|
302
295
|
puts "✅ Validation error caught: #{e.message}"
|
303
296
|
end
|
304
297
|
|
305
298
|
# Test authentication error
|
306
299
|
begin
|
307
|
-
Langfuse.new(public_key: nil, secret_key:
|
300
|
+
Langfuse.new(public_key: nil, secret_key: 'secret')
|
308
301
|
rescue Langfuse::AuthenticationError => e
|
309
302
|
puts "✅ Authentication error caught: #{e.message}"
|
310
303
|
end
|
311
|
-
|
312
|
-
rescue => e
|
304
|
+
rescue StandardError => e
|
313
305
|
puts "❌ Error handling failed: #{e.message}"
|
314
306
|
end
|
315
307
|
|
316
308
|
# Final summary
|
317
309
|
puts "\n🎉 All offline tests completed successfully!"
|
318
|
-
puts
|
310
|
+
puts ' The Langfuse Ruby SDK is ready for use!'
|
319
311
|
puts " Total events in queue: #{client.instance_variable_get(:@event_queue).length}"
|
320
312
|
|
321
313
|
# Clean shutdown (kill background thread)
|
322
314
|
client.instance_variable_get(:@flush_thread)&.kill
|
323
|
-
puts
|
315
|
+
puts ' Background thread terminated'
|
324
316
|
|
325
317
|
puts "\n📚 Next steps:"
|
326
|
-
puts
|
327
|
-
puts
|
328
|
-
puts
|
329
|
-
puts
|
318
|
+
puts ' 1. Set your real Langfuse API keys'
|
319
|
+
puts ' 2. Configure the correct host URL'
|
320
|
+
puts ' 3. Start using the SDK in your application'
|
321
|
+
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.
|
4
|
+
version: 0.1.3
|
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-
|
11
|
+
date: 2025-07-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -172,7 +172,6 @@ executables: []
|
|
172
172
|
extensions: []
|
173
173
|
extra_rdoc_files: []
|
174
174
|
files:
|
175
|
-
- ".github/workflows/ci.yml"
|
176
175
|
- ".github/workflows/release.yml"
|
177
176
|
- ".gitignore"
|
178
177
|
- CHANGELOG.md
|
@@ -185,14 +184,18 @@ files:
|
|
185
184
|
- docs/PUBLISH_GUIDE.md
|
186
185
|
- docs/README.md
|
187
186
|
- docs/RELEASE_CHECKLIST.md
|
187
|
+
- docs/TYPE_VALIDATION_TROUBLESHOOTING.md
|
188
|
+
- examples/auto_flush_control.rb
|
188
189
|
- examples/basic_tracing.rb
|
189
190
|
- examples/connection_config_demo.rb
|
191
|
+
- examples/event_usage.rb
|
190
192
|
- examples/prompt_management.rb
|
191
193
|
- langfuse-ruby.gemspec
|
192
194
|
- lib/langfuse.rb
|
193
195
|
- lib/langfuse/client.rb
|
194
196
|
- lib/langfuse/errors.rb
|
195
197
|
- lib/langfuse/evaluation.rb
|
198
|
+
- lib/langfuse/event.rb
|
196
199
|
- lib/langfuse/generation.rb
|
197
200
|
- lib/langfuse/prompt.rb
|
198
201
|
- lib/langfuse/span.rb
|
data/.github/workflows/ci.yml
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
name: CI
|
2
|
-
|
3
|
-
on:
|
4
|
-
push:
|
5
|
-
branches: [ main ]
|
6
|
-
pull_request:
|
7
|
-
branches: [ main ]
|
8
|
-
|
9
|
-
jobs:
|
10
|
-
test:
|
11
|
-
runs-on: ubuntu-latest
|
12
|
-
strategy:
|
13
|
-
matrix:
|
14
|
-
ruby-version: ['2.7', '3.0', '3.1', '3.2']
|
15
|
-
|
16
|
-
steps:
|
17
|
-
- uses: actions/checkout@v4
|
18
|
-
|
19
|
-
- name: Set up Ruby ${{ matrix.ruby-version }}
|
20
|
-
uses: ruby/setup-ruby@v1
|
21
|
-
with:
|
22
|
-
ruby-version: ${{ matrix.ruby-version }}
|
23
|
-
bundler-cache: true
|
24
|
-
|
25
|
-
- name: Run tests
|
26
|
-
run: bundle exec rspec
|
27
|
-
|
28
|
-
- name: Run offline tests
|
29
|
-
run: ruby test_offline.rb
|
30
|
-
|
31
|
-
- name: Check gem build
|
32
|
-
run: gem build langfuse.gemspec
|
33
|
-
|
34
|
-
lint:
|
35
|
-
runs-on: ubuntu-latest
|
36
|
-
steps:
|
37
|
-
- uses: actions/checkout@v4
|
38
|
-
|
39
|
-
- name: Set up Ruby
|
40
|
-
uses: ruby/setup-ruby@v1
|
41
|
-
with:
|
42
|
-
ruby-version: '3.2'
|
43
|
-
bundler-cache: true
|
44
|
-
|
45
|
-
- name: Run RuboCop
|
46
|
-
run: bundle exec rubocop
|
47
|
-
continue-on-error: true
|