Class: Verica::RubyOpenAIWrapper
- Inherits:
-
Object
- Object
- Verica::RubyOpenAIWrapper
- Defined in:
- lib/verica/ruby_openai_wrapper.rb
Overview
The community ruby-openai gem (alexrudall) has a different API than the
official openai gem: client.chat(parameters: { model:, messages: })
returning a plain Hash (string keys) instead of typed objects. Both gems
define OpenAI::Client, so an app uses one or the other; this thin decorator
is the ruby-openai counterpart of OpenAIWrapper. Everything delegates to the
real client; only chat is intercepted to emit ONE gen_ai.* span with the
SAME pinned semconv the Verica normalizer accepts. Fail-open: instrumentation
errors never reach the caller; provider errors always do.
Defined Under Namespace
Classes: StreamAccumulator
Instance Method Summary collapse
- #chat(parameters: {}) ⇒ Object
-
#initialize(client) ⇒ RubyOpenAIWrapper
constructor
A new instance of RubyOpenAIWrapper.
- #method_missing(name) ⇒ Object
- #respond_to_missing?(name, include_private = false) ⇒ Boolean
Constructor Details
#initialize(client) ⇒ RubyOpenAIWrapper
Returns a new instance of RubyOpenAIWrapper.
15 16 17 |
# File 'lib/verica/ruby_openai_wrapper.rb', line 15 def initialize(client) @client = client end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name) ⇒ Object
55 56 57 |
# File 'lib/verica/ruby_openai_wrapper.rb', line 55 def method_missing(name, ...) @client.public_send(name, ...) end |
Instance Method Details
#chat(parameters: {}) ⇒ Object
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/verica/ruby_openai_wrapper.rb', line 19 def chat(parameters: {}) model = parameters[:model] || parameters['model'] span = safely do tracer = OpenTelemetry.tracer_provider.tracer('verica-observability', Verica::VERSION) tracer.start_span("chat #{model}", kind: :client) end # Streaming: ruby-openai delivers each chunk to the caller's proc and the # returned value is not a stable Hash. We wrap that proc so our accumulator # sees every chunk first, then hand it to the caller unchanged. The HTTP # call is synchronous, so by the time `@client.chat` returns the stream has # fully drained and the accumulator is complete. accumulator = nil call_parameters = parameters stream_key = stream_key_for(parameters) if stream_key && parameters[stream_key].respond_to?(:call) acc = StreamAccumulator.new built = safely { build_streaming_parameters(parameters, stream_key, acc) } if built accumulator = acc call_parameters = built end end begin response = @client.chat(parameters: call_parameters) safely { annotate(span, parameters, response, accumulator) } if span response rescue StandardError => e safely { span&.status = OpenTelemetry::Trace::Status.error(e.) } raise ensure safely { span&.finish } end end |
#respond_to_missing?(name, include_private = false) ⇒ Boolean
59 60 61 |
# File 'lib/verica/ruby_openai_wrapper.rb', line 59 def respond_to_missing?(name, include_private = false) @client.respond_to?(name, include_private) || super end |