Repository: vllm-project/vllm

Issue:
Bug in LLaMA fast tokenizer
In my environment, using the LLaMA fast tokenizer raises an error about protobuf:
```
  File "/opt/conda/envs/dev/lib/python3.9/site-packages/transformers/convert_slow_tokenizer.py", line 445, in __init__
    from .utils import sentencepiece_model_pb2 as model_pb2
  File "/opt/conda/envs/dev/lib/python3.9/site-packages/transformers/utils/sentencepiece_model_pb2.py", line 91, in <module>
    _descriptor.EnumValueDescriptor(
  File "/opt/conda/envs/dev/lib/python3.9/site-packages/google/protobuf/descriptor.py", line 796, in __new__
    _message.Message._CheckCalledFromGeneratedFile()
TypeError: Descriptors cannot not be created directly.
If this call came from a _pb2.py file, your generated code is out of date and must be regenerated with protoc >= 3.19.0.
If you cannot immediately regenerate your protos, some other possible workarounds are:
 1. Downgrade the protobuf package to 3.20.x or lower.
 2. Set PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python (but this will use pure-Python parsing and will be much slower).
```

While downgrading the protobuf version removed the error, it slowed down the initialization time by ~8x.
* Initialization with fast tokenizer & protobuf==3.20.3 
```
real    4m18.476s
user    3m52.706s
sys     0m27.644s
```
* Initialization with slow tokenizer
```
real    0m27.620s
user    0m8.011s
sys     0m19.237s
```



Discussion:

Resolving patch:
diff --git a/cacheflow/frontend/fastapi_frontend.py b/cacheflow/frontend/fastapi_frontend.py
--- a/cacheflow/frontend/fastapi_frontend.py
+++ b/cacheflow/frontend/fastapi_frontend.py
@@ -7,12 +7,12 @@
 from fastapi import FastAPI, Request
 from fastapi.responses import StreamingResponse
 import ray
-from transformers import AutoTokenizer
 import uvicorn
 
 from cacheflow.core.server import (Server, add_server_arguments,
                                    process_server_arguments,
                                    initialize_cluster)
+from cacheflow.frontend.utils import get_tokenizer
 from cacheflow.sampling_params import SamplingParams
 from cacheflow.sequence import Sequence, SequenceGroup
 from cacheflow.utils import Counter, get_gpu_memory, get_cpu_memory
@@ -44,7 +44,7 @@ def __init__(
     ):
         self.block_size = block_size
 
-        self.tokenizer = AutoTokenizer.from_pretrained(model)
+        self.tokenizer = get_tokenizer(model)
         self.seq_group_counter = Counter()
         self.seq_counter = Counter()
         if server_use_ray:
diff --git a/cacheflow/frontend/simple_frontend.py b/cacheflow/frontend/simple_frontend.py
--- a/cacheflow/frontend/simple_frontend.py
+++ b/cacheflow/frontend/simple_frontend.py
@@ -1,8 +1,7 @@
 import time
 from typing import List, Optional, Tuple
 
-from transformers import AutoTokenizer
-
+from cacheflow.frontend.utils import get_tokenizer
 from cacheflow.logger import init_logger
 from cacheflow.sampling_params import SamplingParams
 from cacheflow.sequence import Sequence, SequenceGroup
@@ -21,7 +20,7 @@ def __init__(
     ) -> None:
         self.block_size = block_size
 
-        self.tokenizer = AutoTokenizer.from_pretrained(model_name)
+        self.tokenizer = get_tokenizer(model_name)
         self.seq_group_counter = Counter()
         self.seq_counter = Counter()
         self.inputs: List[Tuple[SequenceGroup, SamplingParams]] = []
diff --git a/cacheflow/frontend/utils.py b/cacheflow/frontend/utils.py
new file mode 100644
--- /dev/null
+++ b/cacheflow/frontend/utils.py
@@ -0,0 +1,22 @@
+from typing import Union
+
+from transformers import (AutoConfig, AutoTokenizer, PreTrainedTokenizer,
+                          PreTrainedTokenizerFast)
+
+
+_MODEL_TYPES_WITH_SLOW_TOKENIZER = [
+    # LLaMA fast tokenizer has a bug related to protobuf.
+    # See https://github.com/WoosukKwon/cacheflow/issues/80#issue-1698550554
+    "llama",
+]
+
+
+def get_tokenizer(
+    model_name: str,
+    *args,
+    **kwargs,
+) -> Union[PreTrainedTokenizer, PreTrainedTokenizerFast]:
+    config = AutoConfig.from_pretrained(model_name)
+    if config.model_type in _MODEL_TYPES_WITH_SLOW_TOKENIZER:
+        kwargs["use_fast"] = False
+    return AutoTokenizer.from_pretrained(model_name, *args, **kwargs)


Test patch: