@@ -27,9 +27,7 @@ def initialize(bot, strategy, persist_summaries: true)
2727 def summarize ( user , &on_partial_blk )
2828 truncated_content = content_to_summarize . map { |cts | truncate ( cts ) }
2929
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 )
3331
3432 if persist_summaries
3533 AiSummary . store! ( strategy , llm_model , summary , truncated_content , human : user &.human? )
@@ -113,67 +111,24 @@ def fold(items, user, &on_partial_blk)
113111
114112 summary = +""
115113
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-
128114 buffer_blk =
129115 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
171126 end
172127 end
173128
174129 bot . reply ( context , &buffer_blk )
175130
176- summary . chomp ( json_reply_end )
131+ summary
177132 end
178133
179134 def available_tokens
0 commit comments