Skip to content

Commit efa020a

Browse files
committed
Merge branch 'community-main' into image-tool
2 parents 1704a8e + c66899d commit efa020a

File tree

1 file changed

+50
-9
lines changed

1 file changed

+50
-9
lines changed

lib/ruby_llm/stream_accumulator.rb

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@ class StreamAccumulator
66
attr_reader :content, :model_id, :tool_calls
77

88
def initialize
9-
@content = +''
9+
@content = nil
1010
@tool_calls = {}
1111
@input_tokens = 0
1212
@output_tokens = 0
13-
@cached_tokens = 0
14-
@cache_creation_tokens = 0
1513
@latest_tool_call_id = nil
1614
end
1715

@@ -22,7 +20,7 @@ def add(chunk)
2220
if chunk.tool_call?
2321
accumulate_tool_calls chunk.tool_calls
2422
else
25-
@content << (chunk.content || '')
23+
accumulate_content(chunk.content)
2624
end
2725

2826
count_tokens chunk
@@ -32,19 +30,64 @@ def add(chunk)
3230
def to_message(response)
3331
Message.new(
3432
role: :assistant,
35-
content: content.empty? ? nil : content,
33+
content: final_content,
3634
model_id: model_id,
3735
tool_calls: tool_calls_from_stream,
3836
input_tokens: @input_tokens.positive? ? @input_tokens : nil,
3937
output_tokens: @output_tokens.positive? ? @output_tokens : nil,
40-
cached_tokens: @cached_tokens.positive? ? @cached_tokens : nil,
41-
cache_creation_tokens: @cache_creation_tokens.positive? ? @cache_creation_tokens : nil,
4238
raw: response
4339
)
4440
end
4541

4642
private
4743

44+
def accumulate_content(new_content)
45+
return unless new_content
46+
47+
if @content.nil?
48+
@content = new_content.is_a?(String) ? +new_content : new_content
49+
else
50+
case [@content.class, new_content.class]
51+
when [String, String]
52+
@content << new_content
53+
when [String, Content]
54+
# Convert accumulated string to Content and merge
55+
@content = Content.new(@content)
56+
merge_content(new_content)
57+
when [Content, String]
58+
# Append string to existing Content's text
59+
@content.instance_variable_set(:@text, (@content.text || '') + new_content)
60+
when [Content, Content]
61+
merge_content(new_content)
62+
end
63+
end
64+
end
65+
66+
def merge_content(new_content)
67+
# Merge text
68+
current_text = @content.text || ''
69+
new_text = new_content.text || ''
70+
@content.instance_variable_set(:@text, current_text + new_text)
71+
72+
# Merge attachments
73+
new_content.attachments.each do |attachment|
74+
@content.attach(attachment)
75+
end
76+
end
77+
78+
def final_content
79+
case @content
80+
when nil
81+
nil
82+
when String
83+
@content.empty? ? nil : @content
84+
when Content
85+
@content.text.nil? && @content.attachments.empty? ? nil : @content
86+
else
87+
@content
88+
end
89+
end
90+
4891
def tool_calls_from_stream
4992
tool_calls.transform_values do |tc|
5093
arguments = if tc.arguments.is_a?(String) && !tc.arguments.empty?
@@ -94,8 +137,6 @@ def find_tool_call(tool_call_id)
94137
def count_tokens(chunk)
95138
@input_tokens = chunk.input_tokens if chunk.input_tokens
96139
@output_tokens = chunk.output_tokens if chunk.output_tokens
97-
@cached_tokens = chunk.cached_tokens if chunk.cached_tokens
98-
@cache_creation_tokens = chunk.cache_creation_tokens if chunk.cache_creation_tokens
99140
end
100141
end
101142
end

0 commit comments

Comments
 (0)