Class: DSPy::LM::Strategies::AnthropicToolUseStrategy

Inherits:
BaseStrategy
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/dspy/lm/strategies/anthropic_tool_use_strategy.rb

Overview

Strategy for using Anthropic’s tool use feature for guaranteed JSON output

Instance Method Summary collapse

Methods inherited from BaseStrategy

#initialize

Constructor Details

This class inherits a constructor from DSPy::LM::Strategies::BaseStrategy

Instance Method Details

#available?Boolean

Returns:

  • (Boolean)


13
14
15
16
# File 'lib/dspy/lm/strategies/anthropic_tool_use_strategy.rb', line 13

def available?
  # Only available for Anthropic adapters with models that support tool use
  adapter.is_a?(DSPy::LM::AnthropicAdapter) && supports_tool_use?
end

#extract_json(response) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/dspy/lm/strategies/anthropic_tool_use_strategy.rb', line 49

def extract_json(response)
  # Extract JSON from tool use response
  begin
    # Check for tool calls in metadata first (this is the primary method)
    if response..respond_to?(:tool_calls) && response..tool_calls
      tool_calls = response..tool_calls
      if tool_calls.is_a?(Array) && !tool_calls.empty?
        first_call = tool_calls.first
        if first_call[:name] == "json_output" && first_call[:input]
          json_result = JSON.generate(first_call[:input])
          return json_result
        end
      end
    end
    
    # Fallback: try to extract from content if it contains tool use blocks
    content = response.content
    if content && !content.empty? && content.include?("<tool_use>")
      tool_content = content[/<tool_use>.*?<\/tool_use>/m]
      if tool_content
        json_match = tool_content[/<input>(.*?)<\/input>/m, 1]
        return json_match.strip if json_match
      end
    end
    
    nil
  rescue => e
    DSPy.logger.debug("Failed to extract tool use JSON: #{e.message}")
    nil
  end
end

#handle_error(error) ⇒ Object



82
83
84
85
86
87
88
89
90
# File 'lib/dspy/lm/strategies/anthropic_tool_use_strategy.rb', line 82

def handle_error(error)
  # Tool use errors should trigger fallback to extraction strategy
  if error.message.include?("tool") || error.message.include?("invalid_request_error")
    DSPy.logger.warn("Anthropic tool use failed: #{error.message}")
    true # We handled it, try next strategy
  else
    false # Let retry handler deal with it
  end
end

#nameObject



24
25
26
# File 'lib/dspy/lm/strategies/anthropic_tool_use_strategy.rb', line 24

def name
  "anthropic_tool_use"
end

#prepare_request(messages, request_params) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/dspy/lm/strategies/anthropic_tool_use_strategy.rb', line 29

def prepare_request(messages, request_params)
  # Convert signature output schema to Anthropic tool format
  tool_schema = convert_to_tool_schema
  
  # Add the tool definition to request params
  request_params[:tools] = [tool_schema]
  
  # Force the model to use our tool
  request_params[:tool_choice] = {
    type: "tool",
    name: "json_output"
  }
  
  # Update the last user message to request tool use
  if messages.any? && messages.last[:role] == "user"
    messages.last[:content] += "\n\nPlease use the json_output tool to provide your response."
  end
end

#priorityObject



19
20
21
# File 'lib/dspy/lm/strategies/anthropic_tool_use_strategy.rb', line 19

def priority
  95 # Higher priority than extraction strategy - tool use is more reliable
end