bibibi12345 commited on
Commit
0da76bb
·
1 Parent(s): 433bff2

tentative tool call support

Browse files
Files changed (1) hide show
  1. app/openai_handler.py +49 -18
app/openai_handler.py CHANGED
@@ -245,30 +245,61 @@ class OpenAIDirectHandler:
245
  # print(f"DEBUG: Chunk {chunk_count} - Processed content: '{processed_content}', Reasoning: '{current_reasoning[:50]}...' if len(current_reasoning) > 50 else '{current_reasoning}'")
246
 
247
  # Send chunks for both reasoning and content as they arrive
248
- chunks_to_send = []
249
-
250
- # If we have reasoning content, send it
 
 
251
  if current_reasoning:
252
- reasoning_chunk_payload = chunk_as_dict.copy()
253
- reasoning_chunk_payload['choices'][0]['delta'] = {'reasoning_content': current_reasoning}
254
- chunks_to_send.append(reasoning_chunk_payload)
 
 
 
 
 
 
255
 
256
- # If we have regular content, send it
257
  if processed_content:
258
- content_chunk_payload = chunk_as_dict.copy()
259
- content_chunk_payload['choices'][0]['delta'] = {'content': processed_content}
260
- chunks_to_send.append(content_chunk_payload)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
261
  has_sent_content = True
262
 
263
- # Send all chunks
264
- for chunk_to_send_payload in chunks_to_send:
265
- yielded_data_str = f"data: {json.dumps(chunk_to_send_payload)}\n\n"
266
- print(f"DEBUG_OPENAI_STREAM: Chunk {chunk_count} - Yielding from process_chunk: {yielded_data_str.strip()}") # Kilo Code Added Log
267
- yield yielded_data_str
268
- else:
269
- # Still yield the chunk even if no content (could have other delta fields)
 
 
 
 
270
  yielded_data_str = f"data: {json.dumps(chunk_as_dict)}\n\n"
271
- print(f"DEBUG_OPENAI_STREAM: Chunk {chunk_count} - Yielding (original delta no content): {yielded_data_str.strip()}") # Kilo Code Added Log
272
  yield yielded_data_str
273
  else:
274
  # Yield chunks without choices too (they might contain metadata)
 
245
  # print(f"DEBUG: Chunk {chunk_count} - Processed content: '{processed_content}', Reasoning: '{current_reasoning[:50]}...' if len(current_reasoning) > 50 else '{current_reasoning}'")
246
 
247
  # Send chunks for both reasoning and content as they arrive
248
+ # Kilo Code: Revised payload construction
249
+ original_choice = chunk_as_dict['choices'][0]
250
+ original_finish_reason = original_choice.get('finish_reason')
251
+ original_usage = original_choice.get('usage')
252
+
253
  if current_reasoning:
254
+ reasoning_delta = {'reasoning_content': current_reasoning}
255
+ reasoning_payload = {
256
+ "id": chunk_as_dict["id"], "object": chunk_as_dict["object"],
257
+ "created": chunk_as_dict["created"], "model": chunk_as_dict["model"],
258
+ "choices": [{"index": 0, "delta": reasoning_delta, "finish_reason": None}]
259
+ }
260
+ yielded_data_str = f"data: {json.dumps(reasoning_payload)}\n\n"
261
+ print(f"DEBUG_OPENAI_STREAM: Chunk {chunk_count} - Yielding REASONING: {yielded_data_str.strip()}")
262
+ yield yielded_data_str
263
 
 
264
  if processed_content:
265
+ content_delta = {'content': processed_content}
266
+ # Determine if this processed_content chunk should carry the original finish_reason and usage.
267
+ # It should if the reasoning processor is NOT inside a tag after this,
268
+ # meaning this processed_content is the final part of any tagged content from original_content_from_delta.
269
+ finish_reason_for_this_content_delta = None
270
+ usage_for_this_content_delta = None
271
+
272
+ if original_finish_reason and not reasoning_processor.inside_tag:
273
+ finish_reason_for_this_content_delta = original_finish_reason
274
+ if original_usage:
275
+ usage_for_this_content_delta = original_usage
276
+
277
+ content_payload = {
278
+ "id": chunk_as_dict["id"], "object": chunk_as_dict["object"],
279
+ "created": chunk_as_dict["created"], "model": chunk_as_dict["model"],
280
+ "choices": [{"index": 0, "delta": content_delta, "finish_reason": finish_reason_for_this_content_delta}]
281
+ }
282
+ if usage_for_this_content_delta:
283
+ content_payload['choices'][0]['usage'] = usage_for_this_content_delta
284
+
285
+ yielded_data_str = f"data: {json.dumps(content_payload)}\n\n"
286
+ print(f"DEBUG_OPENAI_STREAM: Chunk {chunk_count} - Yielding CONTENT: {yielded_data_str.strip()}")
287
+ yield yielded_data_str
288
  has_sent_content = True
289
 
290
+ # If neither reasoning nor processed_content was generated from a non-empty original content,
291
+ # it implies the original content might have been just a tag or something consumed entirely.
292
+ # In this case, do nothing more for this path; the original chunk's other properties (like finish_reason if content was empty) are handled below.
293
+
294
+ elif original_finish_reason: # Original delta had no content, but had a finish_reason
295
+ # This case handles chunks that are purely for signaling stream end or other non-content states.
296
+ yielded_data_str = f"data: {json.dumps(chunk_as_dict)}\n\n" # Yield original chunk as is
297
+ print(f"DEBUG_OPENAI_STREAM: Chunk {chunk_count} - Yielding (original delta no content, but has finish_reason): {yielded_data_str.strip()}")
298
+ yield yielded_data_str
299
+ # If original delta had no content and no finish_reason, it's an empty delta, yield as is.
300
+ elif not content and not original_finish_reason : # Kilo Code: Added this condition
301
  yielded_data_str = f"data: {json.dumps(chunk_as_dict)}\n\n"
302
+ print(f"DEBUG_OPENAI_STREAM: Chunk {chunk_count} - Yielding (original delta empty): {yielded_data_str.strip()}")
303
  yield yielded_data_str
304
  else:
305
  # Yield chunks without choices too (they might contain metadata)