Text Generation
Transformers
Safetensors
English
Chinese
qwen3
ksa
ksa-v2
custom_code
long-context
conversational
text-generation-inference
Instructions to use OpenOneRec/KSA-V2-4B-base with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use OpenOneRec/KSA-V2-4B-base with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="OpenOneRec/KSA-V2-4B-base", trust_remote_code=True) 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("OpenOneRec/KSA-V2-4B-base", trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained("OpenOneRec/KSA-V2-4B-base", trust_remote_code=True, 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 OpenOneRec/KSA-V2-4B-base with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "OpenOneRec/KSA-V2-4B-base" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "OpenOneRec/KSA-V2-4B-base", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/OpenOneRec/KSA-V2-4B-base
- SGLang
How to use OpenOneRec/KSA-V2-4B-base 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 "OpenOneRec/KSA-V2-4B-base" \ --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": "OpenOneRec/KSA-V2-4B-base", "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 "OpenOneRec/KSA-V2-4B-base" \ --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": "OpenOneRec/KSA-V2-4B-base", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use OpenOneRec/KSA-V2-4B-base with Docker Model Runner:
docker model run hf.co/OpenOneRec/KSA-V2-4B-base
Download runtime_config.py from OpenOneRec/KSA-V2-4B-base: direct link, hf CLI and curl.
- Browser
- Download file 7.91 kB
-
https://huggingface.co/OpenOneRec/KSA-V2-4B-base/resolve/main/runtime_config.py
- Command line
-
hf download hf://OpenOneRec/KSA-V2-4B-base/runtime_config.py
-
curl -L -o runtime_config.py https://huggingface.co/OpenOneRec/KSA-V2-4B-base/resolve/main/runtime_config.py
7.91 kB
| # coding=utf-8 | |
| # Copyright 2025 The Qwen team, Alibaba Group and the HuggingFace Inc. team. All rights reserved. | |
| # | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| import ast | |
| import torch | |
| from transformers.models.qwen3.configuration_qwen3 import Qwen3Config | |
| def _parse_config_pattern(val): | |
| """Read integer/list layer patterns without executing configuration text.""" | |
| if not isinstance(val, str): | |
| return val | |
| def parse(node): | |
| if isinstance(node, ast.Constant) and type(node.value) is int: | |
| return node.value | |
| if isinstance(node, ast.List): | |
| return [parse(item) for item in node.elts] | |
| if isinstance(node, ast.BinOp): | |
| left, right = parse(node.left), parse(node.right) | |
| if isinstance(node.op, ast.Add): | |
| return left + right | |
| if isinstance(node.op, ast.Mult): | |
| return left * right | |
| raise ValueError("Layer patterns support only integers, lists, + and *") | |
| return parse(ast.parse(val, mode="eval").body) | |
| def _get_shared_batch_mask(mask: torch.Tensor, name: str) -> torch.Tensor: | |
| """Return a 1D mask shared by all batch rows. | |
| Summary attention currently supports batched prefill only when every sample | |
| has the same expanded layout. Packed/ragged batches need document-local | |
| boundaries and are intentionally rejected here. | |
| """ | |
| if mask.ndim == 1: | |
| return mask | |
| if mask.ndim != 2: | |
| raise ValueError(f"{name} must be 1D or 2D, got shape {tuple(mask.shape)}.") | |
| shared = mask[0] | |
| if mask.shape[0] > 1 and not torch.equal(mask, shared.unsqueeze(0).expand_as(mask)): | |
| raise ValueError( | |
| f"{name} must be identical across the batch for synchronized batched prefill; " | |
| "packed or ragged summary layouts are not supported yet." | |
| ) | |
| return shared | |
| def _validate_sksa_runtime_config(config: Qwen3Config) -> None: | |
| # This export supports the summary-based block routing architecture. | |
| if (not getattr(config, "sksa_enabled", False) | |
| or getattr(config, "sksa_routing_mode", None) != "summary_indexer" | |
| or getattr(config, "mix_coeff", None) != 0): | |
| raise ValueError("This inference export requires summary_indexer and mix_coeff=0") | |
| targets = [int(value) for value in config.sksa_sparse_full_layers] | |
| if not targets: | |
| raise ValueError("S-KSA runtime requires at least one sparse Full layer") | |
| if getattr(config, "summary_token_num", 0) != 1: | |
| raise ValueError("S-KSA runtime currently requires one summary token per chunk") | |
| if getattr(config, "summary_chunk_position_ids_type", None) != "origin": | |
| raise ValueError("S-KSA runtime requires original text position IDs") | |
| groups = _parse_config_pattern(config.summary_meta_pool_group_size) | |
| sliding = _parse_config_pattern(config.summary_sliding_chunk_num) | |
| layers = _parse_config_pattern(config.summary_layer_freq) | |
| if not isinstance(groups, list): | |
| groups = [int(groups)] * config.num_hidden_layers | |
| if not isinstance(sliding, list): | |
| sliding = [int(sliding)] * config.num_hidden_layers | |
| if not isinstance(layers, list): | |
| layers = [int(layers)] * config.num_hidden_layers | |
| if not all(len(values) == config.num_hidden_layers for values in (groups, sliding, layers)): | |
| raise ValueError("S-KSA runtime layer patterns must match num_hidden_layers") | |
| token_budget = getattr(config, "sksa_indexer_token_budget", 0) | |
| if isinstance(token_budget, bool) or not isinstance(token_budget, int) or token_budget <= 0: | |
| raise ValueError("indexer token budget must be a positive integer") | |
| for name in ( | |
| "sksa_indexer_query_rank", | |
| "sksa_indexer_heads", | |
| "sksa_indexer_head_dim", | |
| "sksa_indexer_query_block_size", | |
| ): | |
| value = getattr(config, name, 0) | |
| if isinstance(value, bool) or not isinstance(value, int) or value <= 0: | |
| raise ValueError(f"{name} must be a positive integer") | |
| rope_dim = getattr(config, "sksa_indexer_rope_dim", 0) | |
| if ( | |
| isinstance(rope_dim, bool) | |
| or not isinstance(rope_dim, int) | |
| or rope_dim < 0 | |
| or rope_dim > int(config.sksa_indexer_head_dim) | |
| or rope_dim % 2 | |
| ): | |
| raise ValueError("sksa_indexer_rope_dim must be even and within head_dim") | |
| scorer_backend = getattr( | |
| config, "sksa_indexer_scorer_backend", "torch" | |
| ) | |
| if scorer_backend not in ("torch", "fused", "auto"): | |
| raise ValueError( | |
| "sksa_indexer_scorer_backend must be 'torch', 'fused', or 'auto'" | |
| ) | |
| key_source = getattr( | |
| config, "sksa_indexer_summary_key_source", "input_summary" | |
| ) | |
| if key_source not in ("input_summary", "chunk_attention"): | |
| raise ValueError( | |
| "sksa_indexer_summary_key_source must be 'input_summary' or " | |
| "'chunk_attention'" | |
| ) | |
| chunk_qk_source = getattr( | |
| config, "sksa_indexer_chunk_attention_qk_source", "backbone" | |
| ) | |
| if chunk_qk_source not in ("backbone", "independent"): | |
| raise ValueError( | |
| "sksa_indexer_chunk_attention_qk_source must be " | |
| "'backbone' or 'independent'" | |
| ) | |
| chunk_v_source = getattr(config, "sksa_indexer_chunk_attention_v_source", "backbone") | |
| if chunk_v_source not in ("backbone", "independent"): | |
| raise ValueError("invalid sksa_indexer_chunk_attention_v_source") | |
| if chunk_v_source == "independent" and chunk_qk_source != "independent": | |
| raise ValueError("independent chunk V requires independent chunk Q/K") | |
| if chunk_qk_source == "independent" and key_source != "chunk_attention": | |
| raise ValueError( | |
| "independent chunk Q/K requires " | |
| "sksa_indexer_summary_key_source='chunk_attention'" | |
| ) | |
| if int(config.summary_chunk_size) != 8: | |
| raise ValueError("summary indexer runtime currently requires 8-token chunks") | |
| raw_block_size = (getattr(config, "sksa_indexer_block_size", 8)) | |
| if ( | |
| isinstance(raw_block_size, bool) | |
| or not isinstance(raw_block_size, int) | |
| or raw_block_size not in ((2, 4, 8)) | |
| ): | |
| raise ValueError("sksa_indexer_block_size must be 2, 4, or 8") | |
| if raw_block_size < 8 and ( | |
| chunk_qk_source != "independent" | |
| or int(getattr(config, "sksa_local_window_tokens", 0)) < 8 | |
| ): | |
| raise ValueError("subchunk indexer requires independent Q/K and local window >= 8") | |
| if token_budget % raw_block_size: | |
| raise ValueError( | |
| "summary indexer token budget must be divisible by the raw block size" | |
| ) | |
| if int(getattr(config, "sksa_local_window_tokens", 0)) <= 0: | |
| raise ValueError("summary indexer requires a positive local window") | |
| if getattr(config, "sksa_indexer_force_sink", True) and token_budget < 8: | |
| raise ValueError("indexer token budget must cover 8 sink tokens") | |
| for target in targets: | |
| if not 0 <= target < config.num_hidden_layers: | |
| raise ValueError(f"S-KSA target layer {target} is out of range") | |
| if not layers[target] or int(groups[target]) > 1: | |
| raise ValueError(f"S-KSA target layer {target} is not a full KSA layer") | |
| if int(sliding[target]) * config.summary_chunk_size < config.max_position_embeddings: | |
| raise ValueError(f"S-KSA target layer {target} is not globally dense") | |