Skip to content

Commit 7763d9c

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

2 files changed

Lines changed: 68 additions & 11 deletions

File tree

astrbot/core/provider/sources/openai_source.py

Lines changed: 14 additions & 11 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 not None and 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"] = (
@@ -468,11 +476,6 @@ def _apply_provider_specific_request_overrides(
468476
)
469477
compatible_messages[index] = user_message
470478
break
471-
else:
472-
compatible_messages.insert(
473-
0,
474-
{"role": "user", "content": system_prompt},
475-
)
476479

477480
payloads["messages"] = compatible_messages
478481

tests/test_openai_source.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,6 +1373,60 @@ 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_does_not_move_system_prompt_past_structured_user():
1404+
"""Do not move a system prompt into a later string user message."""
1405+
provider = _make_provider(
1406+
{
1407+
"api_base": "https://spark-api-open.xf-yun.com/v1",
1408+
"model": "lite",
1409+
}
1410+
)
1411+
try:
1412+
messages = [
1413+
{"role": "system", "content": "persona"},
1414+
{
1415+
"role": "user",
1416+
"content": [{"type": "text", "text": "hello"}],
1417+
},
1418+
{"role": "assistant", "content": "answer"},
1419+
{"role": "user", "content": "continue"},
1420+
]
1421+
payloads = {"model": "lite", "messages": messages}
1422+
1423+
provider._apply_provider_specific_request_overrides(payloads, {})
1424+
1425+
assert payloads["messages"] == messages
1426+
finally:
1427+
await provider.terminate()
1428+
1429+
13761430
@pytest.mark.asyncio
13771431
@pytest.mark.parametrize("streaming", [False, True])
13781432
async def test_spark_lite_query_removes_unsupported_request_fields(

0 commit comments

Comments
 (0)