Text Generation
Transformers
Safetensors
qwen3_5_moe
qwen3.5
Mixture of Experts
fp8
quantized
abliterated
compressed-tensors
vllm
conversational
Instructions to use bjk110/Qwen3.5-122B-A10B-abliterated-FP8 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use bjk110/Qwen3.5-122B-A10B-abliterated-FP8 with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="bjk110/Qwen3.5-122B-A10B-abliterated-FP8") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# Load model directly from transformers import AutoProcessor, AutoModelForCausalLM processor = AutoProcessor.from_pretrained("bjk110/Qwen3.5-122B-A10B-abliterated-FP8") model = AutoModelForCausalLM.from_pretrained("bjk110/Qwen3.5-122B-A10B-abliterated-FP8", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = processor.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=40) print(processor.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use bjk110/Qwen3.5-122B-A10B-abliterated-FP8 with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "bjk110/Qwen3.5-122B-A10B-abliterated-FP8" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "bjk110/Qwen3.5-122B-A10B-abliterated-FP8", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/bjk110/Qwen3.5-122B-A10B-abliterated-FP8
- SGLang
How to use bjk110/Qwen3.5-122B-A10B-abliterated-FP8 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 "bjk110/Qwen3.5-122B-A10B-abliterated-FP8" \ --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": "bjk110/Qwen3.5-122B-A10B-abliterated-FP8", "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 "bjk110/Qwen3.5-122B-A10B-abliterated-FP8" \ --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": "bjk110/Qwen3.5-122B-A10B-abliterated-FP8", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use bjk110/Qwen3.5-122B-A10B-abliterated-FP8 with Docker Model Runner:
docker model run hf.co/bjk110/Qwen3.5-122B-A10B-abliterated-FP8
| #!/usr/bin/env python3 | |
| """ | |
| vLLM patch: Qwen3.5 MoE text-only compatibility shim. | |
| Creates a text-only subclass of Qwen3_5MoeForConditionalGeneration that: | |
| - Reuses the wrapper's hybrid cache-spec calculation (fixes page-size bug) | |
| - Skips vision encoder initialization entirely | |
| - Sets supports_multimodal = False (prevents multimodal warmup) | |
| - Registers as Qwen3_5MoeForCausalLM in the model registry | |
| """ | |
| import re | |
| import textwrap | |
| REGISTRY_PATH = "/usr/local/lib/python3.12/dist-packages/vllm/model_executor/models/registry.py" | |
| QWEN35_PATH = "/usr/local/lib/python3.12/dist-packages/vllm/model_executor/models/qwen3_5.py" | |
| def patch_registry(): | |
| """Map Qwen3_5MoeForCausalLM -> Qwen3_5MoeTextOnlyShim.""" | |
| with open(REGISTRY_PATH) as f: | |
| content = f.read() | |
| entry = '"Qwen3_5MoeForCausalLM"' | |
| if entry in content: | |
| # Update existing entry | |
| content = re.sub( | |
| r'"Qwen3_5MoeForCausalLM": \(\s*"qwen3_5",\s*"[^"]+",\s*\)', | |
| '"Qwen3_5MoeForCausalLM": (\n "qwen3_5",\n "Qwen3_5MoeTextOnlyShim",\n )', | |
| content, | |
| ) | |
| print("[patch] registry: Updated Qwen3_5MoeForCausalLM -> TextOnlyShim") | |
| else: | |
| # Add new entry | |
| target = '"Qwen3_5MoeForConditionalGeneration": (\n "qwen3_5",\n "Qwen3_5MoeForConditionalGeneration",\n ),' | |
| insert = target + '\n "Qwen3_5MoeForCausalLM": (\n "qwen3_5",\n "Qwen3_5MoeTextOnlyShim",\n ),' | |
| if target in content: | |
| content = content.replace(target, insert) | |
| else: | |
| lines = content.split('\n') | |
| for i, line in enumerate(lines): | |
| if '"Qwen3_5MoeForConditionalGeneration"' in line: | |
| for j in range(i, min(i+5, len(lines))): | |
| if lines[j].strip() == '),': | |
| lines.insert(j+1, ' "Qwen3_5MoeForCausalLM": (') | |
| lines.insert(j+2, ' "qwen3_5",') | |
| lines.insert(j+3, ' "Qwen3_5MoeTextOnlyShim",') | |
| lines.insert(j+4, ' ),') | |
| content = '\n'.join(lines) | |
| break | |
| break | |
| print("[patch] registry: Added Qwen3_5MoeForCausalLM -> TextOnlyShim") | |
| with open(REGISTRY_PATH, 'w') as f: | |
| f.write(content) | |
| def patch_add_text_only_shim(): | |
| """Add Qwen3_5MoeTextOnlyShim class to qwen3_5.py.""" | |
| with open(QWEN35_PATH) as f: | |
| content = f.read() | |
| if "Qwen3_5MoeTextOnlyShim" in content: | |
| print("[patch] qwen3_5: TextOnlyShim already exists") | |
| return | |
| # The shim class: inherits ConditionalGeneration for cache-spec, | |
| # but overrides __init__ to skip vision, and sets supports_multimodal = False | |
| shim_code = ''' | |
| ######################################################## | |
| # Text-only compatibility shim | |
| # Reuses ConditionalGeneration's cache-spec but skips vision | |
| ######################################################## | |
| class Qwen3_5MoeTextOnlyShim(Qwen3_5MoeForConditionalGeneration): | |
| """Text-only shim for Qwen3.5 MoE CausalLM checkpoints. | |
| Inherits Qwen3_5MoeForConditionalGeneration for hybrid cache-spec | |
| calculation (fixing the page-size bug in CausalLM path), but: | |
| - Does NOT initialize vision encoder | |
| - Does NOT register as multimodal | |
| - Rejects multimodal input at forward time | |
| """ | |
| # Override: NOT a multimodal model | |
| supports_multimodal = False | |
| def __init__(self, *, vllm_config, prefix: str = "model"): | |
| import logging | |
| log = logging.getLogger("qwen3_5_text_only_shim") | |
| # Skip the parent's multimodal __init__ entirely | |
| # Go directly to nn.Module.__init__ | |
| nn.Module.__init__(self) | |
| config = vllm_config.model_config.hf_config | |
| self.config = config | |
| # vision_config is now a dummy with safe values (hidden_size=128) | |
| # created by the patched Qwen3_5MoeConfig.__init__ | |
| vc = getattr(config, "vision_config", None) | |
| if vc is not None: | |
| log.info(f"vision_config present: hidden_size={getattr(vc, 'hidden_size', '?')}") | |
| # Inject dummy MultiModalConfig so _mark_language_model works | |
| # All defaults are safe for text-only (mm_encoder_only=False, etc.) | |
| from vllm.config.multimodal import MultiModalConfig | |
| if vllm_config.model_config.multimodal_config is None: | |
| vllm_config.model_config.multimodal_config = MultiModalConfig() | |
| log.info("Injected dummy MultiModalConfig for text-only shim") | |
| self.multimodal_config = vllm_config.model_config.multimodal_config | |
| self.visual = None | |
| self.use_data_parallel = False | |
| self.is_multimodal_pruning_enabled = False | |
| self._text_only_mode = True | |
| log.info("Qwen3_5MoeTextOnlyShim: text-only mode, vision encoder skipped") | |
| # Use _mark_language_model to preserve wrapper's cache-spec path | |
| with self._mark_language_model(vllm_config): | |
| self.language_model = Qwen3_5MoeForCausalLM( | |
| vllm_config=vllm_config, | |
| prefix=maybe_prefix(prefix, "language_model"), | |
| ) | |
| self.make_empty_intermediate_tensors = ( | |
| self.language_model.make_empty_intermediate_tensors | |
| ) | |
| # set MoE hyperparameters | |
| self.set_moe_parameters() | |
| def forward(self, *args, **kwargs): | |
| """Forward: delegate to language_model, reject multimodal input.""" | |
| if kwargs.get("pixel_values") is not None or kwargs.get("image_grid_thw") is not None: | |
| raise ValueError( | |
| "Qwen3_5MoeTextOnlyShim does not support multimodal input. " | |
| "This model was loaded as text-only." | |
| ) | |
| return self.language_model(*args, **kwargs) | |
| def load_weights(self, weights): | |
| """Load weights with key remapping for text-only checkpoints.""" | |
| import logging | |
| log = logging.getLogger("qwen3_5_text_only_shim") | |
| def _remap(weights_iter): | |
| remapped = False | |
| for name, tensor in weights_iter: | |
| new_name = name | |
| # ModelOpt export uses model.language_model.* prefix | |
| # which matches our module tree (self.language_model.model.*) | |
| # No remapping needed for ConditionalGeneration path | |
| # since self.language_model prefix is already "language_model" | |
| yield new_name, tensor | |
| loader = AutoWeightsLoader(self, skip_prefixes=["mtp.", "visual."]) | |
| return loader.load_weights(_remap(weights), mapper=self.hf_to_vllm_mapper) | |
| ''' | |
| # Insert before the final class or at the end of file | |
| # Find the last class definition to insert after | |
| insert_pos = content.rfind('\nclass Qwen3_5MoeForConditionalGeneration') | |
| if insert_pos == -1: | |
| # Append at end | |
| content += shim_code | |
| else: | |
| # Find the end of Qwen3_5MoeForConditionalGeneration class (next class or EOF) | |
| # Insert after the entire ConditionalGeneration class | |
| # Find the set_moe_parameters() call which is the last line of __init__ | |
| end_of_class = content.find('\nclass ', insert_pos + 10) | |
| if end_of_class == -1: | |
| content += shim_code | |
| else: | |
| # Actually, insert at the very end of the file | |
| content += shim_code | |
| with open(QWEN35_PATH, 'w') as f: | |
| f.write(content) | |
| print("[patch] qwen3_5: Added Qwen3_5MoeTextOnlyShim class") | |
| def patch_processing_info(): | |
| """Patch ProcessingInfo to handle text-only config gracefully.""" | |
| with open(QWEN35_PATH) as f: | |
| content = f.read() | |
| if "text_only_shim_processing" in content: | |
| print("[patch] qwen3_5: ProcessingInfo already patched") | |
| return | |
| old = '''class Qwen3_5MoeProcessingInfo(Qwen3VLProcessingInfo): | |
| def get_hf_config(self): | |
| return self.ctx.get_hf_config(Qwen3_5MoeConfig)''' | |
| new = '''class Qwen3_5MoeProcessingInfo(Qwen3VLProcessingInfo): | |
| # text_only_shim_processing | |
| def get_hf_config(self): | |
| try: | |
| return self.ctx.get_hf_config(Qwen3_5MoeConfig) | |
| except TypeError: | |
| return self.ctx.model_config.hf_config | |
| def get_data_parser(self): | |
| config = self.get_hf_config() | |
| if not hasattr(config, "vision_config") or config.vision_config is None: | |
| from vllm.multimodal.parse import MultiModalDataParser | |
| return MultiModalDataParser() | |
| return super().get_data_parser() | |
| def get_max_image_tokens(self): | |
| config = self.get_hf_config() | |
| if not hasattr(config, "vision_config") or config.vision_config is None: | |
| return 0 | |
| return super().get_max_image_tokens() | |
| def get_max_video_tokens(self, seq_len, mm_counts=None): | |
| config = self.get_hf_config() | |
| if not hasattr(config, "vision_config") or config.vision_config is None: | |
| return 0 | |
| return super().get_max_video_tokens(seq_len, mm_counts) | |
| def get_image_size_with_most_features(self): | |
| config = self.get_hf_config() | |
| if not hasattr(config, "vision_config") or config.vision_config is None: | |
| return (0, 0) | |
| return super().get_image_size_with_most_features()''' | |
| if old in content: | |
| content = content.replace(old, new) | |
| with open(QWEN35_PATH, 'w') as f: | |
| f.write(content) | |
| print("[patch] qwen3_5: ProcessingInfo patched") | |
| else: | |
| print("[patch] qwen3_5: ProcessingInfo already modified or not found") | |
| def patch_config_vision_default(): | |
| """Prevent Qwen3_5MoeConfig from auto-creating vision_config when None. | |
| The original code: if vision_config is None -> create default VisionConfig. | |
| We change it: if vision_config is None -> keep as None. | |
| This prevents vision hidden_size=1152 from leaking into FP8 TP2 validation. | |
| """ | |
| CONFIG_PATH = "/usr/local/lib/python3.12/dist-packages/vllm/transformers_utils/configs/qwen3_5_moe.py" | |
| with open(CONFIG_PATH) as f: | |
| content = f.read() | |
| if "text_only_shim_config" in content: | |
| print("[patch] config: vision_config default already patched") | |
| return | |
| old = ' elif vision_config is None:\n self.vision_config = self.sub_configs["vision_config"]()' | |
| # Instead of None, use a dummy with minimal safe values | |
| # This prevents NoneType errors in multimodal processing code | |
| # while keeping hidden_size small enough for TP2 block validation | |
| new = ''' elif vision_config is None: | |
| # text_only_shim_config: create minimal dummy vision config | |
| # with safe values that pass TP2 block-wise FP8 validation | |
| # hidden_size=128 is divisible by block_size=128 and any TP | |
| self.vision_config = self.sub_configs["vision_config"]( | |
| hidden_size=128, intermediate_size=256, depth=0, | |
| num_heads=1, patch_size=16, spatial_merge_size=2, | |
| temporal_patch_size=2, in_channels=3, | |
| )''' | |
| if old in content: | |
| content = content.replace(old, new) | |
| with open(CONFIG_PATH, 'w') as f: | |
| f.write(content) | |
| print("[patch] config: vision_config default -> None (text-only safe)") | |
| else: | |
| print("[patch] config: Could not find vision_config default pattern") | |
| if __name__ == "__main__": | |
| print("=" * 55) | |
| print("vLLM Patch: Qwen3.5 MoE text-only shim v3") | |
| print("=" * 55) | |
| patch_registry() | |
| patch_add_text_only_shim() | |
| patch_processing_info() | |
| patch_config_vision_default() | |
| print("=" * 55) | |
| print("Patch complete") | |