Module: RubyLLM::Providers::Mistral::Chat
- Included in:
- RubyLLM::Providers::Mistral
- Defined in:
- lib/ruby_llm/providers/mistral/chat.rb
Overview
Chat methods for Mistral API
Class Method Summary collapse
- .adjustable_reasoning_model?(model_id) ⇒ Boolean
- .append_formatted_content(content_blocks, formatted_content) ⇒ Object
- .build_thinking_blocks(thinking) ⇒ Object
-
.build_tool_choice(tool_choice) ⇒ Object
rubocop:enable Metrics/ParameterLists.
- .configure_native_reasoning_payload(payload, thinking) ⇒ Object
- .configure_thinking_payload(payload, model, thinking) ⇒ Object
- .format_content_with_thinking(msg) ⇒ Object
- .format_messages(messages) ⇒ Object
- .format_role(role) ⇒ Object
- .native_reasoning_model?(model_id) ⇒ Boolean
- .normalize_required_tool_choice(payload) ⇒ Object
- .reasoning_effort_for(thinking) ⇒ Object
-
.render_payload(messages, tools:, temperature:, model:, stream: false, schema: nil, thinking: nil, tool_prefs: nil) ⇒ Object
rubocop:disable Metrics/ParameterLists.
- .warn_on_unsupported_thinking(model, thinking) ⇒ Object
Class Method Details
.adjustable_reasoning_model?(model_id) ⇒ Boolean
103 104 105 |
# File 'lib/ruby_llm/providers/mistral/chat.rb', line 103 def adjustable_reasoning_model?(model_id) model_id.to_s.match?(/\Amistral-(?:small-latest|medium-(?:3(?:[.-]5)?|latest))\z/) end |
.append_formatted_content(content_blocks, formatted_content) ⇒ Object
123 124 125 126 127 128 129 |
# File 'lib/ruby_llm/providers/mistral/chat.rb', line 123 def append_formatted_content(content_blocks, formatted_content) if formatted_content.is_a?(Array) content_blocks.concat(formatted_content) elsif formatted_content content_blocks << { type: 'text', text: formatted_content } end end |
.build_thinking_blocks(thinking) ⇒ Object
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/ruby_llm/providers/mistral/chat.rb', line 107 def build_thinking_blocks(thinking) return [] unless thinking if thinking.text [{ type: 'thinking', thinking: [{ type: 'text', text: thinking.text }], signature: thinking.signature }.compact] elsif thinking.signature [{ type: 'thinking', signature: thinking.signature }] else [] end end |
.build_tool_choice(tool_choice) ⇒ Object
rubocop:enable Metrics/ParameterLists
36 37 38 39 40 |
# File 'lib/ruby_llm/providers/mistral/chat.rb', line 36 def build_tool_choice(tool_choice) return 'any' if tool_choice == :required OpenAI::Tools.build_tool_choice(tool_choice) end |
.configure_native_reasoning_payload(payload, thinking) ⇒ Object
87 88 89 90 |
# File 'lib/ruby_llm/providers/mistral/chat.rb', line 87 def configure_native_reasoning_payload(payload, thinking) payload.delete(:reasoning_effort) payload[:prompt_mode] = thinking.effort == 'none' ? nil : 'reasoning' end |
.configure_thinking_payload(payload, model, thinking) ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/ruby_llm/providers/mistral/chat.rb', line 74 def configure_thinking_payload(payload, model, thinking) return unless thinking&.enabled? if native_reasoning_model?(model.id) configure_native_reasoning_payload(payload, thinking) elsif adjustable_reasoning_model?(model.id) payload[:reasoning_effort] = reasoning_effort_for(thinking) else payload.delete(:reasoning_effort) warn_on_unsupported_thinking(model, thinking) end end |
.format_content_with_thinking(msg) ⇒ Object
54 55 56 57 58 59 60 61 62 |
# File 'lib/ruby_llm/providers/mistral/chat.rb', line 54 def format_content_with_thinking(msg) formatted_content = OpenAI::Media.format_content(msg.content) return formatted_content unless msg.role == :assistant && msg.thinking content_blocks = build_thinking_blocks(msg.thinking) append_formatted_content(content_blocks, formatted_content) content_blocks end |
.format_messages(messages) ⇒ Object
14 15 16 17 18 19 20 21 22 23 |
# File 'lib/ruby_llm/providers/mistral/chat.rb', line 14 def () .map do |msg| { role: format_role(msg.role), content: format_content_with_thinking(msg), tool_calls: OpenAI::Tools.format_tool_calls(msg.tool_calls), tool_call_id: msg.tool_call_id }.compact end end |
.format_role(role) ⇒ Object
10 11 12 |
# File 'lib/ruby_llm/providers/mistral/chat.rb', line 10 def format_role(role) role.to_s end |
.native_reasoning_model?(model_id) ⇒ Boolean
99 100 101 |
# File 'lib/ruby_llm/providers/mistral/chat.rb', line 99 def native_reasoning_model?(model_id) model_id.to_s.include?('magistral') end |
.normalize_required_tool_choice(payload) ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/ruby_llm/providers/mistral/chat.rb', line 42 def normalize_required_tool_choice(payload) return unless payload[:tool_choice] == 'any' && Array(payload[:tools]).one? function_name = payload.dig(:tools, 0, :function, :name) return unless function_name payload[:tool_choice] = { type: 'function', function: { name: function_name } } end |
.reasoning_effort_for(thinking) ⇒ Object
92 93 94 95 96 97 |
# File 'lib/ruby_llm/providers/mistral/chat.rb', line 92 def reasoning_effort_for(thinking) effort = thinking.respond_to?(:effort) ? thinking.effort : nil return effort if %w[high none].include?(effort) 'high' end |
.render_payload(messages, tools:, temperature:, model:, stream: false, schema: nil, thinking: nil, tool_prefs: nil) ⇒ Object
rubocop:disable Metrics/ParameterLists
26 27 28 29 30 31 32 33 |
# File 'lib/ruby_llm/providers/mistral/chat.rb', line 26 def render_payload(, tools:, temperature:, model:, stream: false, schema: nil, thinking: nil, tool_prefs: nil) payload = super payload.delete(:stream_options) configure_thinking_payload(payload, model, thinking) normalize_required_tool_choice(payload) payload end |
.warn_on_unsupported_thinking(model, thinking) ⇒ Object
64 65 66 67 68 69 70 71 72 |
# File 'lib/ruby_llm/providers/mistral/chat.rb', line 64 def warn_on_unsupported_thinking(model, thinking) return unless thinking&.enabled? return if native_reasoning_model?(model.id) || adjustable_reasoning_model?(model.id) RubyLLM.logger.warn( 'Mistral thinking is only supported on Magistral and adjustable-reasoning models. ' \ "Ignoring thinking settings for #{model.id}." ) end |