Class: SmartPrompt::AnthropicAdapter

Inherits:
LLMAdapter show all
Defined in:
lib/smart_prompt/anthropic_adapter.rb

Instance Attribute Summary

Attributes inherited from LLMAdapter

#last_response

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ AnthropicAdapter

Returns a new instance of AnthropicAdapter.



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
# File 'lib/smart_prompt/anthropic_adapter.rb', line 8

def initialize(config)
  super
  SmartPrompt.logger.info "Start create the SmartPrompt AnthropicAdapter."

  # Parse API key (support environment variable reference)
  api_key = @config["api_key"]
  if api_key.is_a?(String) && api_key.start_with?("ENV[") && api_key.end_with?("]")
    api_key = eval(api_key)
  end

  # Determine base_url with priority: config['url'] > ENV['ANTHROPIC_BASE_URL'] > default
  base_url = @config["url"] || ENV["ANTHROPIC_BASE_URL"]

  begin
    # Create Anthropic::Client instance
    client_options = { api_key: api_key }
    client_options[:base_url] = base_url if base_url

    @client = Anthropic::Client.new(**client_options)
    SmartPrompt.logger.info "Successful creation an Anthropic client."
  rescue => e
    SmartPrompt.logger.error "Failed to initialize Anthropic client: #{e.message}"
    raise LLMAPIError, "Invalid Anthropic configuration: #{e.message}"
  end
end

Instance Method Details

#embeddings(text, model) ⇒ Object

Embeddings method (not supported by Anthropic API)

Parameters:

  • text (String)

    Text to generate embeddings for

  • model (String)

    Model name

Raises:

  • (NotImplementedError)

    Always raises as Anthropic doesn’t support embeddings



376
377
378
# File 'lib/smart_prompt/anthropic_adapter.rb', line 376

def embeddings(text, model)
  raise NotImplementedError, "Anthropic API does not support embeddings. Please use OpenAI or other providers for embedding generation."
end

#send_request(messages, model = nil, temperature = nil, tools = nil, proc = nil) ⇒ Hash?

Send request to Anthropic API

Parameters:

  • messages (Array)

    Array of message hashes

  • model (String, nil) (defaults to: nil)

    Model name (optional, uses config default if nil)

  • temperature (Float, nil) (defaults to: nil)

    Temperature value (optional, uses config or 0.7 if nil)

  • tools (Array, nil) (defaults to: nil)

    Array of tool definitions (optional)

  • proc (Proc, nil) (defaults to: nil)

    Callback for streaming responses (optional)

Returns:

  • (Hash, nil)

    OpenAI-formatted response (nil for streaming mode)



294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
# File 'lib/smart_prompt/anthropic_adapter.rb', line 294

def send_request(messages, model = nil, temperature = nil, tools = nil, proc = nil)
  begin
    # Determine model name (parameter > config)
    model_name = model || @config["model"]

    # Determine temperature (config > parameter > default 0.7)
    temp_value = @config["temperature"] || temperature || 0.7

    # Determine max_tokens (config > default 1024)
    max_tokens_value = @config["max_tokens"] || 1024

    SmartPrompt.logger.info "AnthropicAdapter: Sending request to Anthropic"
    SmartPrompt.logger.info "AnthropicAdapter: Using model #{model_name}"

    # Extract system message
    system_message = extract_system_message(messages)

    # Convert messages to Anthropic format
    converted_messages = convert_messages_to_anthropic_format(messages)

    # Build request parameters
    parameters = {
      model: model_name,
      messages: converted_messages,
      max_tokens: max_tokens_value,
      temperature: temp_value,
    }

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

    # Convert and add tools if provided
    if tools
      anthropic_tools = convert_tools_to_anthropic_format(tools)
      parameters[:tools] = anthropic_tools if anthropic_tools
    end

    SmartPrompt.logger.info "Send parameters is: #{parameters}"

    # Send request to Anthropic API
    if proc
      # Streaming mode: use stream method
      stream = @client.messages.stream(**parameters)

      # Iterate through the stream and call proc for each event
      stream.each do |event|
        # Convert event to hash format for compatibility
        event_hash = {
          "type" => event.type.to_s,
        }

        # Add delta information for content_block_delta events
        if event.type == :content_block_delta && event.delta.type == :text_delta
          event_hash["delta"] = { "text" => event.delta.text }
        end

        proc.call(event_hash, 0)
      end

      SmartPrompt.logger.info "Successful send a message (streaming)"
      nil
    else
      # Non-streaming mode: use create method
      response = @client.messages.create(**parameters)
      SmartPrompt.logger.info "Successful send a message"
      SmartPrompt.logger.info "AnthropicAdapter: Received response from Anthropic"

      # Convert response to openai format
      convert_response_to_openai_format(response)
    end
  rescue => e
    SmartPrompt.logger.error "Anthropic API error: #{e.message}"
    SmartPrompt.logger.error "Error class: #{e.class}"
    SmartPrompt.logger.error "Backtrace: #{e.backtrace.first(5).join("\n")}"
    raise LLMAPIError, "Failed to send request to Anthropic: #{e.message}"
  end
end