Module: LLM::AnthropicMethods

Included in:
Anthropic
Defined in:
lib/scout/llm/backends/anthropic.rb

Instance Method Summary collapse

Instance Method Details

#client(options, messages = nil) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/scout/llm/backends/anthropic.rb', line 20

def client(options, messages = nil)
  url, key = IndiferentHash.process_options options,
    :url, :key

  # ScoutCoder: the anthropic gem (>= 1.x, e.g. 1.17.0) Client#initialize
  # accepts api_key: / auth_token: / base_url:, NOT access_token: (that
  # is ruby-openai's keyword). Passing access_token: raises
  # ArgumentError: unknown keyword. Verify kwargs against the installed
  # gem's lib/anthropic/client.rb when touching this.
  Object::Anthropic::Client.new(
    api_key: key,
    base_url: url
  )
end

#embed_query(client, text, options = {}) ⇒ Object



101
102
103
# File 'lib/scout/llm/backends/anthropic.rb', line 101

def embed_query(client, text, options = {})
  raise 'Anthropic does not offer embeddings'
end

#extra_options(options, messages = nil) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/scout/llm/backends/anthropic.rb', line 7

def extra_options(options, messages = nil)
  format, max_tokens = IndiferentHash.process_options options, :format, :max_tokens, max_tokens: 1000

  options[:max_tokens] = max_tokens

  case format.to_sym
  when :json, :json_object
    options[:response_format] = { type: 'json_object' }
  else
    options[:response_format] = { type: format }
  end if format
end

#format_tool_call(message) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/scout/llm/backends/anthropic.rb', line 52

def format_tool_call(message)
  tool_call = IndiferentHash.setup(JSON.parse(message[:content]))
  arguments = tool_call.delete('arguments') || tool_call[:function].delete('arguments') || '{}'
  arguments = JSON.parse arguments if String === arguments
  name = tool_call[:name]
  id = tool_call.delete('call_id') || tool_call.delete('id') || tool_call.delete('tool_use_id')
  tool_call['id'] = id
  tool_call['type'] = 'tool_use'
  tool_call['name'] ||= name
  tool_call['input'] = arguments
  tool_call.delete :function
  { role: 'assistant', content: [tool_call] }
end

#format_tool_definitions(tools) ⇒ Object



41
42
43
44
45
46
47
48
49
50
# File 'lib/scout/llm/backends/anthropic.rb', line 41

def format_tool_definitions(tools)
  tools.values.collect do |obj, info|
    info = obj if Hash === obj
    IndiferentHash.setup(info)
    info[:type] = 'custom' if info[:type] == 'function'
    info[:input_schema] = info.delete('parameters') if info['parameters']
    info[:description] ||= ''
    info
  end
end

#format_tool_output(message, last_id = nil) ⇒ Object



66
67
68
69
70
71
# File 'lib/scout/llm/backends/anthropic.rb', line 66

def format_tool_output(message, last_id = nil)
  info = JSON.parse(message[:content])
  id = info.delete('call_id') || info.delete('id') || info.delete('tool_use_id') || info[:function].delete('id')
  tool_output = { type: 'tool_result', tool_use_id: id, content: info[:content] }
  { role: 'user', content: [tool_output] }
end

#parse_tool_call(info) ⇒ Object



73
74
75
76
# File 'lib/scout/llm/backends/anthropic.rb', line 73

def parse_tool_call(info)
  arguments, id, name = IndiferentHash.process_options info, :input, :id, :name
  { arguments: arguments, id: id, name: name }
end

#process_response(messages, response, tools, options, &block) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/scout/llm/backends/anthropic.rb', line 78

def process_response(messages, response, tools, options, &block)
  IndiferentHash.setup response

  response[:content].collect do |output|
    IndiferentHash.setup output
    case output[:type].to_s
    when 'text'
      IndiferentHash.setup({ role: :assistant, content: output[:text] })
    when 'reasoning'
      next
    when 'tool_use'
      tool_call = parse_tool_call(output)
      LLM.process_calls(tools, [tool_call], &block)
    when 'web_search_call'
      next
    else
      eee response
      eee output
      raise
    end
  end.compact.flatten
end

#query(client, messages, tools = [], parameters = {}) ⇒ Object



35
36
37
38
39
# File 'lib/scout/llm/backends/anthropic.rb', line 35

def query(client, messages, tools = [], parameters = {})
  parameters[:messages] = messages
  parameters[:tools] = format_tool_definitions(tools) if tools && tools.any?
  client.messages(parameters: parameters)
end