Module: Foam::Otel::LLM::RubyLLMShim
- Defined in:
- lib/foam/otel/llm/ruby_llm_shim.rb
Overview
Gap-filler for the ruby_llm multi-provider client: ONE seam —
RubyLLM::Provider#complete, the single synchronous round trip every
chat/ask call funnels through — covers ALL its providers (OpenAI,
Anthropic, Gemini, and the rest) with the identical gen_ai span the
per-SDK shims emit. Streaming rides the same seam (ruby_llm consumes
the stream inside #complete and returns the accumulated Message).
Defined Under Namespace
Modules: ProviderPatch
Constant Summary collapse
- SUPPORTED =
Gem::Requirement.new(">= 1.3", "< 2")
- PROVIDER_NAMES =
ruby_llm provider slugs → gen_ai.provider.name well-known values. Unlisted slugs pass through verbatim (never dropped).
{ "openai" => "openai", "anthropic" => "anthropic", "gemini" => "gcp.gemini", "vertexai" => "gcp.vertex_ai", "bedrock" => "aws.bedrock", "mistral" => "mistral_ai", "deepseek" => "deepseek", "perplexity" => "perplexity", }.freeze
- RESPONSE =
The returned RubyLLM::Message → response attributes.
lambda do || next nil unless .respond_to?(:content) input_tokens = .respond_to?(:input_tokens) ? .input_tokens : nil output_tokens = .respond_to?(:output_tokens) ? .output_tokens : nil LLM.response_attributes( model: .respond_to?(:model_id) ? .model_id : nil, input_tokens: input_tokens.is_a?(Numeric) ? input_tokens.to_i : nil, output_tokens: output_tokens.is_a?(Numeric) ? output_tokens.to_i : nil, output_messages: [{ "role" => (.respond_to?(:role) ? .role.to_s : "assistant"), "content" => RubyLLMShim.content_of(), }] ) end
Class Method Summary collapse
- .content_of(message) ⇒ Object
- .install! ⇒ Object
- .installed? ⇒ Boolean
- .present? ⇒ Boolean
- .provider_name(provider) ⇒ Object
- .request(provider, messages, model) ⇒ Object
-
.serialize_messages(messages) ⇒ Object
RubyLLM::Message list → plain [content:] for the RAW input.messages JSON (Content objects degrade to_s, never dropped).
- .supported_version? ⇒ Boolean
Class Method Details
.content_of(message) ⇒ Object
89 90 91 92 93 94 95 96 |
# File 'lib/foam/otel/llm/ruby_llm_shim.rb', line 89 def content_of() content = .respond_to?(:content) ? .content : return content if content.is_a?(String) content.respond_to?(:text) && content.text ? content.text : content.to_s rescue StandardError, SystemStackError nil end |
.install! ⇒ Object
35 36 37 38 39 40 41 |
# File 'lib/foam/otel/llm/ruby_llm_shim.rb', line 35 def install! return true if @installed ::RubyLLM::Provider.prepend(ProviderPatch) Diagnostics.info("LLM shim installed: ruby_llm (Provider#complete)") @installed = true end |
.installed? ⇒ Boolean
43 |
# File 'lib/foam/otel/llm/ruby_llm_shim.rb', line 43 def installed? = @installed |
.present? ⇒ Boolean
29 30 31 32 33 |
# File 'lib/foam/otel/llm/ruby_llm_shim.rb', line 29 def present? defined?(::RubyLLM::Provider) && ::RubyLLM::Provider.method_defined?(:complete) && supported_version? end |
.provider_name(provider) ⇒ Object
60 61 62 63 64 65 |
# File 'lib/foam/otel/llm/ruby_llm_shim.rb', line 60 def provider_name(provider) slug = provider.respond_to?(:slug) ? provider.slug.to_s : provider.class.to_s PROVIDER_NAMES.fetch(slug, slug) rescue StandardError "ruby_llm" end |
.request(provider, messages, model) ⇒ Object
67 68 69 70 71 72 73 74 |
# File 'lib/foam/otel/llm/ruby_llm_shim.rb', line 67 def request(provider, , model) model_id = model.respond_to?(:id) ? model.id : model LLM.request_attributes( provider: provider_name(provider), operation: "chat", model: model_id, input_messages: () ) end |
.serialize_messages(messages) ⇒ Object
RubyLLM::Message list → plain [content:] for the RAW input.messages JSON (Content objects degrade to_s, never dropped).
78 79 80 81 82 83 84 85 86 87 |
# File 'lib/foam/otel/llm/ruby_llm_shim.rb', line 78 def () Array().map do || { "role" => (.respond_to?(:role) ? .role.to_s : "user"), "content" => content_of(), } end rescue StandardError, SystemStackError nil end |
.supported_version? ⇒ Boolean
45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/foam/otel/llm/ruby_llm_shim.rb', line 45 def supported_version? spec = Gem.loaded_specs["ruby_llm"] return true if spec.nil? supported = SUPPORTED.satisfied_by?(spec.version) unless supported || @version_warned @version_warned = true Diagnostics.warn("ruby_llm #{spec.version} is outside foam's LLM-shim window (#{SUPPORTED}) " \ "— the ruby_llm shim stays dark; file this with foam support") end supported rescue StandardError true end |