From 471070c2c86ea23214d8cc2e2ef3c25a7ab0b13b Mon Sep 17 00:00:00 2001 From: Lynn Date: Fri, 14 Aug 2026 16:27:34 +0800 Subject: [PATCH] Fix: return error when no valid speech text in intranscription response (#18277) --- api/apps/restful_apis/chat_api.py | 2 ++ rag/llm/sequence2txt_model.py | 16 ++++++++++++++-- .../unit_test/rag/llm/test_sequence2txt_model.py | 2 +- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/api/apps/restful_apis/chat_api.py b/api/apps/restful_apis/chat_api.py index 1d9658595a..92b32ddc88 100644 --- a/api/apps/restful_apis/chat_api.py +++ b/api/apps/restful_apis/chat_api.py @@ -1151,6 +1151,8 @@ async def transcription(): os.remove(temp_audio_path) except Exception as e: logging.error(f"Failed to remove temp audio file: {str(e)}") + if "**ERROR**" in text: + return get_data_error_result(message=text) return get_json_result(data={"text": text}) async def event_stream(): diff --git a/rag/llm/sequence2txt_model.py b/rag/llm/sequence2txt_model.py index 2c96dce3d0..cb57f9f407 100644 --- a/rag/llm/sequence2txt_model.py +++ b/rag/llm/sequence2txt_model.py @@ -230,7 +230,13 @@ class QWenSeq2txt(Base): resp = dashscope.MultiModalConversation.call(model=self.model_name, messages=messages, result_format="message", asr_options={"enable_lid": True, "enable_itn": False}) try: - text = resp["output"]["choices"][0]["message"].content[0]["text"] + choices = resp["output"].get("choices") or [] + if not choices: + raise ValueError("no valid speech content in response") + content = (choices[0].get("message") or {}).get("content") or [] + if not content or "text" not in content[0]: + raise ValueError("no speech text in response") + text = content[0]["text"] except Exception as e: text = "**ERROR**: " + str(e) return text, num_tokens_from_string(text) @@ -369,7 +375,13 @@ class QWenSeq2txt(Base): full = "" for chunk in stream: try: - piece = chunk["output"]["choices"][0]["message"].content[0]["text"] + choices = chunk["output"].get("choices") or [] + if not choices: + raise ValueError("no valid speech content in response") + content = (choices[0].get("message") or {}).get("content") or [] + if not content or "text" not in content[0]: + raise ValueError("no speech text in response") + piece = content[0]["text"] full = piece yield {"event": "delta", "text": piece} except Exception as e: diff --git a/test/unit_test/rag/llm/test_sequence2txt_model.py b/test/unit_test/rag/llm/test_sequence2txt_model.py index 42f3c16bfe..0eed80cb11 100644 --- a/test/unit_test/rag/llm/test_sequence2txt_model.py +++ b/test/unit_test/rag/llm/test_sequence2txt_model.py @@ -46,7 +46,7 @@ def test_fun_asr_flash_uses_native_request_format(tmp_path): def test_qwen_audio_asr_keeps_existing_dashscope_path(): - response = {"output": {"choices": [{"message": MagicMock(content=[{"text": "legacy text"}])}]}} + response = {"output": {"choices": [{"message": {"content": [{"text": "legacy text"}]}}]}} with patch("dashscope.MultiModalConversation.call", return_value=response) as call: model = QWenSeq2txt("test-key", "qwen-audio-asr")