Class: Kernai::Providers::Openai
- Inherits:
-
Kernai::Provider
- Object
- Kernai::Provider
- Kernai::Providers::Openai
- Defined in:
- lib/kernai/providers/openai.rb
Overview
Kernai::Provider adapter for the OpenAI Chat Completions API.
Supports streaming, multimodal image input (when the model declares ‘:vision`), and reasoning effort via `GenerationOptions#thinking` which maps to OpenAI’s ‘reasoning_effort` parameter (honored by o1/o3/ gpt-5 reasoning models; silently ignored by others).
Zero runtime dependencies beyond the Ruby stdlib. Works against any OpenAI-compatible endpoint by passing a custom ‘api_url:`.
Constant Summary collapse
- DEFAULT_API_URL =
'https://api.openai.com/v1/chat/completions'
Instance Method Summary collapse
- #call(messages:, model:, generation: nil, &block) ⇒ Object
-
#encode_part(part, model:) ⇒ Object
OpenAI chat completions accept vision parts as ‘image_url` objects.
-
#initialize(api_key: ENV.fetch('OPENAI_API_KEY', nil), api_url: DEFAULT_API_URL) ⇒ Openai
constructor
A new instance of Openai.
Methods inherited from Kernai::Provider
Constructor Details
#initialize(api_key: ENV.fetch('OPENAI_API_KEY', nil), api_url: DEFAULT_API_URL) ⇒ Openai
Returns a new instance of Openai.
21 22 23 24 25 |
# File 'lib/kernai/providers/openai.rb', line 21 def initialize(api_key: ENV.fetch('OPENAI_API_KEY', nil), api_url: DEFAULT_API_URL) super() @api_key = api_key @api_url = api_url end |
Instance Method Details
#call(messages:, model:, generation: nil, &block) ⇒ Object
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 |
# File 'lib/kernai/providers/openai.rb', line 27 def call(messages:, model:, generation: nil, &block) uri = URI(@api_url) payload = build_payload(, model, stream: block_given?, generation: generation) started = Process.clock_gettime(Process::CLOCK_MONOTONIC) response = http_post(uri, payload) unless response.is_a?(Net::HTTPSuccess) raise Kernai::ProviderError, "OpenAI API error #{response.code}: #{response.body}" end content, usage = if block parse_stream(response.body, &block) else parse_response(response.body) end Kernai::LlmResponse.new( content: content, latency_ms: elapsed_ms(started), prompt_tokens: usage['prompt_tokens'], completion_tokens: usage['completion_tokens'], total_tokens: usage['total_tokens'] ) end |
#encode_part(part, model:) ⇒ Object
OpenAI chat completions accept vision parts as ‘image_url` objects. We honour both URL-backed media and inline bytes (encoded as a data URI). Anything else falls back to the base class placeholder.
56 57 58 59 60 61 62 63 64 65 |
# File 'lib/kernai/providers/openai.rb', line 56 def encode_part(part, model:) return { 'type' => 'text', 'text' => part } if part.is_a?(String) return nil unless part.is_a?(Kernai::Media) && part.kind == :image && model.supports?(:vision) url = case part.source when :url then part.data when :path, :bytes then "data:#{part.mime_type};base64,#{part.to_base64}" end { 'type' => 'image_url', 'image_url' => { 'url' => url } } end |