Class: Inquirex::LLM::AnthropicAdapter

Inherits:
Adapter
  • Object
show all
Defined in:
lib/inquirex/llm/anthropic_adapter.rb

Overview

Real Anthropic Claude adapter for inquirex-llm.

Usage:

adapter = Inquirex::LLM::AnthropicAdapter.new(
api_key: ENV["ANTHROPIC_API_KEY"],
model:   "claude-sonnet-4-20250514"
)
result = adapter.call(engine.current_step, engine.answers)

The adapter:

1. Gathers source answers from the step's `from` / `from_all` declaration
2. Builds a prompt that includes the schema as a JSON contract
3. Calls the Anthropic Messages API
4. Parses the JSON response
5. Validates output against the declared schema
6. Returns the structured hash

Constant Summary collapse

API_URL =
"https://api.anthropic.com/v1/messages"
API_VERSION =
"2023-06-01"
DEFAULT_MODEL =
"claude-sonnet-4-20250514"
DEFAULT_MAX_TOKENS =
2048
DEFAULT_SUMMARY_MAX_TOKENS =

Summaries want a little more room than an extraction (prose, not a handful of fields) and a little more warmth than one (0.2 produces summaries that read like a database dump).

4096
DEFAULT_SUMMARY_TEMPERATURE =
0.4
MODEL_MAP =

Maps Inquirex short model symbols to concrete Anthropic model ids.

{
  claude_sonnet: "claude-sonnet-4-20250514",
  claude_haiku:  "claude-haiku-4-5-20251001",
  claude_opus:   "claude-opus-4-20250514"
}.freeze

Instance Method Summary collapse

Methods inherited from Adapter

#normalize_output, #source_answers, #summary_input, #validate_output!

Constructor Details

#initialize(api_key: nil, model: nil) ⇒ AnthropicAdapter

Returns a new instance of AnthropicAdapter.

Parameters:

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

    defaults to ENV

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

    default model id when a node does not specify one



47
48
49
50
51
52
53
# File 'lib/inquirex/llm/anthropic_adapter.rb', line 47

def initialize(api_key: nil, model: nil)
  super()
  @api_key = api_key || ENV.fetch("ANTHROPIC_API_KEY") {
    raise ArgumentError, "ANTHROPIC_API_KEY is required (pass api_key: or set the env var)"
  }
  @default_model = model || DEFAULT_MODEL
end

Instance Method Details

#call(node, answers = {}) ⇒ Hash

Returns structured data matching the node's schema.

Parameters:

  • node (Inquirex::LLM::Node)

    the current LLM step

  • answers (Hash) (defaults to: {})

    all collected answers so far

Returns:

  • (Hash)

    structured data matching the node's schema

Raises:



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/inquirex/llm/anthropic_adapter.rb', line 60

def call(node, answers = {})
  source      = source_answers(node, answers)
  model       = resolve_model(node)
  temperature = node.respond_to?(:temperature) ? (node.temperature || 0.2) : 0.2
  max_tokens  = node.respond_to?(:max_tokens)  ? (node.max_tokens  || DEFAULT_MAX_TOKENS) : DEFAULT_MAX_TOKENS

  response = call_api(
    model:       model,
    system:      build_system_prompt(node),
    user:        build_user_prompt(node, source, answers),
    temperature: temperature,
    max_tokens:  max_tokens
  )

  result = normalize_output(node, parse_response(response))
  validate_output!(node, result)
  result
end

#summarize(node, transcript, _answers = {}) ⇒ String

Generates the closing summary for a summarize step.

The system prompt is Prompts::SUMMARIZE — the node's own prompt is that same constant, but reading it from the constant means a node forged by hand or deserialized from a tampered definition still cannot substitute its own instructions.

Parameters:

  • node (Inquirex::LLM::Node)

    the summarize step

  • transcript (String)

    the session transcript

  • answers (Hash)

    unused; accepted for interface symmetry

Returns:

  • (String)

    markdown summary

Raises:



91
92
93
94
95
96
97
98
99
100
# File 'lib/inquirex/llm/anthropic_adapter.rb', line 91

def summarize(node, transcript, _answers = {})
  response = call_api(
    model:       resolve_model(node),
    system:      Prompts::SUMMARIZE,
    user:        summary_input(transcript),
    temperature: node.respond_to?(:temperature) ? (node.temperature || DEFAULT_SUMMARY_TEMPERATURE) : DEFAULT_SUMMARY_TEMPERATURE,
    max_tokens:  node.respond_to?(:max_tokens) ? (node.max_tokens || DEFAULT_SUMMARY_MAX_TOKENS) : DEFAULT_SUMMARY_MAX_TOKENS
  )
  parse_text_response(response)
end