Fix v32 continue_final_message not work (#16567)
This commit is contained in:
@@ -112,6 +112,62 @@ class OpenAIServingChat(OpenAIServingBase):
|
|||||||
|
|
||||||
self.use_dpsk_v32_encoding = self._use_dpsk_v32_encoding()
|
self.use_dpsk_v32_encoding = self._use_dpsk_v32_encoding()
|
||||||
|
|
||||||
|
def _handle_last_assistant_message(
|
||||||
|
self,
|
||||||
|
messages: List[Dict[str, Any]],
|
||||||
|
request: ChatCompletionRequest,
|
||||||
|
) -> tuple[List[Dict[str, Any]], Optional[str]]:
|
||||||
|
"""
|
||||||
|
Handle continue_final_message feature: separate final assistant message.
|
||||||
|
|
||||||
|
If continue_final_message is enabled and the last message is from assistant,
|
||||||
|
extract its content and remove it from the message list.
|
||||||
|
If continue_final_message is False and the last message is from assistant,
|
||||||
|
convert it to a user message to ensure the last message is always from user.
|
||||||
|
|
||||||
|
Only processes text-based content (strings), ignoring multimodal content (lists).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
messages: List of message dictionaries
|
||||||
|
request: ChatCompletionRequest with continue_final_message flag
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Tuple of (processed_messages, assistant_prefix)
|
||||||
|
- processed_messages: Messages with last assistant message handled appropriately
|
||||||
|
- assistant_prefix: Content of the last assistant message (string only), or None
|
||||||
|
"""
|
||||||
|
assistant_prefix = None
|
||||||
|
if messages and messages[-1].get("role") == "assistant":
|
||||||
|
last_content = messages[-1].get("content")
|
||||||
|
# Only process string content, ignore multimodal content (lists)
|
||||||
|
if isinstance(last_content, str):
|
||||||
|
if request.continue_final_message:
|
||||||
|
# Extract content and remove the assistant message
|
||||||
|
assistant_prefix = last_content
|
||||||
|
messages = messages[:-1]
|
||||||
|
else:
|
||||||
|
# Convert the last assistant message to user message
|
||||||
|
messages[-1] = {"role": "user", "content": last_content}
|
||||||
|
return messages, assistant_prefix
|
||||||
|
|
||||||
|
def _append_assistant_prefix_to_prompt_ids(
|
||||||
|
self, prompt_ids: List[int], assistant_prefix: str
|
||||||
|
) -> List[int]:
|
||||||
|
"""
|
||||||
|
Append assistant prefix to prompt_ids.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
prompt_ids: Current prompt token IDs
|
||||||
|
assistant_prefix: Assistant message content to append
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Updated prompt_ids with assistant prefix appended
|
||||||
|
"""
|
||||||
|
encoded = self.tokenizer_manager.tokenizer.encode(assistant_prefix)
|
||||||
|
if encoded and encoded[0] == self.tokenizer_manager.tokenizer.bos_token_id:
|
||||||
|
encoded = encoded[1:]
|
||||||
|
return prompt_ids + encoded
|
||||||
|
|
||||||
def _use_dpsk_v32_encoding(self) -> bool:
|
def _use_dpsk_v32_encoding(self) -> bool:
|
||||||
has_chat_template = (
|
has_chat_template = (
|
||||||
self.tokenizer_manager.tokenizer is not None
|
self.tokenizer_manager.tokenizer is not None
|
||||||
@@ -327,6 +383,11 @@ class OpenAIServingChat(OpenAIServingBase):
|
|||||||
messages = request.messages
|
messages = request.messages
|
||||||
messages = [msg.model_dump() for msg in messages]
|
messages = [msg.model_dump() for msg in messages]
|
||||||
|
|
||||||
|
# Handle continue_final_message: separate final assistant message
|
||||||
|
messages, assistant_prefix = self._handle_last_assistant_message(
|
||||||
|
messages, request
|
||||||
|
)
|
||||||
|
|
||||||
if messages[0]["role"] != "system":
|
if messages[0]["role"] != "system":
|
||||||
# insert an empty system prompt to help render tool system prompt
|
# insert an empty system prompt to help render tool system prompt
|
||||||
messages.insert(0, {"role": "system", "content": ""})
|
messages.insert(0, {"role": "system", "content": ""})
|
||||||
@@ -334,6 +395,12 @@ class OpenAIServingChat(OpenAIServingBase):
|
|||||||
messages[0]["tools"] = [tool.model_dump() for tool in request.tools]
|
messages[0]["tools"] = [tool.model_dump() for tool in request.tools]
|
||||||
real_input = encode_messages(messages, thinking_mode=thinking_mode)
|
real_input = encode_messages(messages, thinking_mode=thinking_mode)
|
||||||
prompt_ids = self.tokenizer_manager.tokenizer.encode(real_input)
|
prompt_ids = self.tokenizer_manager.tokenizer.encode(real_input)
|
||||||
|
|
||||||
|
# Append assistant prefix if continue_final_message is enabled
|
||||||
|
if assistant_prefix:
|
||||||
|
prompt_ids = self._append_assistant_prefix_to_prompt_ids(
|
||||||
|
prompt_ids, assistant_prefix
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
for message in request.messages:
|
for message in request.messages:
|
||||||
if message.content is None:
|
if message.content is None:
|
||||||
@@ -370,15 +437,10 @@ class OpenAIServingChat(OpenAIServingBase):
|
|||||||
|
|
||||||
openai_compatible_messages.append(processed_msg)
|
openai_compatible_messages.append(processed_msg)
|
||||||
|
|
||||||
# Handle assistant prefix for continue_final_message
|
# Handle continue_final_message: separate final assistant message
|
||||||
assistant_prefix = None
|
openai_compatible_messages, assistant_prefix = (
|
||||||
if (
|
self._handle_last_assistant_message(openai_compatible_messages, request)
|
||||||
openai_compatible_messages
|
)
|
||||||
and openai_compatible_messages[-1]["role"] == "assistant"
|
|
||||||
):
|
|
||||||
if request.continue_final_message:
|
|
||||||
assistant_prefix = openai_compatible_messages[-1]["content"]
|
|
||||||
openai_compatible_messages = openai_compatible_messages[:-1]
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
prompt_ids = self.tokenizer_manager.tokenizer.apply_chat_template(
|
prompt_ids = self.tokenizer_manager.tokenizer.apply_chat_template(
|
||||||
@@ -420,14 +482,11 @@ class OpenAIServingChat(OpenAIServingBase):
|
|||||||
# should be treated as client errors (400 BadRequest)
|
# should be treated as client errors (400 BadRequest)
|
||||||
raise ValueError(str(template_error)) from template_error
|
raise ValueError(str(template_error)) from template_error
|
||||||
|
|
||||||
|
# Append assistant prefix if continue_final_message is enabled
|
||||||
if assistant_prefix:
|
if assistant_prefix:
|
||||||
encoded = self.tokenizer_manager.tokenizer.encode(assistant_prefix)
|
prompt_ids = self._append_assistant_prefix_to_prompt_ids(
|
||||||
if (
|
prompt_ids, assistant_prefix
|
||||||
encoded
|
)
|
||||||
and encoded[0] == self.tokenizer_manager.tokenizer.bos_token_id
|
|
||||||
):
|
|
||||||
encoded = encoded[1:]
|
|
||||||
prompt_ids += encoded
|
|
||||||
|
|
||||||
if is_multimodal:
|
if is_multimodal:
|
||||||
prompt = self.tokenizer_manager.tokenizer.decode(prompt_ids)
|
prompt = self.tokenizer_manager.tokenizer.decode(prompt_ids)
|
||||||
|
|||||||
Reference in New Issue
Block a user