Text Generation
Transformers
Safetensors
English
qwen3
dna
genomics
biology
variant-effect-prediction
conversational
text-generation-inference
Instructions to use HuggingFaceBio/Carbon-X with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use HuggingFaceBio/Carbon-X with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="HuggingFaceBio/Carbon-X") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("HuggingFaceBio/Carbon-X") model = AutoModelForCausalLM.from_pretrained("HuggingFaceBio/Carbon-X", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=256) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use HuggingFaceBio/Carbon-X with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "HuggingFaceBio/Carbon-X" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "HuggingFaceBio/Carbon-X", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/HuggingFaceBio/Carbon-X
- SGLang
How to use HuggingFaceBio/Carbon-X with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "HuggingFaceBio/Carbon-X" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "HuggingFaceBio/Carbon-X", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "HuggingFaceBio/Carbon-X" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "HuggingFaceBio/Carbon-X", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use HuggingFaceBio/Carbon-X with Docker Model Runner:
docker model run hf.co/HuggingFaceBio/Carbon-X
Fix tokenizer persistence using merged source implementation
#7
by edbeeching HF Staff - opened
- tokenizer.py +44 -97
tokenizer.py
CHANGED
|
@@ -80,20 +80,28 @@ class HybridDNATokenizer(PreTrainedTokenizer):
|
|
| 80 |
self._build_combined_vocab()
|
| 81 |
|
| 82 |
# Set special tokens
|
| 83 |
-
self._eos_token = kwargs.pop(
|
| 84 |
-
self._pad_token = kwargs.pop(
|
| 85 |
|
| 86 |
# Initialize parent class
|
| 87 |
super().__init__(
|
| 88 |
eos_token=self._eos_token,
|
| 89 |
pad_token=self._pad_token,
|
|
|
|
|
|
|
|
|
|
| 90 |
**kwargs
|
| 91 |
)
|
| 92 |
|
| 93 |
# Preserve the base tokenizer's AddedToken metadata. These tokens are
|
| 94 |
# already present in the combined vocabulary at their original IDs, so
|
| 95 |
# this only registers their metadata and does not grow the vocabulary.
|
| 96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
|
| 98 |
self.special_tokens = self.dna_special_tokens + [self._eos_token, self._pad_token]
|
| 99 |
self.auto_dna_tags = auto_dna_tags
|
|
@@ -711,14 +719,21 @@ class HybridDNATokenizer(PreTrainedTokenizer):
|
|
| 711 |
|
| 712 |
return (vocab_file,)
|
| 713 |
|
| 714 |
-
def
|
| 715 |
-
|
| 716 |
-
|
| 717 |
-
|
| 718 |
-
|
| 719 |
-
|
| 720 |
-
|
| 721 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 722 |
dna_config = {
|
| 723 |
"k": self.k,
|
| 724 |
"dna_start_id": self.dna_start_id,
|
|
@@ -727,103 +742,31 @@ class HybridDNATokenizer(PreTrainedTokenizer):
|
|
| 727 |
"auto_dna_tags": self.auto_dna_tags,
|
| 728 |
"tail": self.tail,
|
| 729 |
}
|
| 730 |
-
|
| 731 |
dna_config_path = os.path.join(save_directory, "dna_config.json")
|
| 732 |
with open(dna_config_path, "w", encoding="utf-8") as f:
|
| 733 |
json.dump(dna_config, f, indent=2)
|
| 734 |
-
|
| 735 |
-
# Update tokenizer_config.json with auto_map
|
| 736 |
-
config_path = os.path.join(save_directory, "tokenizer_config.json")
|
| 737 |
-
|
| 738 |
-
if os.path.exists(config_path):
|
| 739 |
-
with open(config_path, "r") as f:
|
| 740 |
-
config = json.load(f)
|
| 741 |
-
else:
|
| 742 |
-
config = {}
|
| 743 |
-
|
| 744 |
-
config.update({
|
| 745 |
-
"tokenizer_class": "HybridDNATokenizer",
|
| 746 |
-
"auto_map": {
|
| 747 |
-
"AutoTokenizer": ["tokenizer.HybridDNATokenizer", None]
|
| 748 |
-
},
|
| 749 |
-
"k": self.k,
|
| 750 |
-
"auto_dna_tags": self.auto_dna_tags,
|
| 751 |
-
"tail": self.tail,
|
| 752 |
-
})
|
| 753 |
-
|
| 754 |
-
with open(config_path, "w", encoding="utf-8") as f:
|
| 755 |
-
json.dump(config, f, indent=2, ensure_ascii=False)
|
| 756 |
-
|
| 757 |
-
# Copy this tokenizer.py to save directory
|
| 758 |
-
import shutil
|
| 759 |
-
src_py = os.path.abspath(__file__)
|
| 760 |
-
dst_py = os.path.join(save_directory, "tokenizer.py")
|
| 761 |
-
if os.path.exists(src_py) and src_py != dst_py:
|
| 762 |
-
shutil.copy2(src_py, dst_py)
|
| 763 |
-
|
| 764 |
-
return (save_directory,)
|
| 765 |
|
| 766 |
@classmethod
|
| 767 |
-
def from_pretrained(
|
| 768 |
-
|
| 769 |
-
|
| 770 |
-
*args,
|
| 771 |
-
cache_dir=None,
|
| 772 |
-
force_download=False,
|
| 773 |
-
local_files_only=False,
|
| 774 |
-
token=None,
|
| 775 |
-
revision="main",
|
| 776 |
-
trust_remote_code=False,
|
| 777 |
-
**kwargs,
|
| 778 |
-
):
|
| 779 |
-
# Custom loader: PreTrainedTokenizer.from_pretrained is incompatible with this
|
| 780 |
-
# tokenizer's __init__ (it re-passes bos_token etc.), so construct directly from
|
| 781 |
-
# bio_config/dna_config. That bypasses standard metadata loading, so also read
|
| 782 |
-
# chat_template from tokenizer_config.json (vLLM / apply_chat_template need it).
|
| 783 |
from transformers.utils.hub import cached_file
|
| 784 |
|
| 785 |
-
proxies = kwargs.pop("proxies", None)
|
| 786 |
-
subfolder = kwargs.pop("subfolder", None)
|
| 787 |
-
commit_hash = kwargs.pop("_commit_hash", None)
|
| 788 |
hub_kwargs = {
|
| 789 |
-
|
| 790 |
-
"
|
| 791 |
-
|
| 792 |
-
"proxies": proxies,
|
| 793 |
-
"revision": revision,
|
| 794 |
-
"subfolder": subfolder,
|
| 795 |
-
"token": token,
|
| 796 |
-
"_commit_hash": commit_hash,
|
| 797 |
-
"_raise_exceptions_for_missing_entries": False,
|
| 798 |
}
|
| 799 |
-
|
|
|
|
|
|
|
|
|
|
| 800 |
cfg = {}
|
| 801 |
-
|
| 802 |
-
|
| 803 |
-
|
| 804 |
-
with open(_p, encoding="utf-8") as _f:
|
| 805 |
-
cfg = json.load(_f)
|
| 806 |
-
break
|
| 807 |
|
| 808 |
-
_init = {"base_tokenizer_path": pretrained_model_name_or_path}
|
| 809 |
-
for _key in ("k", "tail", "auto_dna_tags"):
|
| 810 |
-
if _key in cfg:
|
| 811 |
-
_init[_key] = cfg[_key]
|
| 812 |
-
|
| 813 |
-
tokenizer_config_path = cached_file(pretrained_model_name_or_path, "tokenizer_config.json", **hub_kwargs)
|
| 814 |
-
if tokenizer_config_path is not None:
|
| 815 |
-
with open(tokenizer_config_path, encoding="utf-8") as _f:
|
| 816 |
-
tokenizer_config = json.load(_f)
|
| 817 |
-
if tokenizer_config.get("chat_template"):
|
| 818 |
-
_init["chat_template"] = tokenizer_config["chat_template"]
|
| 819 |
-
|
| 820 |
-
chat_template_path = cached_file(pretrained_model_name_or_path, "chat_template.jinja", **hub_kwargs)
|
| 821 |
-
if chat_template_path is not None:
|
| 822 |
-
with open(chat_template_path, encoding="utf-8") as _f:
|
| 823 |
-
_init["chat_template"] = _f.read()
|
| 824 |
-
|
| 825 |
-
_init.update(kwargs)
|
| 826 |
-
tokenizer = cls(**_init)
|
| 827 |
# DNA ids start right after the base vocabulary, so a layout that differs from the saved one would misalign every
|
| 828 |
# DNA embedding. Fail instead of tokenizing with shifted ids.
|
| 829 |
for _key in ("dna_start_id", "dna_vocab_size"):
|
|
@@ -833,3 +776,7 @@ class HybridDNATokenizer(PreTrainedTokenizer):
|
|
| 833 |
f"{getattr(tokenizer, _key)}, so its DNA token ids would not match the model."
|
| 834 |
)
|
| 835 |
return tokenizer
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
self._build_combined_vocab()
|
| 81 |
|
| 82 |
# Set special tokens
|
| 83 |
+
self._eos_token = kwargs.pop("eos_token", "<|endoftext|>")
|
| 84 |
+
self._pad_token = kwargs.pop("pad_token", self._base_tokenizer.pad_token or "<|endoftext|>")
|
| 85 |
|
| 86 |
# Initialize parent class
|
| 87 |
super().__init__(
|
| 88 |
eos_token=self._eos_token,
|
| 89 |
pad_token=self._pad_token,
|
| 90 |
+
k=k,
|
| 91 |
+
tail=tail,
|
| 92 |
+
auto_dna_tags=auto_dna_tags,
|
| 93 |
**kwargs
|
| 94 |
)
|
| 95 |
|
| 96 |
# Preserve the base tokenizer's AddedToken metadata. These tokens are
|
| 97 |
# already present in the combined vocabulary at their original IDs, so
|
| 98 |
# this only registers their metadata and does not grow the vocabulary.
|
| 99 |
+
# Keep any metadata restored by the parent loader or supplied by the caller.
|
| 100 |
+
existing_ids = self.added_tokens_decoder
|
| 101 |
+
self.add_tokens([
|
| 102 |
+
existing_ids.get(token_id, token)
|
| 103 |
+
for token_id, token in self._base_tokenizer.added_tokens_decoder.items()
|
| 104 |
+
])
|
| 105 |
|
| 106 |
self.special_tokens = self.dna_special_tokens + [self._eos_token, self._pad_token]
|
| 107 |
self.auto_dna_tags = auto_dna_tags
|
|
|
|
| 719 |
|
| 720 |
return (vocab_file,)
|
| 721 |
|
| 722 |
+
def _save_pretrained(
|
| 723 |
+
self,
|
| 724 |
+
save_directory,
|
| 725 |
+
file_names,
|
| 726 |
+
legacy_format=None,
|
| 727 |
+
filename_prefix=None,
|
| 728 |
+
):
|
| 729 |
+
# The parent saves this wrapper's configuration and special-token metadata.
|
| 730 |
+
# Delegate only the BPE assets to the underlying tokenizer's save hook.
|
| 731 |
+
file_names = self._base_tokenizer._save_pretrained(
|
| 732 |
+
save_directory,
|
| 733 |
+
file_names,
|
| 734 |
+
legacy_format=legacy_format,
|
| 735 |
+
filename_prefix=filename_prefix,
|
| 736 |
+
)
|
| 737 |
dna_config = {
|
| 738 |
"k": self.k,
|
| 739 |
"dna_start_id": self.dna_start_id,
|
|
|
|
| 742 |
"auto_dna_tags": self.auto_dna_tags,
|
| 743 |
"tail": self.tail,
|
| 744 |
}
|
|
|
|
| 745 |
dna_config_path = os.path.join(save_directory, "dna_config.json")
|
| 746 |
with open(dna_config_path, "w", encoding="utf-8") as f:
|
| 747 |
json.dump(dna_config, f, indent=2)
|
| 748 |
+
return file_names + (dna_config_path,)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 749 |
|
| 750 |
@classmethod
|
| 751 |
+
def from_pretrained(cls, pretrained_model_name_or_path, *args, **kwargs):
|
| 752 |
+
tokenizer = super().from_pretrained(pretrained_model_name_or_path, *args, **kwargs)
|
| 753 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 754 |
from transformers.utils.hub import cached_file
|
| 755 |
|
|
|
|
|
|
|
|
|
|
| 756 |
hub_kwargs = {
|
| 757 |
+
key: kwargs[key]
|
| 758 |
+
for key in ("cache_dir", "force_download", "local_files_only", "token", "revision", "subfolder", "_commit_hash")
|
| 759 |
+
if key in kwargs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 760 |
}
|
| 761 |
+
config_path = cached_file(
|
| 762 |
+
pretrained_model_name_or_path, "dna_config.json",
|
| 763 |
+
_raise_exceptions_for_missing_entries=False, **hub_kwargs,
|
| 764 |
+
)
|
| 765 |
cfg = {}
|
| 766 |
+
if config_path is not None:
|
| 767 |
+
with open(config_path, encoding="utf-8") as f:
|
| 768 |
+
cfg = json.load(f)
|
|
|
|
|
|
|
|
|
|
| 769 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 770 |
# DNA ids start right after the base vocabulary, so a layout that differs from the saved one would misalign every
|
| 771 |
# DNA embedding. Fail instead of tokenizing with shifted ids.
|
| 772 |
for _key in ("dna_start_id", "dna_vocab_size"):
|
|
|
|
| 776 |
f"{getattr(tokenizer, _key)}, so its DNA token ids would not match the model."
|
| 777 |
)
|
| 778 |
return tokenizer
|
| 779 |
+
|
| 780 |
+
|
| 781 |
+
# Include the custom implementation and AutoTokenizer mapping in saved checkpoints.
|
| 782 |
+
HybridDNATokenizer.register_for_auto_class("AutoTokenizer")
|