Module: Raif::Concerns::Llms::Anthropic::ToolFormatting
- Extended by:
- ActiveSupport::Concern
- Included in:
- Llms::Anthropic
- Defined in:
- app/models/raif/concerns/llms/anthropic/tool_formatting.rb
Instance Method Summary collapse
- #build_forced_tool_choice(tool_name) ⇒ Object
- #build_required_tool_choice(disable_parallel: true) ⇒ Object
- #build_tools_parameter(model_completion) ⇒ Object
- #format_provider_managed_tool(tool) ⇒ Object
-
#json_response_tool_definition(model_completion) ⇒ Object
Without strict tool use the synthetic tool is advisory only, and models occasionally emit stub or malformed inputs (empty objects, placeholder values, payloads nested one level deep).
Instance Method Details
#build_forced_tool_choice(tool_name) ⇒ Object
87 88 89 |
# File 'app/models/raif/concerns/llms/anthropic/tool_formatting.rb', line 87 def build_forced_tool_choice(tool_name) { "type" => "tool", "name" => tool_name, "disable_parallel_tool_use" => true } end |
#build_required_tool_choice(disable_parallel: true) ⇒ Object
91 92 93 |
# File 'app/models/raif/concerns/llms/anthropic/tool_formatting.rb', line 91 def build_required_tool_choice(disable_parallel: true) { "type" => "any", "disable_parallel_tool_use" => disable_parallel } end |
#build_tools_parameter(model_completion) ⇒ Object
6 7 8 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 |
# File 'app/models/raif/concerns/llms/anthropic/tool_formatting.rb', line 6 def build_tools_parameter(model_completion) tools = [] # When the caller asks for a JSON response with a schema and the model can't # (or shouldn't) use native structured outputs, expose the schema as a # synthetic `json_response` tool. The model satisfies the request by calling # the tool with schema-matching arguments; `extract_json_response` unwraps # the tool-call input back into JSON. # # The native path (`use_native_structured_outputs?`) sends `output_config.format` # instead — enforced provider-side via constrained decoding, making this # synthetic tool redundant. That path is suppressed when the request # combines JSON output with provider-managed WebSearch, since Anthropic # documents structured outputs as incompatible with web-search citations # and we want to preserve citations on those requests. if model_completion.response_format_json? && model_completion.json_response_schema.present? && !use_native_structured_outputs?(model_completion) tools << json_response_tool_definition(model_completion) end # If we support native tool use and have tools available, add them to the request if supports_native_tool_use? && model_completion.available_model_tools.any? model_completion.available_model_tools_map.each do |_tool_name, tool| tools << if tool.provider_managed? format_provider_managed_tool(tool) else { name: tool.tool_name, description: tool.tool_description, input_schema: tool.tool_arguments_schema_for_source(model_completion.source) } end end end tools end |
#format_provider_managed_tool(tool) ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'app/models/raif/concerns/llms/anthropic/tool_formatting.rb', line 66 def format_provider_managed_tool(tool) validate_provider_managed_tool_support!(tool) case tool.name when "Raif::ModelTools::ProviderManaged::WebSearch" { type: "web_search_20250305", name: "web_search", max_uses: 5 } when "Raif::ModelTools::ProviderManaged::CodeExecution" { type: "code_execution_20250522", name: "code_execution" } else raise Raif::Errors::UnsupportedFeatureError, "Invalid provider-managed tool: #{tool.name} for #{key}" end end |
#json_response_tool_definition(model_completion) ⇒ Object
Without strict tool use the synthetic tool is advisory only, and models occasionally emit stub or malformed inputs (empty objects, placeholder values, payloads nested one level deep). strict: true makes the API enforce the input schema via constrained decoding on models that support it (gated on the same provider setting as native structured outputs, which shipped together with strict tool use).
51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'app/models/raif/concerns/llms/anthropic/tool_formatting.rb', line 51 def json_response_tool_definition(model_completion) tool = { name: "json_response", description: "Generate a structured JSON response based on the provided schema.", input_schema: model_completion.json_response_schema } if supports_structured_outputs? tool[:strict] = true tool[:input_schema] = Raif::Llms::Anthropic::StrictSchemaTransformer.call(tool[:input_schema]) end tool end |