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
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
# File 'lib/active_agent/providers/anthropic.rb', line 8
def chat(messages, tools: [], &block)
api_model = model || "claude-3-5-sonnet-latest"
url = "https://api.anthropic.com/v1/messages"
system_message = messages.find { |m| m[:role].to_s == "system" }
history_messages = messages.reject { |m| m[:role].to_s == "system" }
body = {
model: api_model,
max_tokens: 4096,
messages: format_messages(history_messages)
}
if system_message && !system_message[:content].to_s.empty?
body[:system] = system_message[:content]
end
if tools.any?
body[:tools] = format_tools(tools)
end
= {
"Content-Type" => "application/json",
"x-api-key" => api_key,
"anthropic-version" => "2023-06-01"
}
if block_given?
body[:stream] = true
text_accumulator = ""
tool_calls_accumulator = {}
post_request(url, , body) do |line|
next unless line.start_with?("data:")
json_str = line.sub("data:", "").strip
next if json_str.empty?
begin
event_data = JSON.parse(json_str)
case event_data["type"]
when "content_block_start"
index = event_data["index"]
block_info = event_data["content_block"]
if block_info["type"] == "tool_use"
tool_calls_accumulator[index] = {
id: block_info["id"],
name: block_info["name"],
partial_json: ""
}
end
when "content_block_delta"
index = event_data["index"]
delta = event_data["delta"]
if delta["type"] == "text_delta"
text_accumulator += delta["text"]
yield(delta["text"])
elsif delta["type"] == "input_json_delta"
tool_calls_accumulator[index][:partial_json] += delta["partial_json"] if tool_calls_accumulator[index]
end
end
rescue JSON::ParserError
end
end
tool_calls = tool_calls_accumulator.values.map do |tc|
args = {}
begin
args = JSON.parse(tc[:partial_json], symbolize_names: true) unless tc[:partial_json].empty?
rescue JSON::ParserError
ActiveAgent.logger.warn("Anthropic could not parse streaming tool input JSON: #{tc[:partial_json]}")
end
{
id: tc[:id],
name: tc[:name],
args: args
}
end
result = { role: "assistant" }
result[:content] = text_accumulator unless text_accumulator.empty?
result[:tool_calls] = tool_calls if tool_calls.any?
result
else
response_json = post_request(url, , body)
parse_response(response_json)
end
end
|