Skip to content

Commit fb76cdf

Browse files
ltd0924ltd0924Jiang-Jia-Jun
authored
[Fearture] Support mm model close prefix cache (#4459)
* [Feature] support prefix cache in DP * fix * Update common_engine.py * Update common_engine.py * Update common_engine.py * Update common_engine.py * [BugFix] fix workers more than 1 * fix * Update api_server.py * fix * Update api_server.py * fix * [Fearture] Support mm model close prefix cache * Update api_server.py * Update engine_client.py * Update engine_client.py * add test * Update test_chat.py * fix * fix * Update test_chat.py * Update test_chat.py --------- Co-authored-by: ltd0924 <luotingdan@baidu.com> Co-authored-by: Jiang-Jia-Jun <163579578+Jiang-Jia-Jun@users.noreply.github.com>
1 parent 2b53c4d commit fb76cdf

4 files changed

Lines changed: 47 additions & 4 deletions

File tree

fastdeploy/cache_manager/cache_data.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@
2121
logger = get_logger("prefix_cache_manager", "prefix_cache_manager.log")
2222

2323

24+
DISABLE_PREFIX_CACHE_MM_MODEL: set[str] = {
25+
"Ernie5ForCausalLM",
26+
}
27+
28+
29+
def is_mm_model_disable_prefix_cache(model_config):
30+
"""
31+
check if the model architecture is in DISABLE_PREFIX_CACHE_MM_MODEL
32+
"""
33+
return model_config._architecture in DISABLE_PREFIX_CACHE_MM_MODEL
34+
35+
2436
class CacheStatus(Enum):
2537
"""
2638
cache status enum class

fastdeploy/entrypoints/engine_client.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,13 @@ def __init__(
8686
self.enable_splitwise = splitwise_role != "mixed"
8787
max_chips_per_node = 16 if current_platform.is_iluvatar() else 8
8888

89+
if self.enable_mm and self.enable_prefix_caching:
90+
from fastdeploy.cache_manager.cache_data import (
91+
is_mm_model_disable_prefix_cache,
92+
)
93+
94+
self.disable_prefix_mm = is_mm_model_disable_prefix_cache(model_config)
95+
8996
if tensor_parallel_size <= max_chips_per_node:
9097
self.is_master = True
9198
else:
@@ -152,6 +159,16 @@ async def format_and_add_data(self, prompts: dict):
152159
await self.add_requests(prompts)
153160
return prompts["prompt_token_ids"]
154161

162+
def _check_mm_disable_prefix_cache(self, task):
163+
is_multimodal_data = False
164+
if self.disable_prefix_mm:
165+
multimodal_inputs = task.get("multimodal_inputs", [])
166+
if multimodal_inputs:
167+
token_type_ids = multimodal_inputs.get("token_type_ids", [])
168+
if token_type_ids:
169+
is_multimodal_data = np.sum(token_type_ids) > 0
170+
return is_multimodal_data
171+
155172
async def add_requests(self, task):
156173
"""
157174
Add a new request to the queue.
@@ -174,6 +191,16 @@ async def add_requests(self, task):
174191
else:
175192
self.data_processor.process_request_dict(task, self.max_model_len)
176193

194+
if self.enable_mm and self.enable_prefix_caching:
195+
if self._check_mm_disable_prefix_cache(task):
196+
api_server_logger.error(
197+
"The current service does not support processing requests containing multimodal data when prefix cache is enabled. Please send only text-based requests or disable prefix cache"
198+
)
199+
raise EngineError(
200+
"The current service does not support processing requests containing multimodal data when prefix cache is enabled. Please send only text-based requests or disable prefix cache",
201+
error_code=400,
202+
)
203+
177204
task["prompt_token_ids_len"] = len(task["prompt_token_ids"])
178205
input_ids_len = task["prompt_token_ids_len"]
179206
task["max_tokens"] = min(self.max_model_len - input_ids_len, task.get("max_tokens"))

fastdeploy/output/token_processor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ def _process_batch_output_use_zmq(self, receive_datas):
269269
if self.tokens_counter[task_id] == 0:
270270
if task.messages is not None:
271271
result.prompt = task.messages
272-
result.num_cached_tokens = task.num_cached_tokens
272+
result.num_cached_tokens = task.num_cached_tokens
273273

274274
is_prefill = task.disaggregate_info is not None and task.disaggregate_info["role"] == "prefill"
275275
result = self._process_per_token(task, i, token_ids, result, is_prefill)

tests/entrypoints/test_chat.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,13 @@
2727
class TestChat(unittest.TestCase):
2828
"""Test case for chat functionality"""
2929

30+
COMMON_PREFIX = "I am a highly capable, compassionate, and trustworthy AI assistant dedicated to providing you with exceptional support. Whatever questions or challenges you may have, I will utilize my full capabilities to offer thoughtful and comprehensive assistance. As your intelligent companion, I consistently maintain honesty, transparency, and patience to ensure our interactions are both productive and enjoyable."
31+
3032
PROMPTS = [
31-
[{"content": "The color of tomato is ", "role": "user"}],
32-
[{"content": "The equation 2+3= ", "role": "user"}],
33-
[{"content": "The equation 4-1= ", "role": "user"}],
3433
[{"content": "PaddlePaddle is ", "role": "user"}],
34+
[{"content": COMMON_PREFIX + "The color of tomato is ", "role": "user"}],
35+
[{"content": COMMON_PREFIX + "The equation 2+3= ", "role": "user"}],
36+
[{"content": COMMON_PREFIX + "The equation 4-1= ", "role": "user"}],
3537
]
3638

3739
@classmethod
@@ -58,6 +60,8 @@ def tearDownClass(cls):
5860
def test_chat(self):
5961
outputs = self.llm.chat(messages=self.PROMPTS, sampling_params=None)
6062
self.assertEqual(len(self.PROMPTS), len(outputs))
63+
self.assertEqual(outputs[-1].num_cached_tokens, outputs[-2].num_cached_tokens)
64+
self.assertEqual(outputs[-1].num_cached_tokens, 64)
6165

6266
def test_chat_with_tools(self):
6367
"""Test chat with tools:

0 commit comments

Comments
 (0)