Class: DSPy::LM::AnthropicAdapter

Inherits:
Adapter
  • Object
show all
Defined in:
lib/dspy/lm/adapters/anthropic_adapter.rb

Instance Attribute Summary

Attributes inherited from Adapter

#api_key, #model

Instance Method Summary collapse

Constructor Details

#initialize(model:, api_key:) ⇒ AnthropicAdapter

Returns a new instance of AnthropicAdapter.



8
9
10
11
12
# File 'lib/dspy/lm/adapters/anthropic_adapter.rb', line 8

def initialize(model:, api_key:)
  super
  validate_api_key!(api_key, 'anthropic')
  @client = Anthropic::Client.new(api_key: api_key)
end

Instance Method Details

#chat(messages:, signature: nil, **extra_params, &block) ⇒ Object



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
44
45
46
47
48
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
80
# File 'lib/dspy/lm/adapters/anthropic_adapter.rb', line 14

def chat(messages:, signature: nil, **extra_params, &block)
  # Anthropic requires system message to be separate from messages
  system_message, user_messages = extract_system_message(normalize_messages(messages))
  
  # Apply JSON prefilling if needed for better Claude JSON compliance
  user_messages = prepare_messages_for_json(user_messages, system_message)
  
  request_params = {
    model: model,
    messages: user_messages,
    max_tokens: 4096, # Required for Anthropic
    temperature: 0.0 # DSPy default for deterministic responses
  }

  # Add system message if present
  request_params[:system] = system_message if system_message

  # Add streaming if block provided
  if block_given?
    request_params[:stream] = true
  end

  begin
    if block_given?
      content = ""
      @client.messages.stream(**request_params) do |chunk|
        if chunk.respond_to?(:delta) && chunk.delta.respond_to?(:text)
          chunk_text = chunk.delta.text
          content += chunk_text
          block.call(chunk)
        end
      end
      
      Response.new(
        content: content,
        usage: nil, # Usage not available in streaming
        metadata: {
          provider: 'anthropic',
          model: model,
          streaming: true
        }
      )
    else
      response = @client.messages.create(**request_params)
      
      if response.respond_to?(:error) && response.error
        raise AdapterError, "Anthropic API error: #{response.error}"
      end

      content = response.content.first.text if response.content.is_a?(Array) && response.content.first
      usage = response.usage

      Response.new(
        content: content,
        usage: usage.respond_to?(:to_h) ? usage.to_h : usage,
        metadata: {
          provider: 'anthropic',
          model: model,
          response_id: response.id,
          role: response.role
        }
      )
    end
  rescue => e
    raise AdapterError, "Anthropic adapter error: #{e.message}"
  end
end