Module: Raif::Concerns::Llms::Google::MessageFormatting

Extended by:
ActiveSupport::Concern
Included in:
Llms::Google
Defined in:
app/models/raif/concerns/llms/google/message_formatting.rb

Instance Method Summary collapse

Instance Method Details

#format_messages(messages) ⇒ Object

Override the base format_messages to use Google’s message format



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'app/models/raif/concerns/llms/google/message_formatting.rb', line 7

def format_messages(messages)
  messages.map do |message|
    if message.is_a?(Hash) && message["type"] == "tool_call"
      format_tool_call_message(message)
    elsif message.is_a?(Hash) && message["type"] == "tool_call_result"
      format_tool_call_result_message(message)
    else
      role = message["role"] || message[:role]
      # Google uses "model" instead of "assistant"
      google_role = role == "assistant" ? "model" : role
      {
        "role" => google_role,
        "parts" => format_message_content(message["content"] || message[:content], role: role)
      }
    end
  end
end

#format_model_file_input_message(file_input) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'app/models/raif/concerns/llms/google/message_formatting.rb', line 49

def format_model_file_input_message(file_input)
  if file_input.source_type == :url
    {
      "fileData" => {
        "mimeType" => file_input.content_type,
        "fileUri" => file_input.url
      }
    }
  elsif file_input.source_type == :file_content
    {
      "inlineData" => {
        "mimeType" => file_input.content_type,
        "data" => file_input.base64_data
      }
    }
  else
    raise Raif::Errors::InvalidModelFileInputError, "Invalid model file input source type: #{file_input.source_type}"
  end
end

#format_model_image_input_message(image_input) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'app/models/raif/concerns/llms/google/message_formatting.rb', line 29

def format_model_image_input_message(image_input)
  if image_input.source_type == :url
    {
      "fileData" => {
        "mimeType" => image_input.content_type,
        "fileUri" => image_input.url
      }
    }
  elsif image_input.source_type == :file_content
    {
      "inlineData" => {
        "mimeType" => image_input.content_type,
        "data" => image_input.base64_data
      }
    }
  else
    raise Raif::Errors::InvalidModelImageInputError, "Invalid model image input source type: #{image_input.source_type}"
  end
end

#format_string_message(content, role: nil) ⇒ Object



25
26
27
# File 'app/models/raif/concerns/llms/google/message_formatting.rb', line 25

def format_string_message(content, role: nil)
  { "text" => content }
end

#format_tool_call_message(tool_call) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'app/models/raif/concerns/llms/google/message_formatting.rb', line 69

def format_tool_call_message(tool_call)
  parts = []

  if tool_call["assistant_message"].present?
    parts << format_string_message(tool_call["assistant_message"])
  end

  function_call_part = {
    "functionCall" => {
      "name" => tool_call["name"],
      "args" => tool_call["arguments"]
    }
  }

  # Include thoughtSignature if present (required for Gemini 2.5+ thinking models)
  thought_signature = tool_call.dig("provider_metadata", "thought_signature")
  function_call_part["thoughtSignature"] = thought_signature if thought_signature.present?

  parts << function_call_part

  {
    "role" => "model",
    "parts" => parts
  }
end

#format_tool_call_result_message(tool_call_result) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'app/models/raif/concerns/llms/google/message_formatting.rb', line 95

def format_tool_call_result_message(tool_call_result)
  result = tool_call_result["result"]
  response_content = result.is_a?(String) ? { "output" => result } : result

  {
    "role" => "user",
    "parts" => [{
      "functionResponse" => {
        "name" => tool_call_result["name"],
        "response" => response_content
      }
    }]
  }
end