Class: LLMs::Adapters::OpenAICompatibleMessageAdapter

Inherits:
BaseMessageAdapter show all
Defined in:
lib/llms/adapters/open_ai_compatible_message_adapter.rb

Class Method Summary collapse

Methods inherited from BaseMessageAdapter

has_message?, message_from_api_format, transform_role, transform_text, transform_tool_calls

Class Method Details

.find_message_id(api_response_format) ⇒ Object



74
75
76
# File 'lib/llms/adapters/open_ai_compatible_message_adapter.rb', line 74

def self.find_message_id(api_response_format)
  api_response_format['id']
end

.find_role(api_response_format) ⇒ Object



70
71
72
# File 'lib/llms/adapters/open_ai_compatible_message_adapter.rb', line 70

def self.find_role(api_response_format)
  api_response_format.dig('choices', 0, 'message', 'role')
end

.find_text(api_response_format) ⇒ Object



78
79
80
# File 'lib/llms/adapters/open_ai_compatible_message_adapter.rb', line 78

def self.find_text(api_response_format)
  api_response_format.dig('choices', 0, 'message', 'content')
end

.find_tool_calls(api_response_format) ⇒ Object



82
83
84
# File 'lib/llms/adapters/open_ai_compatible_message_adapter.rb', line 82

def self.find_tool_calls(api_response_format)
  api_response_format.dig('choices', 0, 'message', 'tool_calls')
end

.to_api_format(message, _caching_enabled = false) ⇒ Object



9
10
11
12
13
14
15
16
17
18
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
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/llms/adapters/open_ai_compatible_message_adapter.rb', line 9

def self.to_api_format(message, _caching_enabled = false)
  formatted_messages = []

  message.tool_results&.each do |tool_result|
    formatted_messages << {
      role: 'tool',
      name: tool_result.name,
      tool_call_id: tool_result.tool_call_id,
      content: tool_result.results
    }
  end

  m = {
    role: message.role
  }

  if message.system? && message.text
    m[:content] = message.text
  else
    has_images = message.parts&.any? { |part| part[:image] }
    
    if has_images
      m[:content] = []
      message.parts&.each do |part|
        if part[:text]
          m[:content] << {type: 'text', text: part[:text]}
        end

        if part[:image]
          m[:content] << {type: 'image_url', image_url: {url: "data:#{part[:media_type] || 'image/png'};base64,#{part[:image]}"}}
        end
      end
    else
      ## TODO check this
      # For text-only messages, use array format to match test expectations
      m[:content] = [{type: 'text', text: message.text}]
    end
  end

  message.tool_calls&.each do |tool_call|
    m[:tool_calls] ||= []
    arguments = tool_call.arguments.is_a?(String) ? tool_call.arguments : JSON.dump(tool_call.arguments)
    m[:tool_calls] << {
      id: tool_call.tool_call_id,
      type: 'function',
      function: {
        name: tool_call.name,
        arguments: arguments
      }
    }
  end

  formatted_messages << m if m[:content] || m[:tool_calls]

  formatted_messages
end

.transform_tool_call(api_response_format_part, index) ⇒ Object



66
67
68
# File 'lib/llms/adapters/open_ai_compatible_message_adapter.rb', line 66

def self.transform_tool_call(api_response_format_part, index)
  LLMs::Adapters::OpenAICompatibleToolCallAdapter.from_api_format(api_response_format_part, index)
end