@@ -27,9 +27,7 @@ def initialize(bot, strategy, persist_summaries: true)
27
27
def summarize ( user , &on_partial_blk )
28
28
truncated_content = content_to_summarize . map { |cts | truncate ( cts ) }
29
29
30
- # Done here to cover non-streaming mode.
31
- json_reply_end = "\" }"
32
- summary = fold ( truncated_content , user , &on_partial_blk ) . chomp ( json_reply_end )
30
+ summary = fold ( truncated_content , user , &on_partial_blk )
33
31
34
32
if persist_summaries
35
33
AiSummary . store! ( strategy , llm_model , summary , truncated_content , human : user &.human? )
@@ -113,67 +111,24 @@ def fold(items, user, &on_partial_blk)
113
111
114
112
summary = +""
115
113
116
- # Auxiliary variables to get the summary content from the JSON response.
117
- json_start_buffer = +""
118
- json_start_found = false
119
- # { is optional because Claude uses prefill, so it's not incldued.
120
- # TODO(roman): Maybe extraction should happen in the bot?
121
- json_summary_schema_keys = bot . persona . response_format &.first . to_h
122
- json_reply_start_regex = /\{ ?\s *"#{ json_summary_schema_keys [ :key ] } "\s *:\s *"/
123
- # We need to buffer escaped newlines as the API likes to send \\ and n in different chunks.
124
- partial_unescape_buffer = +""
125
- unescape_regex = %r{\\ (["/bfnrt])}
126
- json_reply_end = "\" }"
127
-
128
114
buffer_blk =
129
115
Proc . new do |partial , cancel , _ , type |
130
- if type . blank?
131
- if bot . returns_json?
132
- # Extract summary from JSON.
133
- if json_start_found
134
- if partial . end_with? ( "\\ " )
135
- partial_unescape_buffer << partial
136
- else
137
- unescaped_partial = partial_unescape_buffer
138
-
139
- buffered_newline = !partial_unescape_buffer . empty? && partial . first == "n"
140
- if buffered_newline
141
- unescaped_partial << partial . first
142
-
143
- unescaped_partial = unescaped_partial . gsub ( "\\ n" , "\n " )
144
- unescaped_partial << partial [ 1 ..] . to_s
145
- else
146
- unescaped_partial << partial . gsub ( "\\ n" , "\n " )
147
- end
148
- partial_unescape_buffer = +""
149
-
150
- summary << unescaped_partial
151
-
152
- on_partial_blk . call ( unescaped_partial , cancel ) if on_partial_blk
153
- end
154
- else
155
- json_start_buffer << partial
156
-
157
- if json_start_buffer . match? ( json_reply_start_regex )
158
- buffered_start = json_start_buffer . gsub ( json_reply_start_regex , "" )
159
- summary << buffered_start
160
-
161
- on_partial_blk . call ( buffered_start , cancel ) if on_partial_blk
162
-
163
- json_start_found = true
164
- end
165
- end
166
- else
167
- # Assume response is a regular completion.
168
- summary << partial
169
- on_partial_blk . call ( partial , cancel ) if on_partial_blk
170
- end
116
+ if type == :structured_output
117
+ json_summary_schema_key = bot . persona . response_format &.first . to_h
118
+ partial_summary = partial [ json_summary_schema_key [ :key ] . to_sym ]
119
+
120
+ summary << partial_summary
121
+ on_partial_blk . call ( partial_summary , cancel ) if on_partial_blk
122
+ elsif type . blank?
123
+ # Assume response is a regular completion.
124
+ summary << partial
125
+ on_partial_blk . call ( partial , cancel ) if on_partial_blk
171
126
end
172
127
end
173
128
174
129
bot . reply ( context , &buffer_blk )
175
130
176
- summary . chomp ( json_reply_end )
131
+ summary
177
132
end
178
133
179
134
def available_tokens
0 commit comments