Open yinjiaoyuan opened 10 months ago
I use the below code to save model: from transformers import AutoModelForCausalLM, AutoTokenizer from transformers.generation import GenerationConfig
model_dir = '/data/model/Qwen-14B-Chat-hf-save'
name = 'Qwen/Qwen-14B-Chat' tokenizer = AutoTokenizer.from_pretrained(name, trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained(name, device_map="auto", trust_remote_code=True, bf16=True).eval() tokenizer.save_pretrained(model_dir) model.save_pretrained(model_dir)
And run: docker run --gpus all --shm-size 1g -p 8080:80 -v /data/model/:/data/ \ ghcr.io/predibase/lorax:latest --model-id /data/Qwen-14B-Chat-hf-save
The error is: 2023-12-26T02:25:38.134822Z INFO lorax_launcher: Args { model_id: "/data/Qwen-14B-Chat-hf-save", adapter_id: "", source: "hub", adapter_source: "hub", revision: None, validation_workers: 2, sharded: None, num_shard: None, quantize: None, dtype: None, trust_remote_code: false, max_concurrent_requests: 128, max_best_of: 2, max_stop_sequences: 4, max_input_length: 1024, max_total_tokens: 2048, waiting_served_ratio: 1.2, max_batch_prefill_tokens: 4096, max_batch_total_tokens: None, max_waiting_tokens: 20, max_active_adapters: 128, adapter_cycle_time_s: 2, hostname: "dd28579e51fc", port: 80, shard_uds_path: "/tmp/lorax-server", master_addr: "localhost", master_port: 29500, huggingface_hub_cache: Some("/data"), weights_cache_override: None, disable_custom_kernels: false, cuda_memory_fraction: 1.0, json_output: false, otlp_endpoint: None, cors_allow_origin: [], watermark_gamma: None, watermark_delta: None, ngrok: false, ngrok_authtoken: None, ngrok_edge: None, env: false, download_only: false } 2023-12-26T02:25:38.134920Z INFO download: lorax_launcher: Starting download process. 2023-12-26T02:25:41.114273Z INFO lorax_launcher: cli.py:103 Files are already present on the host. Skipping download.
2023-12-26T02:25:41.537340Z INFO download: lorax_launcher: Successfully downloaded weights.
2023-12-26T02:25:41.537502Z INFO shard-manager: lorax_launcher: Starting shard rank=0
2023-12-26T02:25:44.896833Z ERROR lorax_launcher: server.py:233 Error when initializing model
Traceback (most recent call last):
File "/opt/conda/bin/lorax-server", line 8, in
File "/opt/conda/lib/python3.10/site-packages/lorax_server/server.py", line 229, in serve_inner model = get_model( File "/opt/conda/lib/python3.10/site-packages/lorax_server/models/init.py", line 321, in get_model return FlashQwen( File "/opt/conda/lib/python3.10/site-packages/lorax_server/models/flash_qwen.py", line 54, in init tokenizer = AutoTokenizer.from_pretrained( File "/opt/conda/lib/python3.10/site-packages/transformers/models/auto/tokenization_auto.py", line 784, in from_pretrained raise ValueError( ValueError: Tokenizer class QWenTokenizer does not exist or is not currently imported.
2023-12-26T02:25:45.540361Z ERROR shard-manager: lorax_launcher: Shard complete standard error output:
Traceback (most recent call last):
File "/opt/conda/bin/lorax-server", line 8, in
File "/opt/conda/lib/python3.10/site-packages/lorax_server/cli.py", line 84, in serve server.serve(
File "/opt/conda/lib/python3.10/site-packages/lorax_server/server.py", line 277, in serve asyncio.run(
File "/opt/conda/lib/python3.10/asyncio/runners.py", line 44, in run return loop.run_until_complete(main)
File "/opt/conda/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete return future.result()
File "/opt/conda/lib/python3.10/site-packages/lorax_server/server.py", line 229, in serve_inner model = get_model(
File "/opt/conda/lib/python3.10/site-packages/lorax_server/models/init.py", line 321, in get_model return FlashQwen(
File "/opt/conda/lib/python3.10/site-packages/lorax_server/models/flash_qwen.py", line 54, in init tokenizer = AutoTokenizer.from_pretrained(
File "/opt/conda/lib/python3.10/site-packages/transformers/models/auto/tokenization_auto.py", line 784, in from_pretrained raise ValueError(
ValueError: Tokenizer class QWenTokenizer does not exist or is not currently imported. rank=0 2023-12-26T02:25:45.639763Z ERROR lorax_launcher: Shard 0 failed to start 2023-12-26T02:25:45.639783Z INFO lorax_launcher: Shutting down shards Error: ShardCannotStart
The dir /data/model/Qwen-14B-Chat-hf-save: total 27673116 drwxr-xr-x 2 root root 4096 Dec 25 19:14 ./ drwxr-xr-x 3 root root 4096 Dec 26 10:25 ../ -rw-r--r-- 1 root root 1110 Dec 25 19:13 config.json -rw-r--r-- 1 root root 250 Dec 25 19:13 generation_config.json -rw-r--r-- 1 root root 4919444336 Dec 25 19:13 model-00001-of-00006.safetensors -rw-r--r-- 1 root root 4991627864 Dec 25 19:13 model-00002-of-00006.safetensors -rw-r--r-- 1 root root 4886749824 Dec 25 19:13 model-00003-of-00006.safetensors -rw-r--r-- 1 root root 4903809664 Dec 25 19:14 model-00004-of-00006.safetensors -rw-r--r-- 1 root root 4903820016 Dec 25 19:14 model-00005-of-00006.safetensors -rw-r--r-- 1 root root 3729165312 Dec 25 19:14 model-00006-of-00006.safetensors -rw-r--r-- 1 root root 24387 Dec 25 19:14 model.safetensors.index.json -rw-r--r-- 1 root root 2561218 Dec 25 19:13 qwen.tiktoken -rw-r--r-- 1 root root 3 Dec 25 19:13 special_tokens_map.json -rw-r--r-- 1 root root 261 Dec 25 19:13 tokenizer_config.json
Or support model from www.modelscope.cn like vllm?
Hey @yinjiaoyuan, apologies for the delayed response, I've been out on holiday this week.
To answer your first question, it looks like the current issue you're seeing is due to the model using a third party tokenizer (not natively part of HF):
ValueError: Tokenizer class QWenTokenizer does not exist or is not currently imported.
You can resolve this issue by running LoRAX with --trust-remote-code
so it downloads the tokenizer from the model repo.
Let me know if that resolves your issue.
I'd be happy to add support for ModelScope, though I would need to explore it to understand the API a bit better (sounds like vllm would be a good reference for that). Contributions also welcome if you'd be interested in adding it.
But my linux server can't visit the site "https://huggingface.co/" in China.
Hey @yinjiaoyuan, you should be able to save the HF tokenizer to the same directory you saved the model weights to, which will allow LoRAX to read from the cache instead of going over the internet. For example, here are the contents of my local directory cache:
ls /data/models--Qwen--Qwen-7B/snapshots/ffe04dd57f85293043ba999a2c0daa788d6182e9/
config.json model-00003-of-00008.safetensors model-00006-of-00008.safetensors qwen.tiktoken
model-00001-of-00008.safetensors model-00004-of-00008.safetensors model-00007-of-00008.safetensors tokenization_qwen.py
model-00002-of-00008.safetensors model-00005-of-00008.safetensors model-00008-of-00008.safetensors tokenizer_config.json
You can see there's a file called tokenization_qwen.py
that contains the tokenizer implementation. If you can write out this file locally, you should be able to avoid hitting the HF servers.
Hey @yinjiaoyuan, you should be able to save the HF tokenizer to the same directory you saved the model weights to, which will allow LoRAX to read from the cache instead of going over the internet. For example, here are the contents of my local directory cache:
ls /data/models--Qwen--Qwen-7B/snapshots/ffe04dd57f85293043ba999a2c0daa788d6182e9/ config.json model-00003-of-00008.safetensors model-00006-of-00008.safetensors qwen.tiktoken model-00001-of-00008.safetensors model-00004-of-00008.safetensors model-00007-of-00008.safetensors tokenization_qwen.py model-00002-of-00008.safetensors model-00005-of-00008.safetensors model-00008-of-00008.safetensors tokenizer_config.json
You can see there's a file called
tokenization_qwen.py
that contains the tokenizer implementation. If you can write out this file locally, you should be able to avoid hitting the HF servers.
Yes, I dowload the hf model on the foreign host and scp the model files to the host in the China, but I run lorax and input --model-id /xxx/yyy/data/models--Qwen--Qwen-7B-Chat/snapshots/218aa3240fd5a5d1e80bb6c47d5d774361913706/, /data/models--Qwen--Qwen-7B-Chat/snapshots/218aa3240fd5a5d1e80bb6c47d5d774361913706/ is the dir of the model fies, but NOT ok, the error info is: 2024-01-08T03:11:04.139756Z INFO lorax_launcher: Args { model_id: "/data/models--Qwen--Qwen-7B-Chat/snapshots/218aa3240fd5a5d1e80bb6c47d5d774361913706/", adapter_id: "", source: "hub", adapter_source: "hub", revision: None, validation_workers: 2, sharded: None, num_shard: None, quantize: None, dtype: None, trust_remote_code: false, max_concurrent_requests: 128, max_best_of: 2, max_stop_sequences: 4, max_input_length: 1024, max_total_tokens: 2048, waiting_served_ratio: 1.2, max_batch_prefill_tokens: 4096, max_batch_total_tokens: None, max_waiting_tokens: 20, max_active_adapters: 128, adapter_cycle_time_s: 2, hostname: "f06b11000cff", port: 80, shard_uds_path: "/tmp/lorax-server", master_addr: "localhost", master_port: 29500, huggingface_hub_cache: Some("/data"), weights_cache_override: None, disable_custom_kernels: false, cuda_memory_fraction: 1.0, json_output: false, otlp_endpoint: None, cors_allow_origin: [], watermark_gamma: None, watermark_delta: None, ngrok: false, ngrok_authtoken: None, ngrok_edge: None, env: false, download_only: false } 2024-01-08T03:11:04.139862Z INFO download: lorax_launcher: Starting download process. 2024-01-08T03:11:07.000076Z INFO lorax_launcher: cli.py:103 Files are already present on the host. Skipping download.
2024-01-08T03:11:07.442269Z INFO download: lorax_launcher: Successfully downloaded weights.
2024-01-08T03:11:07.442447Z INFO shard-manager: lorax_launcher: Starting shard rank=0
2024-01-08T03:11:11.104509Z ERROR lorax_launcher: server.py:233 Error when initializing model
Traceback (most recent call last):
File "/opt/conda/bin/lorax-server", line 8, in
File "/opt/conda/lib/python3.10/site-packages/lorax_server/server.py", line 229, in serve_inner model = get_model( File "/opt/conda/lib/python3.10/site-packages/lorax_server/models/init.py", line 321, in get_model return FlashQwen( File "/opt/conda/lib/python3.10/site-packages/lorax_server/models/flash_qwen.py", line 54, in init tokenizer = AutoTokenizer.from_pretrained( File "/opt/conda/lib/python3.10/site-packages/transformers/models/auto/tokenization_auto.py", line 784, in from_pretrained raise ValueError( ValueError: Tokenizer class QWenTokenizer does not exist or is not currently imported.
2024-01-08T03:11:11.645631Z ERROR shard-manager: lorax_launcher: Shard complete standard error output:
Traceback (most recent call last):
File "/opt/conda/bin/lorax-server", line 8, in
File "/opt/conda/lib/python3.10/site-packages/lorax_server/cli.py", line 84, in serve server.serve(
File "/opt/conda/lib/python3.10/site-packages/lorax_server/server.py", line 277, in serve asyncio.run(
File "/opt/conda/lib/python3.10/asyncio/runners.py", line 44, in run return loop.run_until_complete(main)
File "/opt/conda/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete return future.result()
File "/opt/conda/lib/python3.10/site-packages/lorax_server/server.py", line 229, in serve_inner model = get_model(
File "/opt/conda/lib/python3.10/site-packages/lorax_server/models/init.py", line 321, in get_model return FlashQwen(
File "/opt/conda/lib/python3.10/site-packages/lorax_server/models/flash_qwen.py", line 54, in init tokenizer = AutoTokenizer.from_pretrained(
File "/opt/conda/lib/python3.10/site-packages/transformers/models/auto/tokenization_auto.py", line 784, in from_pretrained raise ValueError(
ValueError: Tokenizer class QWenTokenizer does not exist or is not currently imported. rank=0 2024-01-08T03:11:11.745313Z ERROR lorax_launcher: Shard 0 failed to start 2024-01-08T03:11:11.745333Z INFO lorax_launcher: Shutting down shards Error: ShardCannotStart
Hey @yinjiaoyuan, sorry about the back and forth. That definitely looks like a bug, then. We should be able to obtain the local tokenizer without going to HF. I'll see if I can repro the error.
Can you run ls /data/models--Qwen--Qwen-7B-Chat/snapshots/218aa3240fd5a5d1e80bb6c47d5d774361913706/
and paste the results here to confirm that tokenization_qwen.py
is in the directory?
Hey @yinjiaoyuan, sorry about the back and forth. That definitely looks like a bug, then. We should be able to obtain the local tokenizer without going to HF. I'll see if I can repro the error.
Can you run
ls /data/models--Qwen--Qwen-7B-Chat/snapshots/218aa3240fd5a5d1e80bb6c47d5d774361913706/
and paste the results here to confirm thattokenization_qwen.py
is in the directory?
ls /data/models--Qwen--Qwen-7B-Chat/snapshots/218aa3240fd5a5d1e80bb6c47d5d774361913706/: total 15083436 drwxr-xr-x 2 root root 4096 Jan 3 11:05 ./ drwxr-xr-x 3 root root 4096 Jan 3 10:40 ../ -rw-r--r-- 1 root root 911 Jan 3 10:40 config.json -rw-r--r-- 1 root root 2345 Jan 3 10:40 configuration_qwen.py -rw-r--r-- 1 root root 1924 Jan 3 10:40 cpp_kernels.py -rw-r--r-- 1 root root 273 Jan 3 11:05 generation_config.json -rw-r--r-- 1 root root 1964066488 Jan 3 10:43 model-00001-of-00008.safetensors -rw-r--r-- 1 root root 2023960808 Jan 3 10:47 model-00002-of-00008.safetensors -rw-r--r-- 1 root root 2023960816 Jan 3 10:51 model-00003-of-00008.safetensors -rw-r--r-- 1 root root 2023960848 Jan 3 10:54 model-00004-of-00008.safetensors -rw-r--r-- 1 root root 2023960848 Jan 3 10:57 model-00005-of-00008.safetensors -rw-r--r-- 1 root root 2023960848 Jan 3 11:00 model-00006-of-00008.safetensors -rw-r--r-- 1 root root 2023960848 Jan 3 11:03 model-00007-of-00008.safetensors -rw-r--r-- 1 root root 1334845784 Jan 3 11:05 model-00008-of-00008.safetensors -rw-r--r-- 1 root root 55563 Jan 3 10:40 modeling_qwen.py -rw-r--r-- 1 root root 19547 Jan 3 10:40 model.safetensors.index.json -rw-r--r-- 1 root root 14604 Jan 3 10:40 qwen_generation_utils.py -rw-r--r-- 1 root root 2561218 Jan 3 10:40 qwen.tiktoken -rw-r--r-- 1 root root 9618 Jan 3 10:40 tokenization_qwen.py -rw-r--r-- 1 root root 174 Jan 3 10:40 tokenizer_config.json
And cat /data/models--Qwen--Qwen-7B-Chat/snapshots/218aa3240fd5a5d1e80bb6c47d5d774361913706/tokenization_qwen.py:
#
"""Tokenization classes for QWen."""
import base64 import logging import os import unicodedata from typing import Collection, Dict, List, Set, Tuple, Union
import tiktoken from transformers import PreTrainedTokenizer, AddedToken
logger = logging.getLogger(name)
VOCAB_FILES_NAMES = {"vocab_file": "qwen.tiktoken"}
PAT_STR = r"""(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\r\n\p{L}\p{N}]?\p{L}+|\p{N}| ?[^\s\p{L}\p{N}]+[\r\n]|\s[\r\n]+|\s+(?!\S)|\s+""" ENDOFTEXT = "<|endoftext|>" IMSTART = "<|im_start|>" IMEND = "<|im_end|>"
EXTRAS = tuple((f"<|extra_{i}|>" for i in range(205)))
SPECIAL_START_ID = 151643 SPECIAL_TOKENS = tuple( enumerate( ( ( ENDOFTEXT, IMSTART, IMEND, )
def _load_tiktoken_bpe(tiktoken_bpe_file: str) -> Dict[bytes, int]: with open(tiktoken_bpe_file, "rb") as f: contents = f.read() return { base64.b64decode(token): int(rank) for token, rank in (line.split() for line in contents.splitlines() if line) }
class QWenTokenizer(PreTrainedTokenizer): """QWen tokenizer."""
vocab_files_names = VOCAB_FILES_NAMES
def __init__(
self,
vocab_file,
errors="replace",
extra_vocab_file=None,
**kwargs,
):
super().__init__(**kwargs)
# how to handle errors in decoding UTF-8 byte sequences
# use ignore if you are in streaming inference
self.errors = errors
self.mergeable_ranks = _load_tiktoken_bpe(vocab_file) # type: Dict[bytes, int]
self.special_tokens = {
token: index
for index, token in SPECIAL_TOKENS
}
# try load extra vocab from file
if extra_vocab_file is not None:
used_ids = set(self.mergeable_ranks.values()) | set(self.special_tokens.values())
extra_mergeable_ranks = _load_tiktoken_bpe(extra_vocab_file)
for token, index in extra_mergeable_ranks.items():
if token in self.mergeable_ranks:
logger.info(f"extra token {token} exists, skipping")
continue
if index in used_ids:
logger.info(f'the index {index} for extra token {token} exists, skipping')
continue
self.mergeable_ranks[token] = index
# the index may be sparse after this, but don't worry tiktoken.Encoding will handle this
enc = tiktoken.Encoding(
"Qwen",
pat_str=PAT_STR,
mergeable_ranks=self.mergeable_ranks,
special_tokens=self.special_tokens,
)
assert (
len(self.mergeable_ranks) + len(self.special_tokens) == enc.n_vocab
), f"{len(self.mergeable_ranks) + len(self.special_tokens)} != {enc.n_vocab} in encoding"
self.decoder = {
v: k for k, v in self.mergeable_ranks.items()
} # type: dict[int, bytes|str]
self.decoder.update({v: k for k, v in self.special_tokens.items()})
self.tokenizer = enc # type: tiktoken.Encoding
self.eod_id = self.tokenizer.eot_token
self.im_start_id = self.special_tokens[IMSTART]
self.im_end_id = self.special_tokens[IMEND]
def __getstate__(self):
# for pickle lovers
state = self.__dict__.copy()
del state["tokenizer"]
return state
def __setstate__(self, state):
# tokenizer is not python native; don't pass it; rebuild it
self.__dict__.update(state)
enc = tiktoken.Encoding(
"Qwen",
pat_str=PAT_STR,
mergeable_ranks=self.mergeable_ranks,
special_tokens=self.special_tokens,
)
self.tokenizer = enc
def __len__(self) -> int:
return self.tokenizer.n_vocab
def get_vocab(self) -> Dict[bytes, int]:
return self.mergeable_ranks
def convert_tokens_to_ids(
self, tokens: Union[bytes, str, List[Union[bytes, str]]]
) -> List[int]:
ids = []
if isinstance(tokens, (str, bytes)):
if tokens in self.special_tokens:
return self.special_tokens[tokens]
else:
return self.mergeable_ranks.get(tokens)
for token in tokens:
if token in self.special_tokens:
ids.append(self.special_tokens[token])
else:
ids.append(self.mergeable_ranks.get(token))
return ids
def _add_tokens(
self,
new_tokens: Union[List[str], List[AddedToken]],
special_tokens: bool = False,
) -> int:
if not special_tokens and new_tokens:
raise ValueError("Adding regular tokens is not supported")
for token in new_tokens:
surface_form = token.content if isinstance(token, AddedToken) else token
if surface_form not in SPECIAL_TOKENS_SET:
raise ValueError("Adding unknown special tokens is not supported")
return 0
def save_vocabulary(self, save_directory: str, **kwargs) -> Tuple[str]:
"""
Save only the vocabulary of the tokenizer (vocabulary).
Returns:
`Tuple(str)`: Paths to the files saved.
"""
file_path = os.path.join(save_directory, "qwen.tiktoken")
with open(file_path, "w", encoding="utf8") as w:
for k, v in self.mergeable_ranks.items():
line = base64.b64encode(k).decode("utf8") + " " + str(v) + "\n"
w.write(line)
return (file_path,)
def tokenize(
self,
text: str,
allowed_special: Union[Set, str] = "all",
disallowed_special: Union[Collection, str] = (),
**kwargs,
) -> List[Union[bytes, str]]:
"""
Converts a string in a sequence of tokens.
Args:
text (`str`):
The sequence to be encoded.
allowed_special (`Literal["all"]` or `set`):
The surface forms of the tokens to be encoded as special tokens in regular texts.
Default to "all".
disallowed_special (`Literal["all"]` or `Collection`):
The surface forms of the tokens that should not be in regular texts and trigger errors.
Default to an empty tuple.
kwargs (additional keyword arguments, *optional*):
Will be passed to the underlying model specific encode method.
Returns:
`List[bytes|str]`: The list of tokens.
"""
tokens = []
text = unicodedata.normalize("NFC", text)
# this implementation takes a detour: text -> token id -> token surface forms
for t in self.tokenizer.encode(
text, allowed_special=allowed_special, disallowed_special=disallowed_special
):
tokens.append(self.decoder[t])
return tokens
def convert_tokens_to_string(self, tokens: List[Union[bytes, str]]) -> str:
"""
Converts a sequence of tokens in a single string.
"""
text = ""
temp = b""
for t in tokens:
if isinstance(t, str):
if temp:
text += temp.decode("utf-8", errors=self.errors)
temp = b""
text += t
elif isinstance(t, bytes):
temp += t
else:
raise TypeError("token should only be of type types or str")
if temp:
text += temp.decode("utf-8", errors=self.errors)
return text
@property
def vocab_size(self):
return self.tokenizer.n_vocab
def _convert_id_to_token(self, index: int) -> Union[bytes, str]:
"""Converts an id to a token, special tokens included"""
if index in self.decoder:
return self.decoder[index]
raise ValueError("unknown ids")
def _convert_token_to_id(self, token: Union[bytes, str]) -> int:
"""Converts a token to an id using the vocab, special tokens included"""
if token in self.special_tokens:
return self.special_tokens[token]
if token in self.mergeable_ranks:
return self.mergeable_ranks[token]
raise ValueError("unknown token")
def _tokenize(self, text: str, **kwargs):
"""
Converts a string in a sequence of tokens (string), using the tokenizer. Split in words for word-based
vocabulary or sub-words for sub-word-based vocabularies (BPE/SentencePieces/WordPieces).
Do NOT take care of added tokens.
"""
raise NotImplementedError
def _decode(
self,
token_ids: Union[int, List[int]],
skip_special_tokens: bool = False,
errors: str = None,
**kwargs,
) -> str:
if isinstance(token_ids, int):
token_ids = [token_ids]
if skip_special_tokens:
token_ids = [i for i in token_ids if i < self.eod_id]
return self.tokenizer.decode(token_ids, errors=errors or self.errors)
Feature request
I have download the model, so I want to run it use local model, eht sample is: docker run --gpus all --shm-size 1g -p 8080:80 -v /data/model/:/data/ \ ghcr.io/predibase/lorax:latest --model-id /data/model/Qwen-14B-Chat
Motivation
I want to use the local model. Our computes don't allow to visit huggingface.co.
Your contribution
No.