langfuse-ruby 0.2.0 → 0.2.1
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/.rubocop.yml +1 -1
- data/CHANGELOG.md +44 -0
- data/CLAUDE.md +40 -14
- data/Gemfile.lock +1 -1
- data/Makefile +1 -4
- data/README.md +216 -99
- data/Rakefile +0 -6
- data/docs/FINAL_SUMMARY.md +12 -185
- data/docs/PUBLISH_GUIDE.md +36 -272
- data/docs/README.md +12 -22
- data/docs/RELEASE_CHECKLIST.md +20 -145
- data/docs/V4.md +159 -0
- data/examples/basic_tracing.rb +11 -10
- data/examples/simplified_usage.rb +7 -6
- data/examples/v4_otel_tracing.rb +70 -0
- data/lib/langfuse/client.rb +457 -247
- data/lib/langfuse/event.rb +1 -17
- data/lib/langfuse/generation.rb +35 -120
- data/lib/langfuse/null_objects.rb +4 -0
- data/lib/langfuse/otel_exporter.rb +101 -11
- data/lib/langfuse/partial_updates.rb +30 -0
- data/lib/langfuse/prompt.rb +9 -83
- data/lib/langfuse/prompt_cache.rb +65 -0
- data/lib/langfuse/span.rb +28 -153
- data/lib/langfuse/span_wrappers.rb +32 -0
- data/lib/langfuse/template_compiler.rb +56 -0
- data/lib/langfuse/trace.rb +26 -162
- data/lib/langfuse/utils.rb +28 -26
- data/lib/langfuse/version.rb +1 -1
- data/lib/langfuse.rb +49 -52
- data/scripts/release.sh +12 -12
- metadata +8 -2
data/lib/langfuse.rb
CHANGED
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative 'langfuse/version'
|
|
4
4
|
require_relative 'langfuse/observation_types'
|
|
5
|
+
require_relative 'langfuse/span_wrappers'
|
|
6
|
+
require_relative 'langfuse/partial_updates'
|
|
7
|
+
require_relative 'langfuse/template_compiler'
|
|
5
8
|
require_relative 'langfuse/client'
|
|
6
9
|
require_relative 'langfuse/trace'
|
|
7
10
|
require_relative 'langfuse/span'
|
|
8
11
|
require_relative 'langfuse/generation'
|
|
9
12
|
require_relative 'langfuse/event'
|
|
10
13
|
require_relative 'langfuse/prompt'
|
|
14
|
+
require_relative 'langfuse/prompt_cache'
|
|
11
15
|
require_relative 'langfuse/evaluation'
|
|
12
16
|
require_relative 'langfuse/errors'
|
|
13
17
|
require_relative 'langfuse/utils'
|
|
@@ -47,29 +51,23 @@ module Langfuse
|
|
|
47
51
|
# @param cache_ttl_seconds [Integer] cache TTL in seconds (default: 60)
|
|
48
52
|
# @param retries [Integer] number of retries on failure (default: 2)
|
|
49
53
|
# @return [String, Prompt, nil] compiled prompt string if variables provided, Prompt object otherwise, nil on failure
|
|
54
|
+
# `retries` is applied inside the HTTP layer, which retries only transient
|
|
55
|
+
# failures (timeout, network, 429, 5xx), honors Retry-After and backs off with
|
|
56
|
+
# jitter. A missing prompt therefore fails immediately instead of being
|
|
57
|
+
# requested three times.
|
|
50
58
|
def get_prompt(prompt_name, variables: nil, label: nil, version: nil, cache_ttl_seconds: 60, retries: 2)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
prompt.compile(variables)
|
|
59
|
-
else
|
|
60
|
-
prompt
|
|
61
|
-
end
|
|
62
|
-
rescue StandardError => e
|
|
63
|
-
if attempts <= retries
|
|
64
|
-
sleep_time = (2**(attempts - 1)) * 0.1 # Exponential backoff: 0.1s, 0.2s, 0.4s...
|
|
65
|
-
warn "Langfuse prompt fetch failed (#{prompt_name}), retrying in #{sleep_time}s... (attempt #{attempts}/#{retries + 1})" if configuration.debug
|
|
66
|
-
sleep(sleep_time)
|
|
67
|
-
retry
|
|
68
|
-
end
|
|
59
|
+
prompt = client.get_prompt(
|
|
60
|
+
prompt_name,
|
|
61
|
+
label: label,
|
|
62
|
+
version: version,
|
|
63
|
+
cache_ttl_seconds: cache_ttl_seconds,
|
|
64
|
+
retries: retries
|
|
65
|
+
)
|
|
69
66
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
67
|
+
variables ? prompt.compile(variables) : prompt
|
|
68
|
+
rescue StandardError => e
|
|
69
|
+
warn "Langfuse prompt fetch failed (#{prompt_name}): #{e.message}" if configuration.debug
|
|
70
|
+
nil
|
|
73
71
|
end
|
|
74
72
|
|
|
75
73
|
# Create a trace and optionally execute a block with it
|
|
@@ -103,38 +101,34 @@ module Langfuse
|
|
|
103
101
|
#
|
|
104
102
|
def trace(name = nil, user_id: nil, session_id: nil, input: nil, output: nil,
|
|
105
103
|
metadata: nil, tags: nil, version: nil, release: nil, **kwargs)
|
|
106
|
-
trace
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
input: input,
|
|
111
|
-
output: output,
|
|
112
|
-
metadata: metadata,
|
|
113
|
-
tags: tags,
|
|
114
|
-
version: version,
|
|
115
|
-
release: release,
|
|
116
|
-
**kwargs
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
if block_given?
|
|
104
|
+
# Only trace creation degrades to a NullTrace. An exception raised by the
|
|
105
|
+
# block must propagate: rescuing it here and yielding again would run the
|
|
106
|
+
# caller's block a second time (duplicate LLM calls and billing).
|
|
107
|
+
trace =
|
|
120
108
|
begin
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
109
|
+
client.trace(
|
|
110
|
+
name: name,
|
|
111
|
+
user_id: user_id,
|
|
112
|
+
session_id: session_id,
|
|
113
|
+
input: input,
|
|
114
|
+
output: output,
|
|
115
|
+
metadata: metadata,
|
|
116
|
+
tags: tags,
|
|
117
|
+
version: version,
|
|
118
|
+
release: release,
|
|
119
|
+
**kwargs
|
|
120
|
+
)
|
|
121
|
+
rescue StandardError => e
|
|
122
|
+
warn "Langfuse trace creation failed: #{e.message}" if configuration.debug
|
|
123
|
+
NullTrace.new
|
|
125
124
|
end
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
if block_given?
|
|
134
|
-
null_trace = NullTrace.new
|
|
135
|
-
yield(null_trace)
|
|
136
|
-
else
|
|
137
|
-
NullTrace.new
|
|
125
|
+
|
|
126
|
+
return trace unless block_given?
|
|
127
|
+
|
|
128
|
+
begin
|
|
129
|
+
yield(trace)
|
|
130
|
+
ensure
|
|
131
|
+
flush
|
|
138
132
|
end
|
|
139
133
|
end
|
|
140
134
|
|
|
@@ -161,7 +155,8 @@ module Langfuse
|
|
|
161
155
|
# Configuration class for Langfuse client settings
|
|
162
156
|
class Configuration
|
|
163
157
|
attr_accessor :public_key, :secret_key, :host, :debug, :timeout, :retries, :flush_interval, :auto_flush,
|
|
164
|
-
:ingestion_mode, :environment, :sample_rate, :mask, :flush_at, :
|
|
158
|
+
:ingestion_mode, :environment, :sample_rate, :mask, :flush_at, :max_queue_size, :logger,
|
|
159
|
+
:shutdown_on_exit, :http_adapter
|
|
165
160
|
|
|
166
161
|
def initialize
|
|
167
162
|
@public_key = nil
|
|
@@ -177,8 +172,10 @@ module Langfuse
|
|
|
177
172
|
@sample_rate = nil # 0.0..1.0, nil disables sampling
|
|
178
173
|
@mask = nil # callable applied to input/output/metadata before sending
|
|
179
174
|
@flush_at = 15 # flush as soon as this many events are queued
|
|
175
|
+
@max_queue_size = 10_000 # queue cap; the oldest events are dropped when full
|
|
180
176
|
@logger = nil # custom Logger instance
|
|
181
177
|
@shutdown_on_exit = true # register an at_exit hook that flushes pending events
|
|
178
|
+
@http_adapter = nil # Faraday adapter, e.g. :net_http_persistent for keep-alive
|
|
182
179
|
end
|
|
183
180
|
end
|
|
184
181
|
end
|
data/scripts/release.sh
CHANGED
|
@@ -49,31 +49,31 @@ if ! bundle exec rspec; then
|
|
|
49
49
|
fi
|
|
50
50
|
|
|
51
51
|
print_status "Running offline tests..."
|
|
52
|
-
if ! ruby scripts/test_offline.rb; then
|
|
52
|
+
if ! bundle exec ruby scripts/test_offline.rb; then
|
|
53
53
|
print_error "Offline tests failed. Please fix them before releasing."
|
|
54
54
|
exit 1
|
|
55
55
|
fi
|
|
56
56
|
|
|
57
57
|
# Build gem
|
|
58
58
|
print_status "Building gem..."
|
|
59
|
-
if ! gem build langfuse.gemspec; then
|
|
59
|
+
if ! gem build langfuse-ruby.gemspec; then
|
|
60
60
|
print_error "Gem build failed."
|
|
61
61
|
exit 1
|
|
62
62
|
fi
|
|
63
63
|
|
|
64
64
|
# Check if gem was built successfully
|
|
65
|
-
if [ ! -f "langfuse-${CURRENT_VERSION}.gem" ]; then
|
|
66
|
-
print_error "Gem file not found: langfuse-${CURRENT_VERSION}.gem"
|
|
65
|
+
if [ ! -f "langfuse-ruby-${CURRENT_VERSION}.gem" ]; then
|
|
66
|
+
print_error "Gem file not found: langfuse-ruby-${CURRENT_VERSION}.gem"
|
|
67
67
|
exit 1
|
|
68
68
|
fi
|
|
69
69
|
|
|
70
|
-
print_status "Gem built successfully: langfuse-${CURRENT_VERSION}.gem"
|
|
70
|
+
print_status "Gem built successfully: langfuse-ruby-${CURRENT_VERSION}.gem"
|
|
71
71
|
|
|
72
72
|
# Ask for confirmation
|
|
73
73
|
echo
|
|
74
74
|
echo "📋 Release Summary:"
|
|
75
75
|
echo " Version: $CURRENT_VERSION"
|
|
76
|
-
echo " Gem file: langfuse-${CURRENT_VERSION}.gem"
|
|
76
|
+
echo " Gem file: langfuse-ruby-${CURRENT_VERSION}.gem"
|
|
77
77
|
echo " Tests: ✅ Passed"
|
|
78
78
|
echo
|
|
79
79
|
|
|
@@ -81,7 +81,7 @@ read -p "Do you want to proceed with the release? (y/N): " -n 1 -r
|
|
|
81
81
|
echo
|
|
82
82
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
83
83
|
print_warning "Release cancelled."
|
|
84
|
-
rm -f "langfuse-${CURRENT_VERSION}.gem"
|
|
84
|
+
rm -f "langfuse-ruby-${CURRENT_VERSION}.gem"
|
|
85
85
|
exit 0
|
|
86
86
|
fi
|
|
87
87
|
|
|
@@ -91,12 +91,12 @@ git tag "v${CURRENT_VERSION}"
|
|
|
91
91
|
|
|
92
92
|
# Push to git
|
|
93
93
|
print_status "Pushing to git..."
|
|
94
|
-
git push origin
|
|
94
|
+
git push origin master
|
|
95
95
|
git push origin "v${CURRENT_VERSION}"
|
|
96
96
|
|
|
97
97
|
# Publish to RubyGems
|
|
98
98
|
print_status "Publishing to RubyGems..."
|
|
99
|
-
if gem push "langfuse-${CURRENT_VERSION}.gem"; then
|
|
99
|
+
if gem push "langfuse-ruby-${CURRENT_VERSION}.gem"; then
|
|
100
100
|
print_status "Successfully published to RubyGems!"
|
|
101
101
|
else
|
|
102
102
|
print_error "Failed to publish to RubyGems."
|
|
@@ -105,16 +105,16 @@ else
|
|
|
105
105
|
fi
|
|
106
106
|
|
|
107
107
|
# Clean up
|
|
108
|
-
rm -f "langfuse-${CURRENT_VERSION}.gem"
|
|
108
|
+
rm -f "langfuse-ruby-${CURRENT_VERSION}.gem"
|
|
109
109
|
|
|
110
110
|
print_status "Release completed successfully! 🎉"
|
|
111
111
|
echo
|
|
112
112
|
echo "📝 Next steps:"
|
|
113
|
-
echo " 1. Check https://rubygems.org/gems/langfuse"
|
|
113
|
+
echo " 1. Check https://rubygems.org/gems/langfuse-ruby"
|
|
114
114
|
echo " 2. Update documentation if needed"
|
|
115
115
|
echo " 3. Announce the release"
|
|
116
116
|
echo
|
|
117
117
|
echo "🔗 Useful links:"
|
|
118
|
-
echo " - RubyGems: https://rubygems.org/gems/langfuse"
|
|
118
|
+
echo " - RubyGems: https://rubygems.org/gems/langfuse-ruby"
|
|
119
119
|
echo " - GitHub: https://github.com/ai-firstly/langfuse-ruby"
|
|
120
120
|
echo " - Documentation: https://github.com/ai-firstly/langfuse-ruby#readme"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: langfuse-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Richard Sun
|
|
@@ -242,6 +242,7 @@ files:
|
|
|
242
242
|
- docs/PUBLISH_GUIDE.md
|
|
243
243
|
- docs/README.md
|
|
244
244
|
- docs/RELEASE_CHECKLIST.md
|
|
245
|
+
- docs/V4.md
|
|
245
246
|
- examples/auto_flush_control.rb
|
|
246
247
|
- examples/basic_tracing.rb
|
|
247
248
|
- examples/connection_config_demo.rb
|
|
@@ -249,6 +250,7 @@ files:
|
|
|
249
250
|
- examples/prompt_management.rb
|
|
250
251
|
- examples/simplified_usage.rb
|
|
251
252
|
- examples/url_encoding_demo.rb
|
|
253
|
+
- examples/v4_otel_tracing.rb
|
|
252
254
|
- langfuse-ruby.gemspec
|
|
253
255
|
- lib/langfuse.rb
|
|
254
256
|
- lib/langfuse/client.rb
|
|
@@ -259,8 +261,12 @@ files:
|
|
|
259
261
|
- lib/langfuse/null_objects.rb
|
|
260
262
|
- lib/langfuse/observation_types.rb
|
|
261
263
|
- lib/langfuse/otel_exporter.rb
|
|
264
|
+
- lib/langfuse/partial_updates.rb
|
|
262
265
|
- lib/langfuse/prompt.rb
|
|
266
|
+
- lib/langfuse/prompt_cache.rb
|
|
263
267
|
- lib/langfuse/span.rb
|
|
268
|
+
- lib/langfuse/span_wrappers.rb
|
|
269
|
+
- lib/langfuse/template_compiler.rb
|
|
264
270
|
- lib/langfuse/trace.rb
|
|
265
271
|
- lib/langfuse/utils.rb
|
|
266
272
|
- lib/langfuse/version.rb
|
|
@@ -292,7 +298,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
292
298
|
- !ruby/object:Gem::Version
|
|
293
299
|
version: '0'
|
|
294
300
|
requirements: []
|
|
295
|
-
rubygems_version: 4.0.
|
|
301
|
+
rubygems_version: 4.0.20
|
|
296
302
|
specification_version: 4
|
|
297
303
|
summary: Ruby SDK for Langfuse - Open source LLM engineering platform
|
|
298
304
|
test_files: []
|