rubyllm-observ 0.6.4 → 0.6.6
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/README.md +0 -1
- data/app/services/observ/concerns/observable_service.rb +143 -0
- data/app/views/layouts/observ/application.html.erb +1 -1
- data/lib/observ/configuration.rb +0 -2
- data/lib/observ/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9515276911fc3bbb7170e6a9e5f67e58ae7e4285a5c929ebdd469b13d334fa3c
|
|
4
|
+
data.tar.gz: 5efd608bda38651dc6e606f9216fd423f0f69b655f7264fe7af51a337e37f9d6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 39e136a3e9ddb512b5231fbd25b7d588550f8476101ac7c9e8f3e278fbe68f0692836bd15f0f45aebcfe82be5d4d74de0195249cd9a1be099088c69ee1c5926c
|
|
7
|
+
data.tar.gz: 369289406fc87cfc150b86c7d32bdaafdb52fc5a42836068bd21b16745141d0baaa4313ea98fd0630d33ecfe486b460c39a7f42d1b85a4b6416fb79c2069b99d
|
data/README.md
CHANGED
|
@@ -196,7 +196,6 @@ Observ.configure do |config|
|
|
|
196
196
|
|
|
197
197
|
# UI configuration
|
|
198
198
|
config.back_to_app_path = -> { Rails.application.routes.url_helpers.root_path }
|
|
199
|
-
config.back_to_app_label = "← Back to App"
|
|
200
199
|
|
|
201
200
|
# Chat UI (auto-detects if Chat model exists with acts_as_chat)
|
|
202
201
|
# Manually override if needed:
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Observ
|
|
4
|
+
module Concerns
|
|
5
|
+
# Concern for adding observability to service objects
|
|
6
|
+
#
|
|
7
|
+
# This module provides automatic observability session management for services
|
|
8
|
+
# that perform LLM operations. It handles session creation, lifecycle management,
|
|
9
|
+
# and chat instrumentation.
|
|
10
|
+
#
|
|
11
|
+
# Usage:
|
|
12
|
+
# class MyService
|
|
13
|
+
# include Observ::Concerns::ObservableService
|
|
14
|
+
#
|
|
15
|
+
# def initialize(observability_session: nil)
|
|
16
|
+
# initialize_observability(
|
|
17
|
+
# observability_session,
|
|
18
|
+
# service_name: "my_service",
|
|
19
|
+
# metadata: { custom: "data" }
|
|
20
|
+
# )
|
|
21
|
+
# end
|
|
22
|
+
#
|
|
23
|
+
# def perform(input)
|
|
24
|
+
# with_observability do |session|
|
|
25
|
+
# # Your service logic here
|
|
26
|
+
# # Session automatically finalized on success/error
|
|
27
|
+
# end
|
|
28
|
+
# end
|
|
29
|
+
# end
|
|
30
|
+
module ObservableService
|
|
31
|
+
extend ActiveSupport::Concern
|
|
32
|
+
|
|
33
|
+
included do
|
|
34
|
+
attr_reader :observability
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Initialize observability for the service
|
|
38
|
+
#
|
|
39
|
+
# @param session_or_false [Observ::Session, false, nil] Session to use, false to disable, nil to auto-create
|
|
40
|
+
# @param service_name [String] Name of the service (used in session metadata)
|
|
41
|
+
# @param metadata [Hash] Additional metadata to include in the session
|
|
42
|
+
def initialize_observability(session_or_false = nil, service_name:, metadata: {})
|
|
43
|
+
if session_or_false == false
|
|
44
|
+
# Explicitly disable observability
|
|
45
|
+
@observability = nil
|
|
46
|
+
@owns_session = false
|
|
47
|
+
elsif session_or_false
|
|
48
|
+
# Use provided session
|
|
49
|
+
@observability = session_or_false
|
|
50
|
+
@owns_session = false
|
|
51
|
+
else
|
|
52
|
+
# Auto-create session for standalone use
|
|
53
|
+
@observability = create_service_session(service_name, metadata)
|
|
54
|
+
@owns_session = @observability.present?
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Execute a block with automatic session lifecycle management
|
|
59
|
+
#
|
|
60
|
+
# The session will be finalized automatically after the block completes,
|
|
61
|
+
# whether it succeeds or raises an error. Only sessions owned by this
|
|
62
|
+
# service instance (i.e., auto-created sessions) will be finalized.
|
|
63
|
+
#
|
|
64
|
+
# @yield [session] The observability session (may be nil if disabled)
|
|
65
|
+
# @return The result of the block
|
|
66
|
+
#
|
|
67
|
+
# @example
|
|
68
|
+
# with_observability do |session|
|
|
69
|
+
# # Your service logic here
|
|
70
|
+
# process_data(session)
|
|
71
|
+
# end
|
|
72
|
+
def with_observability(&block)
|
|
73
|
+
result = block.call(@observability)
|
|
74
|
+
finalize_service_session if @owns_session
|
|
75
|
+
result
|
|
76
|
+
rescue StandardError
|
|
77
|
+
finalize_service_session if @owns_session
|
|
78
|
+
raise
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Instrument a RubyLLM chat instance for observability
|
|
82
|
+
#
|
|
83
|
+
# This wraps the chat's ask method to automatically create traces
|
|
84
|
+
# and track LLM calls within the observability session.
|
|
85
|
+
#
|
|
86
|
+
# @param chat [RubyLLM::Chat] The chat instance to instrument
|
|
87
|
+
# @param context [Hash] Additional context to include in traces
|
|
88
|
+
# @return [Observ::ChatInstrumenter, nil] The instrumenter or nil if observability is disabled
|
|
89
|
+
#
|
|
90
|
+
# @example
|
|
91
|
+
# chat = RubyLLM.chat(model: "gpt-4")
|
|
92
|
+
# instrument_chat(chat, context: { operation: "summarize" })
|
|
93
|
+
# response = chat.ask("Summarize this text")
|
|
94
|
+
def instrument_chat(chat, context: {})
|
|
95
|
+
return unless @observability
|
|
96
|
+
|
|
97
|
+
@observability.instrument_chat(chat, context: context)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
private
|
|
101
|
+
|
|
102
|
+
# Create a new observability session for this service
|
|
103
|
+
#
|
|
104
|
+
# @param service_name [String] Name of the service
|
|
105
|
+
# @param metadata [Hash] Additional metadata for the session
|
|
106
|
+
# @return [Observ::Session, nil] The created session or nil if observability is disabled/failed
|
|
107
|
+
def create_service_session(service_name, metadata = {})
|
|
108
|
+
return nil unless Rails.configuration.observability.enabled
|
|
109
|
+
|
|
110
|
+
Observ::Session.create!(
|
|
111
|
+
user_id: "#{service_name}_service",
|
|
112
|
+
metadata: metadata.merge(
|
|
113
|
+
agent_type: service_name,
|
|
114
|
+
standalone: true,
|
|
115
|
+
created_at: Time.current.iso8601
|
|
116
|
+
)
|
|
117
|
+
)
|
|
118
|
+
rescue StandardError => e
|
|
119
|
+
Rails.logger.error(
|
|
120
|
+
"[#{self.class.name}] Failed to create observability session: #{e.message}"
|
|
121
|
+
)
|
|
122
|
+
nil
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Finalize the observability session if we own it
|
|
126
|
+
#
|
|
127
|
+
# This marks the session as complete and triggers aggregation of metrics.
|
|
128
|
+
# Only called for sessions created by this service instance.
|
|
129
|
+
def finalize_service_session
|
|
130
|
+
return unless @observability
|
|
131
|
+
|
|
132
|
+
@observability.finalize
|
|
133
|
+
Rails.logger.debug(
|
|
134
|
+
"[#{self.class.name}] Session finalized: #{@observability.session_id}"
|
|
135
|
+
)
|
|
136
|
+
rescue StandardError => e
|
|
137
|
+
Rails.logger.error(
|
|
138
|
+
"[#{self.class.name}] Failed to finalize session: #{e.message}"
|
|
139
|
+
)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
<div class="observ-sidebar__footer">
|
|
87
87
|
<%= link_to main_app.instance_exec(&Observ.config.back_to_app_path), class: "observ-sidebar__back-link" do %>
|
|
88
88
|
<span>←</span>
|
|
89
|
-
<span
|
|
89
|
+
<span>Back to App</span>
|
|
90
90
|
<% end %>
|
|
91
91
|
</div>
|
|
92
92
|
</aside>
|
data/lib/observ/configuration.rb
CHANGED
|
@@ -17,7 +17,6 @@ module Observ
|
|
|
17
17
|
:prompt_config_schema,
|
|
18
18
|
:prompt_config_schema_strict,
|
|
19
19
|
:back_to_app_path,
|
|
20
|
-
:back_to_app_label,
|
|
21
20
|
:chat_ui_enabled,
|
|
22
21
|
:agent_path,
|
|
23
22
|
:pagination_per_page
|
|
@@ -38,7 +37,6 @@ module Observ
|
|
|
38
37
|
@prompt_config_schema = default_prompt_config_schema
|
|
39
38
|
@prompt_config_schema_strict = false
|
|
40
39
|
@back_to_app_path = -> { "/" }
|
|
41
|
-
@back_to_app_label = "← Back to App"
|
|
42
40
|
@chat_ui_enabled = -> { defined?(::Chat) && ::Chat.respond_to?(:acts_as_chat) }
|
|
43
41
|
@agent_path = nil # Defaults to Rails.root.join("app", "agents")
|
|
44
42
|
@pagination_per_page = 25
|
data/lib/observ/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubyllm-observ
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Franck D'agostini
|
|
@@ -309,6 +309,7 @@ files:
|
|
|
309
309
|
- app/services/observ/agent_provider.rb
|
|
310
310
|
- app/services/observ/agent_selection_service.rb
|
|
311
311
|
- app/services/observ/chat_instrumenter.rb
|
|
312
|
+
- app/services/observ/concerns/observable_service.rb
|
|
312
313
|
- app/services/observ/dataset_runner_service.rb
|
|
313
314
|
- app/services/observ/evaluator_runner_service.rb
|
|
314
315
|
- app/services/observ/evaluators/base_evaluator.rb
|