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
7 changes: 3 additions & 4 deletions lmdeploy/deepseek_v4_encoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -584,14 +584,13 @@ def _drop_thinking_messages(messages: list[dict[str, Any]]) -> list[dict[str, An
message.

Behavior:
- Messages with role in ["user", "system", "tool", "latest_reminder"] are always kept.
- Messages with role in ["user", "system", "tool", "latest_reminder", "developer"] are always kept.
- Messages at or after the last user index are always kept.
- Assistant messages before the last user get reasoning_content removed.
- Developer messages before the last user are dropped entirely.
"""
last_user_idx = find_last_user_index(messages)
result = []
keep_roles = {'user', 'system', 'tool', 'latest_reminder', 'direct_search_results'}
keep_roles = {'user', 'system', 'tool', 'latest_reminder', 'direct_search_results', 'developer'}

for idx, msg in enumerate(messages):
role = msg.get('role')
Expand All @@ -601,7 +600,7 @@ def _drop_thinking_messages(messages: list[dict[str, Any]]) -> list[dict[str, An
msg = copy.copy(msg)
msg.pop('reasoning_content', None)
result.append(msg)
# developer and other roles before last_user_idx are dropped
# other unknown roles before last_user_idx are dropped

return result

Expand Down
33 changes: 33 additions & 0 deletions tests/test_lmdeploy/test_deepseek_v4_encoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,39 @@ def test_deepseek_v4_task_and_latest_reminder_rendering():
assert '<|Assistant|>' not in prompt


def test_deepseek_v4_thinking_drop_keeps_developer_message():
messages = [
{'role': 'system', 'content': 'You are helpful.'},
{'role': 'developer', 'content': 'Always answer in French.'},
{'role': 'user', 'content': 'Real question'},
]

prompt = encode_messages(messages, thinking_mode='thinking')

assert '<|User|>Always answer in French.' in prompt
assert '<|User|>Real question' in prompt
assert prompt.endswith('<|Assistant|><think>')


def test_deepseek_v4_thinking_drop_keeps_developer_in_multiturn():
messages = [
{'role': 'user', 'content': 'First question'},
{
'role': 'assistant',
'content': 'First answer',
'reasoning_content': 'private chain of thought',
},
{'role': 'developer', 'content': 'Now answer in French.'},
{'role': 'user', 'content': 'Second question'},
]

prompt = encode_messages(messages, thinking_mode='thinking')

assert '<|User|>Now answer in French.' in prompt
assert '<|User|>Second question' in prompt
assert 'private chain of thought' not in prompt


def test_deepseek_v4_parse_completion_text():
completion = (
'I should call a tool.</think>\n\n'
Expand Down