Skip to content
Open
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
156 changes: 156 additions & 0 deletions tests/unit/service/test_llm_request_rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,159 @@ def test_fill_missing_reasoning_content_thinking_disabled():
next_request, applied_rules = apply_llm_request_rules(request)

assert "FillMissingReasoningContentRule" not in applied_rules


# ===== StripRequiredToolChoiceForReasoningRule 边界场景 =====


def test_strip_tool_choice_not_triggered_when_reasoning_effort_empty_string():
"""reasoning_effort 为空字符串时不触发 StripRequiredToolChoiceForReasoningRule。"""
request = llmApiUtil.OpenAIRequest(
model="deepseek-v4-pro",
messages=[llmApiUtil.OpenAIMessage.text(llmApiUtil.OpenaiApiRole.USER, "hello")],
tool_choice="required",
provider_params={"reasoning_effort": ""},
)

next_request, applied_rules = apply_llm_request_rules(request)

assert next_request.tool_choice == "required"
assert applied_rules == ()


def test_strip_tool_choice_not_triggered_when_tool_choice_is_none():
"""tool_choice 为 None 时不触发 StripRequiredToolChoiceForReasoningRule。"""
request = llmApiUtil.OpenAIRequest(
model="deepseek-v4-pro",
messages=[llmApiUtil.OpenAIMessage.text(llmApiUtil.OpenaiApiRole.USER, "hello")],
tool_choice=None,
provider_params={"reasoning_effort": "high"},
)

next_request, applied_rules = apply_llm_request_rules(request)

assert next_request.tool_choice is None
assert applied_rules == ()


def test_strip_tool_choice_not_triggered_when_provider_params_empty():
"""provider_params 为空字典时不触发 StripRequiredToolChoiceForReasoningRule。"""
request = llmApiUtil.OpenAIRequest(
model="deepseek-v4-pro",
messages=[llmApiUtil.OpenAIMessage.text(llmApiUtil.OpenaiApiRole.USER, "hello")],
tool_choice="required",
provider_params={},
)

next_request, applied_rules = apply_llm_request_rules(request)

assert next_request.tool_choice == "required"
assert applied_rules == ()


# ===== FillMissingReasoningContentRule 边界场景 =====


def test_fill_missing_reasoning_content_not_triggered_for_plain_assistant_message():
"""纯文本 assistant 消息(无 tool_calls)的 reasoning_content=None 不应被补填。"""
plain_assistant_msg = llmApiUtil.OpenAIMessage(
role=llmApiUtil.OpenaiApiRole.ASSISTANT,
content="I am a plain response",
reasoning_content=None,
tool_calls=None,
)
request = llmApiUtil.OpenAIRequest(
model="deepseek-v4-pro",
messages=[
llmApiUtil.OpenAIMessage.text(llmApiUtil.OpenaiApiRole.USER, "hello"),
plain_assistant_msg,
],
provider_params=THINKING_PARAMS,
)

next_request, applied_rules = apply_llm_request_rules(request)

assert "FillMissingReasoningContentRule" not in applied_rules
assistant_msgs = [m for m in next_request.messages if m.role == llmApiUtil.OpenaiApiRole.ASSISTANT]
assert assistant_msgs[0].reasoning_content is None


def test_fill_missing_reasoning_content_not_triggered_when_provider_params_empty():
"""provider_params 为空字典时不触发 FillMissingReasoningContentRule。"""
msg_no_rc = _make_assistant_tool_call_msg(reasoning_content=None)
request = llmApiUtil.OpenAIRequest(
model="deepseek-v4-pro",
messages=[
llmApiUtil.OpenAIMessage.text(llmApiUtil.OpenaiApiRole.USER, "hello"),
msg_no_rc,
],
provider_params={},
)

next_request, applied_rules = apply_llm_request_rules(request)

assert "FillMissingReasoningContentRule" not in applied_rules
assistant_msgs = [m for m in next_request.messages if m.role == llmApiUtil.OpenaiApiRole.ASSISTANT]
assert assistant_msgs[0].reasoning_content is None


def test_fill_missing_reasoning_content_not_triggered_when_thinking_is_string():
"""thinking 为非 dict 值(如字符串)时不触发规则。"""
msg_no_rc = _make_assistant_tool_call_msg(reasoning_content=None)
request = llmApiUtil.OpenAIRequest(
model="deepseek-v4-pro",
messages=[
llmApiUtil.OpenAIMessage.text(llmApiUtil.OpenaiApiRole.USER, "hello"),
msg_no_rc,
],
provider_params={"thinking": "enabled"},
)

next_request, applied_rules = apply_llm_request_rules(request)

assert "FillMissingReasoningContentRule" not in applied_rules


# ===== 两条规则同时触发的组合场景 =====


def test_both_rules_triggered_simultaneously():
"""reasoning_effort + tool_choice="required" + thinking enabled + 缺失 reasoning_content,
两条规则应同时触发。"""
msg_no_rc = _make_assistant_tool_call_msg(reasoning_content=None)
request = llmApiUtil.OpenAIRequest(
model="deepseek-v4-pro",
messages=[
llmApiUtil.OpenAIMessage.text(llmApiUtil.OpenaiApiRole.USER, "hello"),
msg_no_rc,
],
tool_choice="required",
provider_params={
"reasoning_effort": "high",
"thinking": {"type": "enabled"},
},
)

next_request, applied_rules = apply_llm_request_rules(request)

assert next_request.tool_choice is None
assert "StripRequiredToolChoiceForReasoningRule" in applied_rules
assert "FillMissingReasoningContentRule" in applied_rules
assistant_msgs = [m for m in next_request.messages if m.role == llmApiUtil.OpenaiApiRole.ASSISTANT]
assert assistant_msgs[0].reasoning_content == ""


def test_no_rules_triggered_when_no_conditions_match():
"""无任何规则匹配时,请求原样返回。"""
request = llmApiUtil.OpenAIRequest(
model="gpt-4o",
messages=[llmApiUtil.OpenAIMessage.text(llmApiUtil.OpenaiApiRole.USER, "hello")],
tool_choice="auto",
provider_params={},
)

next_request, applied_rules = apply_llm_request_rules(request)

assert next_request.tool_choice == "auto"
assert next_request.messages == request.messages
assert applied_rules == ()
Loading