Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion astrbot/core/provider/sources/openai_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,11 @@ async def _parse_openai_completion(
raise Exception(
"API 返回的 completion 由于内容安全过滤被拒绝(非 AstrBot)。",
)
if llm_response.completion_text is None and not llm_response.tools_call_args:
if (
llm_response.completion_text is None
and not llm_response.tools_call_args
and not llm_response.reasoning_content
):
logger.error(f"API 返回的 completion 无法解析:{completion}。")
raise Exception(f"API 返回的 completion 无法解析:{completion}。")

Expand Down
31 changes: 31 additions & 0 deletions tests/test_openai_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,37 @@ def test_extract_error_text_candidates_truncates_long_response_text():
)


@pytest.mark.asyncio
async def test_parse_openai_completion_accepts_reasoning_only_response(monkeypatch):
provider = _make_provider()
try:
completion = SimpleNamespace(
id="chatcmpl-test",
choices=[
SimpleNamespace(
finish_reason="stop",
message=SimpleNamespace(content=None, tool_calls=[]),
)
],
usage=None,
)
monkeypatch.setattr(
provider,
"_extract_reasoning_content",
lambda _completion: "我先思考一下这个问题",
)

llm_response = await provider._parse_openai_completion(completion, tools=None)

assert llm_response.role == "assistant"
assert llm_response.completion_text is None
assert llm_response.reasoning_content == "我先思考一下这个问题"
assert llm_response.raw_completion is completion
assert llm_response.id == "chatcmpl-test"
finally:
await provider.terminate()


@pytest.mark.asyncio
async def test_handle_api_error_content_moderated_without_images_raises():
provider = _make_provider(
Expand Down