fix(realtime): unblock fixed speech after tool calls
This commit is contained in:
@@ -109,6 +109,8 @@ class QwenAudioRealtimeService(AIService):
|
||||
self._websocket = None
|
||||
self._receive_task: asyncio.Task | None = None
|
||||
self._session_ready = asyncio.Event()
|
||||
self._response_done = asyncio.Event()
|
||||
self._response_done.set()
|
||||
self._pending_events: list[dict[str, Any]] = []
|
||||
self._warned_input_sample_rate = False
|
||||
|
||||
@@ -123,7 +125,10 @@ class QwenAudioRealtimeService(AIService):
|
||||
self._user_transcript_timestamp = ""
|
||||
self._deferred_assistant_messages: list[dict[str, Any]] = []
|
||||
self._tools: list[RealtimeTool] = []
|
||||
self._tool_session = RealtimeToolSession(self._send_tool_event)
|
||||
self._tool_session = RealtimeToolSession(
|
||||
self._send_tool_event,
|
||||
wait_for_response_boundary=self._response_done.wait,
|
||||
)
|
||||
self._fixed_speech_completion: asyncio.Future[None] | None = None
|
||||
self._suppress_response_transcript = False
|
||||
self._speech_started_handler: SpeechStartedHandler | None = None
|
||||
@@ -373,6 +378,7 @@ class QwenAudioRealtimeService(AIService):
|
||||
websocket = self._websocket
|
||||
self._websocket = None
|
||||
self._session_ready.clear()
|
||||
self._response_done.set()
|
||||
self._pending_events.clear()
|
||||
self._response_active = False
|
||||
self._user_transcript_pending = False
|
||||
@@ -404,6 +410,9 @@ class QwenAudioRealtimeService(AIService):
|
||||
if self._websocket is websocket:
|
||||
self._websocket = None
|
||||
self._session_ready.clear()
|
||||
self._response_done.set()
|
||||
self._greeting_request_item_id = None
|
||||
self._resolve_fixed_speech()
|
||||
if self._receive_task is asyncio.current_task():
|
||||
self._receive_task = None
|
||||
|
||||
@@ -424,6 +433,7 @@ class QwenAudioRealtimeService(AIService):
|
||||
await self._send_event(payload, wait_until_ready=False)
|
||||
elif event_type == "response.created":
|
||||
self._response_active = True
|
||||
self._response_done.clear()
|
||||
self._audio_suppressed = False
|
||||
elif event_type == "response.audio.delta":
|
||||
audio = event.get("delta")
|
||||
@@ -473,13 +483,17 @@ class QwenAudioRealtimeService(AIService):
|
||||
await self._finish_assistant_text(interrupted=interrupted)
|
||||
await self._delete_greeting_request()
|
||||
self._resolve_fixed_speech()
|
||||
self._response_done.set()
|
||||
elif event_type == "response.output_item.added":
|
||||
self._remember_function_call(event)
|
||||
elif event_type in {
|
||||
"response.function_call_arguments.done",
|
||||
"response.output_item.done",
|
||||
}:
|
||||
await self._handle_function_call_event(event)
|
||||
self.create_task(
|
||||
self._handle_function_call_event(dict(event)),
|
||||
name="qwen_audio_realtime_tool_call",
|
||||
)
|
||||
elif event_type == "error":
|
||||
error = event.get("error")
|
||||
message = error.get("message") if isinstance(error, dict) else str(error)
|
||||
@@ -527,12 +541,18 @@ class QwenAudioRealtimeService(AIService):
|
||||
)
|
||||
if not name:
|
||||
return
|
||||
await self._tool_session.handle_call(
|
||||
name=name,
|
||||
call_id=call_id,
|
||||
arguments=source.get("arguments", event.get("arguments")),
|
||||
)
|
||||
self._function_names.pop(call_id, None)
|
||||
try:
|
||||
await self._tool_session.handle_call(
|
||||
name=name,
|
||||
call_id=call_id,
|
||||
arguments=source.get("arguments", event.get("arguments")),
|
||||
)
|
||||
except asyncio.CancelledError:
|
||||
raise
|
||||
except Exception as exc: # noqa: BLE001 - background provider task
|
||||
logger.exception(f"Qwen-Audio Realtime 工具调用处理失败:{exc}")
|
||||
finally:
|
||||
self._function_names.pop(call_id, None)
|
||||
|
||||
def _remember_function_call(self, event: dict[str, Any]) -> None:
|
||||
item = event.get("item")
|
||||
|
||||
Reference in New Issue
Block a user