Class: OmniAI::Anthropic::Chat
- Inherits:
-
Chat
- Object
- Chat
- OmniAI::Anthropic::Chat
- Defined in:
- lib/omniai/anthropic/chat.rb,
lib/omniai/anthropic/chat/stream.rb,
lib/omniai/anthropic/chat/url_serializer.rb,
lib/omniai/anthropic/chat/file_serializer.rb,
lib/omniai/anthropic/chat/text_serializer.rb,
lib/omniai/anthropic/chat/tool_serializer.rb,
lib/omniai/anthropic/chat/usage_serializer.rb,
lib/omniai/anthropic/chat/choice_serializer.rb,
lib/omniai/anthropic/chat/content_serializer.rb,
lib/omniai/anthropic/chat/message_serializer.rb,
lib/omniai/anthropic/chat/function_serializer.rb,
lib/omniai/anthropic/chat/response_serializer.rb,
lib/omniai/anthropic/chat/thinking_serializer.rb,
lib/omniai/anthropic/chat/tool_call_serializer.rb,
lib/omniai/anthropic/chat/tool_call_result_serializer.rb
Overview
Defined Under Namespace
Modules: ChoiceSerializer, ContentSerializer, FileSerializer, FunctionSerializer, MessageSerializer, Model, ResponseSerializer, TextSerializer, ThinkingSerializer, ToolCallResultSerializer, ToolCallSerializer, ToolSerializer, URLSerializer, UsageSerializer Classes: Stream
Constant Summary collapse
- DEFAULT_MODEL =
Model::CLAUDE_SONNET
- TEMPERATURE_UNSUPPORTED_MODELS =
Models that reject
temperaturewith a 400 ("temperatureis deprecated for this model"), even with thinking omitted. Every entry below was verified live against the API (Haiku 5.5 on 2026-10-07, Sonnet 5.5 on 2026-09-28, the rest on 2026-09-26). Opus 4.8 rejects it too but has no constant yet.Models absent from this list pass
temperaturethrough unchanged. That is deliberate: an unlisted model that rejects it surfaces a loud API error the caller can act on, whereas over-applying the guard would silently discard a caller's temperature. [ Model::CLAUDE_OPUS_4_7, Model::CLAUDE_OPUS_5, Model::CLAUDE_OPUS_5_5, Model::CLAUDE_SONNET_5, Model::CLAUDE_SONNET_5_5, Model::CLAUDE_HAIKU_5_5, ].freeze
- CONTEXT =
Context.build do |context| context.serializers[:tool] = ToolSerializer.method(:serialize) context.serializers[:file] = FileSerializer.method(:serialize) context.serializers[:url] = URLSerializer.method(:serialize) context.serializers[:choice] = ChoiceSerializer.method(:serialize) context.deserializers[:choice] = ChoiceSerializer.method(:deserialize) context.serializers[:tool_call] = ToolCallSerializer.method(:serialize) context.deserializers[:tool_call] = ToolCallSerializer.method(:deserialize) context.serializers[:tool_call_result] = ToolCallResultSerializer.method(:serialize) context.deserializers[:tool_call_result] = ToolCallResultSerializer.method(:deserialize) context.serializers[:function] = FunctionSerializer.method(:serialize) context.deserializers[:function] = FunctionSerializer.method(:deserialize) context.serializers[:message] = MessageSerializer.method(:serialize) context.deserializers[:message] = MessageSerializer.method(:deserialize) context.deserializers[:content] = ContentSerializer.method(:deserialize) context.deserializers[:response] = ResponseSerializer.method(:deserialize) context.serializers[:thinking] = ThinkingSerializer.method(:serialize) context.deserializers[:thinking] = ThinkingSerializer.method(:deserialize) context.deserializers[:usage] = UsageSerializer.method(:deserialize) end
- ADAPTIVE_THINKING_MIN_TOKENS =
Adaptive thinking can consume any portion of max_tokens before emitting output. Without a floor, callers using adaptive with the legacy default (4096) silently get empty responses. This constant guarantees enough headroom for thinking + output.
32_768
Instance Method Summary collapse
-
#cache_control ⇒ Hash?
Translates the opt-in
cacheoption to Anthropic'scache_control. -
#max_tokens ⇒ Object
Resolved max_tokens.
-
#messages ⇒ Array<Hash>
When caching, the last block of the last message is marked so each tool-loop round reads the history the previous round wrote.
- #path ⇒ String
-
#payload ⇒ Hash
NOTE: Anthropic requires temperature=1 (default) when thinking is enabled, so temperature is omitted from the payload when thinking_config is present or the model is in TEMPERATURE_UNSUPPORTED_MODELS.
-
#system ⇒ String, ...
When caching, a single marked text block.
-
#thinking_config ⇒ Hash?
Translates unified thinking option to Anthropic's native format.
-
#thinking_max_tokens ⇒ Integer?
Returns max_tokens ensuring enough headroom when thinking is in play.
Instance Method Details
#cache_control ⇒ Hash?
Translates the opt-in cache option to Anthropic's cache_control.
Example: cache: true becomes { type: "ephemeral" } (5-minute TTL)
Example: cache: :system becomes { type: "ephemeral" } on the system prompt (or last tool) only
Example: cache: { ttl: "1h" } becomes { type: "ephemeral", ttl: "1h" }
218 219 220 221 222 223 |
# File 'lib/omniai/anthropic/chat.rb', line 218 def cache_control case @options[:cache] when true, :system then { type: "ephemeral" } when Hash then { type: "ephemeral" }.merge(@options[:cache]) end end |
#max_tokens ⇒ Object
Resolved max_tokens. Precedence: thinking floor (when budget set) > per-call kwarg. Returns nil when neither is set, so the config default flows through unchanged.
135 136 137 |
# File 'lib/omniai/anthropic/chat.rb', line 135 def max_tokens thinking_max_tokens || @options[:max_tokens] end |
#messages ⇒ Array<Hash>
When caching, the last block of the last message is marked so each tool-loop round reads the history the
previous round wrote. cache: :system skips this for single-shot prompts whose message is never reused.
192 193 194 195 196 197 198 |
# File 'lib/omniai/anthropic/chat.rb', line 192 def = @prompt..reject(&:system?).map { || .serialize(context:) } return unless cache_control && @options[:cache] != :system && .any? *history, last = history + [last.merge(content: with_cache_control(last[:content]))] end |
#path ⇒ String
226 227 228 |
# File 'lib/omniai/anthropic/chat.rb', line 226 def path "/#{Client::VERSION}/messages" end |
#payload ⇒ Hash
NOTE: Anthropic requires temperature=1 (default) when thinking is enabled, so temperature is omitted from the payload when thinking_config is present or the model is in TEMPERATURE_UNSUPPORTED_MODELS.
118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/omniai/anthropic/chat.rb', line 118 def payload OmniAI::Anthropic.config. .merge({ model: @model, messages:, system:, stream: stream? || nil, temperature: thinking_config || TEMPERATURE_UNSUPPORTED_MODELS.include?(@model) ? nil : @temperature, tools: tools_payload, thinking: thinking_config, }) .merge({ max_tokens:, output_config: }.compact) .compact end |
#system ⇒ String, ...
When caching, a single marked text block. Tools render before system, so this breakpoint covers both.
203 204 205 206 207 208 209 210 |
# File 'lib/omniai/anthropic/chat.rb', line 203 def system parts = @prompt..filter(&:system?).filter(&:text?).map(&:text) parts << formatting if formatting? return if parts.empty? text = parts.join("\n\n") cache_control ? [{ type: "text", text:, cache_control: }] : text end |
#thinking_config ⇒ Hash?
Translates unified thinking option to Anthropic's native format.
Example: thinking: { budget_tokens: 10000 } becomes { type: "enabled", budget_tokens: 10000 }
Example: thinking: { effort: nil } becomes { type: "adaptive" } (Claude decides)
Example: thinking: { effort: "medium" } becomes { type: "adaptive" } + output_config
Example: thinking: { effort: "medium", display: "summarized" } forwards display onto the adaptive object.
NOTE: display is strictly opt-in pass-through. When omitted, no display key is sent and the
model's own default applies (e.g. "omitted" on Sonnet 5 / Opus 4.7+, "summarized" on Sonnet 4.6).
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/omniai/anthropic/chat.rb', line 148 def thinking_config return @thinking_config if defined?(@thinking_config) thinking = @options[:thinking] @thinking_config = case thinking when true then { type: "enabled", budget_tokens: 10_000 } when Hash if thinking.key?(:effort) { type: "adaptive" }.merge(thinking.slice(:display)) else { type: "enabled" }.merge(thinking) end end end |
#thinking_max_tokens ⇒ Integer?
Returns max_tokens ensuring enough headroom when thinking is in play. Enabled-mode path preserves the existing [base, budget+8000].max floor. Adaptive-mode path applies ADAPTIVE_THINKING_MIN_TOKENS as a safety floor.
173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/omniai/anthropic/chat.rb', line 173 def thinking_max_tokens return unless thinking_config case thinking_config[:type] when "adaptive" [@options[:max_tokens] || ADAPTIVE_THINKING_MIN_TOKENS, ADAPTIVE_THINKING_MIN_TOKENS].max when "enabled" budget = thinking_config[:budget_tokens] return unless budget base = @options[:max_tokens] || OmniAI::Anthropic.config.[:max_tokens] || 0 [base, budget + 8_000].max end end |