Class: Legion::Extensions::Llm::Openai::Translator
- Inherits:
-
Object
- Object
- Legion::Extensions::Llm::Openai::Translator
- Includes:
- Logging::Helper
- Defined in:
- lib/legion/extensions/llm/openai/translator.rb
Overview
Canonical <-> OpenAI wire-format translator.
Implements the provider-boundary contract (Amendment A) so that canonical requests/responses/chunks cross exactly one translation layer per provider. Extracted from OpenAICompatible mixin methods; semantics preserved, not rewritten.
Capabilities (declarative, per the design doc):
- reasoning_effort: true (gpt-5.x / o-series)
- responses_api: true (chat/completions wire format)
- thinking_metadata_keys: [...] (metadata keys for thinking)
- stop_reason_map: { openai -> canonical }
Constant Summary collapse
- STOP_REASON_MAP =
OpenAI finish_reason -> canonical stop_reason (G18 stop-reason matrix)
{ 'stop' => :end_turn, 'tool_calls' => :tool_use, 'function_call' => :tool_use, 'length' => :max_tokens, 'content_filter' => :content_filter }.freeze
- THINKING_METADATA_KEYS =
Metadata keys carrying thinking/reasoning in OpenAI responses
%i[ reasoning_content reasoning thinking thinking_text thinking_signature reasoning_signature ].freeze
Instance Method Summary collapse
-
#capabilities ⇒ Hash
Declarative capabilities consumed by routing/dispatch.
-
#initialize(api_base: nil, headers: nil) ⇒ Translator
constructor
A new instance of Translator.
- #parse_chunk(raw) ⇒ Canonical::Chunk?
- #parse_response(wire) ⇒ Canonical::Response
-
#render_request(canonical_request) ⇒ Hash
OpenAI wire-format payload for /v1/chat/completions.
Constructor Details
#initialize(api_base: nil, headers: nil) ⇒ Translator
Returns a new instance of Translator.
37 38 39 40 |
# File 'lib/legion/extensions/llm/openai/translator.rb', line 37 def initialize(api_base: nil, headers: nil) @api_base = api_base @headers = headers || {} end |
Instance Method Details
#capabilities ⇒ Hash
Returns declarative capabilities consumed by routing/dispatch.
43 44 45 46 47 48 49 50 51 |
# File 'lib/legion/extensions/llm/openai/translator.rb', line 43 def capabilities { provider: 'openai', reasoning_effort: true, responses_api: true, thinking_metadata_keys: THINKING_METADATA_KEYS, stop_reason_map: STOP_REASON_MAP } end |
#parse_chunk(raw) ⇒ Canonical::Chunk?
84 85 86 87 88 89 90 91 92 |
# File 'lib/legion/extensions/llm/openai/translator.rb', line 84 def parse_chunk(raw) return nil if raw.nil? || raw.to_h.empty? return Canonical::Chunk.from_hash(raw) if canonical_chunk_form?(raw) parse_raw_chunk(raw.to_h) rescue StandardError => e handle_exception(e, level: :error, handled: true, operation: 'openai.translator.parse_chunk') Canonical::Chunk.error_chunk(error: e., request_id: raw.to_h['id']) end |
#parse_response(wire) ⇒ Canonical::Response
73 74 75 76 77 78 79 80 |
# File 'lib/legion/extensions/llm/openai/translator.rb', line 73 def parse_response(wire) return Canonical::Response.from_hash(wire) if canonical_form?(wire) build_canonical_response(wire.to_h) rescue StandardError => e handle_exception(e, level: :error, handled: true, operation: 'openai.translator.parse_response') Canonical::Response.build(text: '', stop_reason: :error, metadata: { error: e. }) end |
#render_request(canonical_request) ⇒ Hash
Returns OpenAI wire-format payload for /v1/chat/completions.
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/legion/extensions/llm/openai/translator.rb', line 55 def render_request(canonical_request) wire = { model: resolve_model(canonical_request), messages: (canonical_request), stream: canonical_request.stream }.compact apply_params(wire, canonical_request.params) if canonical_request.params apply_tools(wire, canonical_request) if canonical_request.tools&.any? apply_tool_choice(wire, canonical_request.tool_choice) if canonical_request.tool_choice apply_thinking(wire, canonical_request) use_stream_usage(wire) if canonical_request.stream wire end |