Skip to content

Commit cc9e637

Browse files
author
w33d
committed
fix: 避免 Spark Lite 改写结构化消息
1 parent 20bce99 commit cc9e637

2 files changed

Lines changed: 92 additions & 6 deletions

File tree

astrbot/core/provider/sources/openai_source.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,19 @@ def _apply_provider_specific_request_overrides(
434434
extra_body.pop(field, None)
435435

436436
messages = payloads.get("messages")
437-
if isinstance(messages, list):
437+
first_user = (
438+
next(
439+
(
440+
message
441+
for message in messages
442+
if isinstance(message, dict) and message.get("role") == "user"
443+
),
444+
None,
445+
)
446+
if isinstance(messages, list)
447+
else None
448+
)
449+
if first_user is None or isinstance(first_user.get("content"), str):
438450
system_parts: list[str] = []
439451
compatible_messages: list[Any] = []
440452
for message in messages:
@@ -454,11 +466,7 @@ def _apply_provider_specific_request_overrides(
454466
if system_parts:
455467
system_prompt = "\n\n".join(system_parts)
456468
for index, message in enumerate(compatible_messages):
457-
if (
458-
isinstance(message, dict)
459-
and message.get("role") == "user"
460-
and isinstance(message.get("content"), str)
461-
):
469+
if isinstance(message, dict) and message.get("role") == "user":
462470
user_message = dict(message)
463471
user_content = user_message.get("content", "")
464472
user_message["content"] = (

tests/test_openai_source.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,6 +1373,84 @@ async def test_spark_lite_does_not_drop_unsupported_history_content():
13731373
await provider.terminate()
13741374

13751375

1376+
@pytest.mark.asyncio
1377+
async def test_spark_lite_keeps_structured_first_user_content_unchanged():
1378+
"""Keep structured first-user content unchanged for fallback handling."""
1379+
provider = _make_provider(
1380+
{
1381+
"api_base": "https://spark-api-open.xf-yun.com/v1",
1382+
"model": "lite",
1383+
}
1384+
)
1385+
try:
1386+
messages = [
1387+
{"role": "system", "content": "persona"},
1388+
{
1389+
"role": "user",
1390+
"content": [{"type": "text", "text": "hello"}],
1391+
},
1392+
]
1393+
payloads = {"model": "lite", "messages": messages}
1394+
1395+
provider._apply_provider_specific_request_overrides(payloads, {})
1396+
1397+
assert payloads["messages"] == messages
1398+
finally:
1399+
await provider.terminate()
1400+
1401+
1402+
@pytest.mark.asyncio
1403+
async def test_spark_lite_converts_string_system_without_user():
1404+
"""Preserve the existing system-only compatibility conversion."""
1405+
provider = _make_provider(
1406+
{
1407+
"api_base": "https://spark-api-open.xf-yun.com/v1",
1408+
"model": "lite",
1409+
}
1410+
)
1411+
try:
1412+
payloads = {
1413+
"model": "lite",
1414+
"messages": [{"role": "system", "content": "persona"}],
1415+
}
1416+
1417+
provider._apply_provider_specific_request_overrides(payloads, {})
1418+
1419+
assert payloads["messages"] == [
1420+
{"role": "user", "content": "persona"}
1421+
]
1422+
finally:
1423+
await provider.terminate()
1424+
1425+
1426+
@pytest.mark.asyncio
1427+
async def test_spark_lite_does_not_move_system_prompt_past_structured_user():
1428+
"""Do not move a system prompt into a later string user message."""
1429+
provider = _make_provider(
1430+
{
1431+
"api_base": "https://spark-api-open.xf-yun.com/v1",
1432+
"model": "lite",
1433+
}
1434+
)
1435+
try:
1436+
messages = [
1437+
{"role": "system", "content": "persona"},
1438+
{
1439+
"role": "user",
1440+
"content": [{"type": "text", "text": "hello"}],
1441+
},
1442+
{"role": "assistant", "content": "answer"},
1443+
{"role": "user", "content": "continue"},
1444+
]
1445+
payloads = {"model": "lite", "messages": messages}
1446+
1447+
provider._apply_provider_specific_request_overrides(payloads, {})
1448+
1449+
assert payloads["messages"] == messages
1450+
finally:
1451+
await provider.terminate()
1452+
1453+
13761454
@pytest.mark.asyncio
13771455
@pytest.mark.parametrize("streaming", [False, True])
13781456
async def test_spark_lite_query_removes_unsupported_request_fields(

0 commit comments

Comments
 (0)