Text Generation
Transformers
Safetensors
GGUF
English
qwen3_5
image-text-to-text
fastbrain
clef
llama-cpp
sglang
systemone
decision-model
image-text-to-typed-output
decision-index
tool-calling
function-calling
intent-classification
structured-decision
conversational
Eval Results
Instructions to use TypeScript/FastBrain-9B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use TypeScript/FastBrain-9B with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="TypeScript/FastBrain-9B") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] pipe(text=messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoProcessor, AutoModelForMultimodalLM processor = AutoProcessor.from_pretrained("TypeScript/FastBrain-9B") model = AutoModelForMultimodalLM.from_pretrained("TypeScript/FastBrain-9B", device_map="auto") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] 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=256) print(processor.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use TypeScript/FastBrain-9B with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf TypeScript/FastBrain-9B:Q4_K_M # Run inference directly in the terminal: llama cli -hf TypeScript/FastBrain-9B:Q4_K_M
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf TypeScript/FastBrain-9B:Q4_K_M # Run inference directly in the terminal: llama cli -hf TypeScript/FastBrain-9B:Q4_K_M
Build from source code
git clone https://github.com/ggml-org/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-app # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama serve -hf TypeScript/FastBrain-9B:Q4_K_M # Run inference directly in the terminal: ./build/bin/llama cli -hf TypeScript/FastBrain-9B:Q4_K_M
Use Docker
docker model run hf.co/TypeScript/FastBrain-9B:Q4_K_M
- Llama new
- LM Studio
- Jan
- vLLM
How to use TypeScript/FastBrain-9B with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "TypeScript/FastBrain-9B" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "TypeScript/FastBrain-9B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/TypeScript/FastBrain-9B:Q4_K_M
- SGLang
How to use TypeScript/FastBrain-9B 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 "TypeScript/FastBrain-9B" \ --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": "TypeScript/FastBrain-9B", "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 "TypeScript/FastBrain-9B" \ --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": "TypeScript/FastBrain-9B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Ollama
How to use TypeScript/FastBrain-9B with Ollama:
ollama run hf.co/TypeScript/FastBrain-9B:Q4_K_M
- Unsloth Desktop
- Pi
How to use TypeScript/FastBrain-9B with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf TypeScript/FastBrain-9B:Q4_K_M
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "TypeScript/FastBrain-9B:Q4_K_M" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Docker Model Runner
How to use TypeScript/FastBrain-9B with Docker Model Runner:
docker model run hf.co/TypeScript/FastBrain-9B:Q4_K_M
- Lemonade
How to use TypeScript/FastBrain-9B with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull TypeScript/FastBrain-9B:Q4_K_M
Run and chat with the model
lemonade run user.FastBrain-9B-Q4_K_M
List all available models
lemonade list
- Hermes Agent
How to use TypeScript/FastBrain-9B with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf TypeScript/FastBrain-9B:Q4_K_M
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default TypeScript/FastBrain-9B:Q4_K_M
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use TypeScript/FastBrain-9B with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf TypeScript/FastBrain-9B:Q4_K_M
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "TypeScript/FastBrain-9B:Q4_K_M" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
Optimize JointSchemaHead (Ordinal-KL + multi-task calibration distillation), SGLang fast FlashAttention kernel in joint_schema_model.py, and sync GGUF builds
Browse files- FastBrain-9B-BF16.gguf +2 -2
- FastBrain-9B-Q4_K_M.gguf +2 -2
- FastBrain-9B-Q8_0.gguf +2 -2
- joint_head.safetensors +1 -1
- joint_schema_model.py +295 -2
FastBrain-9B-BF16.gguf
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ef9d5ec64502466ed71933f4dfd89156ff1aafaa4e2c36c8af5a3f62dc091a2e
|
| 3 |
+
size 18164488768
|
FastBrain-9B-Q4_K_M.gguf
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a40f122e5c7dac5d901a4a0c9993e953c1e4b0ebb974722459020ad801d54c6b
|
| 3 |
+
size 6732782144
|
FastBrain-9B-Q8_0.gguf
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:901e34c4ac710b2c52c4d1c56da85bc8b230f70a514ad5420b019ce27037bfa7
|
| 3 |
+
size 9657260608
|
joint_head.safetensors
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
size 243537984
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ce8517deeb83948b29c4e24428171bbd403af220555ddf8c063792c332752b14
|
| 3 |
size 243537984
|
joint_schema_model.py
CHANGED
|
@@ -267,6 +267,41 @@ def collate_records(
|
|
| 267 |
}
|
| 268 |
|
| 269 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 270 |
class EvidenceRoutingLayer(torch.nn.Module):
|
| 271 |
def __init__(
|
| 272 |
self,
|
|
@@ -369,7 +404,234 @@ class JointSchemaHead(torch.nn.Module):
|
|
| 369 |
start, end = span
|
| 370 |
return values[start:end].mean(dim=0)
|
| 371 |
|
| 372 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 373 |
self,
|
| 374 |
hidden_states: torch.Tensor,
|
| 375 |
input_ids: torch.Tensor,
|
|
@@ -486,6 +748,38 @@ class JointSchemaHead(torch.nn.Module):
|
|
| 486 |
results.append(record_logits)
|
| 487 |
return results
|
| 488 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 489 |
|
| 490 |
class ClefModel(torch.nn.Module):
|
| 491 |
def __init__(self, language_model: Any, head: JointSchemaHead) -> None:
|
|
@@ -1053,4 +1347,3 @@ def _apply_schema_aware_calibration(request: dict[str, Any], answers: dict[str,
|
|
| 1053 |
|
| 1054 |
|
| 1055 |
apply_schema_aware_calibration = _apply_schema_aware_calibration
|
| 1056 |
-
|
|
|
|
| 267 |
}
|
| 268 |
|
| 269 |
|
| 270 |
+
def _packed_flash_attention(
|
| 271 |
+
module: torch.nn.MultiheadAttention,
|
| 272 |
+
queries: torch.Tensor,
|
| 273 |
+
keys: torch.Tensor | None,
|
| 274 |
+
query_bounds: tuple[torch.Tensor, int],
|
| 275 |
+
key_bounds: tuple[torch.Tensor, int],
|
| 276 |
+
) -> torch.Tensor:
|
| 277 |
+
"""Variable-length FlashAttention over packed sequences within each request."""
|
| 278 |
+
width = queries.shape[-1]
|
| 279 |
+
heads = module.num_heads
|
| 280 |
+
if keys is None:
|
| 281 |
+
query, key, value = functional.linear(
|
| 282 |
+
queries, module.in_proj_weight, module.in_proj_bias
|
| 283 |
+
).chunk(3, dim=-1)
|
| 284 |
+
else:
|
| 285 |
+
query_weight, key_value_weight = module.in_proj_weight.split([width, 2 * width])
|
| 286 |
+
query_bias, key_value_bias = module.in_proj_bias.split([width, 2 * width])
|
| 287 |
+
query = functional.linear(queries, query_weight, query_bias)
|
| 288 |
+
key, value = functional.linear(keys, key_value_weight, key_value_bias).chunk(2, dim=-1)
|
| 289 |
+
head_dim = width // heads
|
| 290 |
+
output = torch.ops.aten._flash_attention_forward(
|
| 291 |
+
query.reshape(-1, heads, head_dim),
|
| 292 |
+
key.reshape(-1, heads, head_dim),
|
| 293 |
+
value.reshape(-1, heads, head_dim),
|
| 294 |
+
query_bounds[0],
|
| 295 |
+
key_bounds[0],
|
| 296 |
+
query_bounds[1],
|
| 297 |
+
key_bounds[1],
|
| 298 |
+
0.0,
|
| 299 |
+
False,
|
| 300 |
+
False,
|
| 301 |
+
)[0]
|
| 302 |
+
return module.out_proj(output.reshape(-1, width))
|
| 303 |
+
|
| 304 |
+
|
| 305 |
class EvidenceRoutingLayer(torch.nn.Module):
|
| 306 |
def __init__(
|
| 307 |
self,
|
|
|
|
| 404 |
start, end = span
|
| 405 |
return values[start:end].mean(dim=0)
|
| 406 |
|
| 407 |
+
def _forward_fast_cuda(
|
| 408 |
+
self,
|
| 409 |
+
hidden_states: torch.Tensor,
|
| 410 |
+
input_ids: torch.Tensor,
|
| 411 |
+
attention_mask: torch.Tensor,
|
| 412 |
+
records: list[EncodedRecord],
|
| 413 |
+
output_embedding_weight: torch.Tensor,
|
| 414 |
+
) -> list[list[torch.Tensor]]:
|
| 415 |
+
"""Vectorized prefix-sum span pooling + packed varlen FlashAttention (SGLang dev-clef kernel)."""
|
| 416 |
+
device, dtype = hidden_states.device, hidden_states.dtype
|
| 417 |
+
batch = len(records)
|
| 418 |
+
lengths = [int(attention_mask[i].sum().item()) for i in range(batch)]
|
| 419 |
+
if batch == 1:
|
| 420 |
+
hidden = hidden_states[0, : lengths[0]]
|
| 421 |
+
flat_ids = input_ids[0, : lengths[0]]
|
| 422 |
+
else:
|
| 423 |
+
hidden = torch.cat([hidden_states[i, : lengths[i]] for i in range(batch)], dim=0)
|
| 424 |
+
flat_ids = torch.cat([input_ids[i, : lengths[i]] for i in range(batch)], dim=0)
|
| 425 |
+
|
| 426 |
+
question_bounds: list[int] = []
|
| 427 |
+
option_bounds: list[int] = []
|
| 428 |
+
type_ids: list[int] = []
|
| 429 |
+
owner: list[int] = []
|
| 430 |
+
slot: list[int] = []
|
| 431 |
+
question_request: list[int] = []
|
| 432 |
+
last_tokens: list[int] = []
|
| 433 |
+
regions: list[tuple[int, int]] = []
|
| 434 |
+
region_offsets = [0]
|
| 435 |
+
token_cu = [0]
|
| 436 |
+
question_cu = [0]
|
| 437 |
+
option_cu = [0]
|
| 438 |
+
option_counts: list[int] = []
|
| 439 |
+
per_req_q_counts: list[list[int]] = []
|
| 440 |
+
|
| 441 |
+
for request, (length, record) in enumerate(zip(lengths, records)):
|
| 442 |
+
offset = token_cu[-1]
|
| 443 |
+
questions = record.questions
|
| 444 |
+
low = min(min(q.question_span[0], q.option_spans[0][0]) for q in questions)
|
| 445 |
+
high = max(
|
| 446 |
+
max(q.question_span[1], *(e for _, e in q.option_spans))
|
| 447 |
+
for q in questions
|
| 448 |
+
)
|
| 449 |
+
base = region_offsets[-1] + request - low
|
| 450 |
+
regions.append((offset + low, offset + high))
|
| 451 |
+
request_options = 0
|
| 452 |
+
q_opt_counts: list[int] = []
|
| 453 |
+
for question in questions:
|
| 454 |
+
count = len(question.option_spans)
|
| 455 |
+
q_opt_counts.append(count)
|
| 456 |
+
question_bounds += (
|
| 457 |
+
base + question.question_span[0],
|
| 458 |
+
base + question.question_span[1],
|
| 459 |
+
)
|
| 460 |
+
for option_slot, (option_start, option_end) in enumerate(
|
| 461 |
+
question.option_spans
|
| 462 |
+
):
|
| 463 |
+
option_bounds += (base + option_start, base + option_end)
|
| 464 |
+
owner.append(len(type_ids))
|
| 465 |
+
slot.append(option_slot)
|
| 466 |
+
type_ids.append(question.question_type)
|
| 467 |
+
question_request.append(request)
|
| 468 |
+
request_options += count
|
| 469 |
+
per_req_q_counts.append(q_opt_counts)
|
| 470 |
+
last_tokens.append(offset + length - 1)
|
| 471 |
+
token_cu.append(offset + length)
|
| 472 |
+
region_offsets.append(region_offsets[-1] + high - low)
|
| 473 |
+
question_cu.append(len(type_ids))
|
| 474 |
+
option_cu.append(option_cu[-1] + request_options)
|
| 475 |
+
option_counts.append(request_options)
|
| 476 |
+
|
| 477 |
+
num_questions = len(type_ids)
|
| 478 |
+
widest = max(len(q.option_spans) for r in records for q in r.questions)
|
| 479 |
+
sizes = [
|
| 480 |
+
2 * num_questions,
|
| 481 |
+
len(option_bounds),
|
| 482 |
+
num_questions,
|
| 483 |
+
len(owner),
|
| 484 |
+
len(slot),
|
| 485 |
+
num_questions,
|
| 486 |
+
batch,
|
| 487 |
+
3 * (batch + 1),
|
| 488 |
+
]
|
| 489 |
+
packed = torch.tensor(
|
| 490 |
+
question_bounds
|
| 491 |
+
+ option_bounds
|
| 492 |
+
+ type_ids
|
| 493 |
+
+ owner
|
| 494 |
+
+ slot
|
| 495 |
+
+ question_request
|
| 496 |
+
+ last_tokens
|
| 497 |
+
+ token_cu
|
| 498 |
+
+ question_cu
|
| 499 |
+
+ option_cu,
|
| 500 |
+
dtype=torch.long,
|
| 501 |
+
device=device,
|
| 502 |
+
)
|
| 503 |
+
(
|
| 504 |
+
question_bounds_t,
|
| 505 |
+
option_bounds_t,
|
| 506 |
+
type_ids_t,
|
| 507 |
+
owner_t,
|
| 508 |
+
slot_t,
|
| 509 |
+
question_request_t,
|
| 510 |
+
last_tokens_t,
|
| 511 |
+
cu_t,
|
| 512 |
+
) = torch.split(packed, sizes)
|
| 513 |
+
question_bounds_t = question_bounds_t.view(-1, 2)
|
| 514 |
+
option_bounds_t = option_bounds_t.view(-1, 2)
|
| 515 |
+
token_cu_t, question_cu_t, option_cu_t = (
|
| 516 |
+
cu_t.to(torch.int32).view(3, batch + 1).unbind(0)
|
| 517 |
+
)
|
| 518 |
+
token_bounds = (token_cu_t, max(lengths))
|
| 519 |
+
question_bounds_cu = (question_cu_t, max(len(r.questions) for r in records))
|
| 520 |
+
option_bounds_cu = (option_cu_t, max(option_counts))
|
| 521 |
+
|
| 522 |
+
normalized = self.hidden_norm(hidden)
|
| 523 |
+
region_total = region_offsets[-1] + batch
|
| 524 |
+
hidden_prefix = torch.zeros(
|
| 525 |
+
region_total, normalized.shape[-1], dtype=torch.float32, device=device
|
| 526 |
+
)
|
| 527 |
+
lexical_prefix = torch.zeros(
|
| 528 |
+
region_total,
|
| 529 |
+
output_embedding_weight.shape[-1],
|
| 530 |
+
dtype=torch.float32,
|
| 531 |
+
device=device,
|
| 532 |
+
)
|
| 533 |
+
for request, (low, high) in enumerate(regions):
|
| 534 |
+
row = region_offsets[request] + request + 1
|
| 535 |
+
torch.cumsum(
|
| 536 |
+
normalized[low:high].float(),
|
| 537 |
+
dim=0,
|
| 538 |
+
out=hidden_prefix[row : row + high - low],
|
| 539 |
+
)
|
| 540 |
+
torch.cumsum(
|
| 541 |
+
output_embedding_weight[flat_ids[low:high]].float(),
|
| 542 |
+
dim=0,
|
| 543 |
+
out=lexical_prefix[row : row + high - low],
|
| 544 |
+
)
|
| 545 |
+
|
| 546 |
+
def span_means(prefix: torch.Tensor, bounds: torch.Tensor) -> torch.Tensor:
|
| 547 |
+
sums = prefix[bounds[:, 1]] - prefix[bounds[:, 0]]
|
| 548 |
+
return (sums / (bounds[:, 1] - bounds[:, 0]).unsqueeze(-1)).to(dtype)
|
| 549 |
+
|
| 550 |
+
memory = self.memory_projection(normalized)
|
| 551 |
+
global_vectors = normalized[last_tokens_t]
|
| 552 |
+
question_vectors = span_means(hidden_prefix, question_bounds_t)
|
| 553 |
+
option_contexts = span_means(hidden_prefix, option_bounds_t)
|
| 554 |
+
lexical = span_means(lexical_prefix, option_bounds_t)
|
| 555 |
+
|
| 556 |
+
routed = (
|
| 557 |
+
self.option_context_projection(option_contexts)
|
| 558 |
+
+ self.option_lexical_projection(lexical)
|
| 559 |
+
+ self.option_question_projection(question_vectors)[owner_t]
|
| 560 |
+
)
|
| 561 |
+
for layer in self.evidence_layers:
|
| 562 |
+
routed = routed + _packed_flash_attention(
|
| 563 |
+
layer.attention,
|
| 564 |
+
layer.query_norm(routed),
|
| 565 |
+
layer.memory_norm(memory),
|
| 566 |
+
option_bounds_cu,
|
| 567 |
+
token_bounds,
|
| 568 |
+
)
|
| 569 |
+
routed = routed + layer.feedforward(layer.feedforward_norm(routed))
|
| 570 |
+
|
| 571 |
+
base_fields = self.question_projection(question_vectors)
|
| 572 |
+
scores = torch.matmul(
|
| 573 |
+
routed.unsqueeze(1), base_fields[owner_t].unsqueeze(2)
|
| 574 |
+
).view(-1) / math.sqrt(routed.shape[-1])
|
| 575 |
+
padded_scores = torch.full(
|
| 576 |
+
(num_questions, widest), float("-inf"), dtype=torch.float32, device=device
|
| 577 |
+
)
|
| 578 |
+
padded_scores[owner_t, slot_t] = scores.float()
|
| 579 |
+
weights = torch.softmax(padded_scores, dim=1).to(dtype)
|
| 580 |
+
padded_options = routed.new_zeros(num_questions, widest, routed.shape[-1])
|
| 581 |
+
padded_options[owner_t, slot_t] = routed
|
| 582 |
+
summaries = torch.sum(weights.unsqueeze(-1) * padded_options, dim=1)
|
| 583 |
+
fields = (
|
| 584 |
+
base_fields
|
| 585 |
+
+ self.option_summary_norm(summaries)
|
| 586 |
+
+ self.global_projection(global_vectors)[question_request_t]
|
| 587 |
+
+ self.type_embedding(type_ids_t)
|
| 588 |
+
)
|
| 589 |
+
for layer in self.layers:
|
| 590 |
+
fields = fields + _packed_flash_attention(
|
| 591 |
+
layer.self_attn,
|
| 592 |
+
layer.norm1(fields),
|
| 593 |
+
None,
|
| 594 |
+
question_bounds_cu,
|
| 595 |
+
question_bounds_cu,
|
| 596 |
+
)
|
| 597 |
+
fields = fields + _packed_flash_attention(
|
| 598 |
+
layer.multihead_attn,
|
| 599 |
+
layer.norm2(fields),
|
| 600 |
+
memory,
|
| 601 |
+
question_bounds_cu,
|
| 602 |
+
token_bounds,
|
| 603 |
+
)
|
| 604 |
+
fields = fields + layer.linear2(
|
| 605 |
+
layer.activation(layer.linear1(layer.norm3(fields)))
|
| 606 |
+
)
|
| 607 |
+
fields = self.field_norm(fields)
|
| 608 |
+
|
| 609 |
+
prior_scale = self.prior_logit_scale.clamp(max=math.log(100.0)).exp()
|
| 610 |
+
joint_scale = self.joint_logit_scale.clamp(max=math.log(100.0)).exp()
|
| 611 |
+
anchor = functional.normalize(
|
| 612 |
+
question_vectors + global_vectors[question_request_t], dim=-1
|
| 613 |
+
)
|
| 614 |
+
prior = prior_scale * torch.matmul(
|
| 615 |
+
functional.normalize(lexical, dim=-1).unsqueeze(1), anchor[owner_t].unsqueeze(2)
|
| 616 |
+
).view(-1)
|
| 617 |
+
options = self.option_norm(routed)
|
| 618 |
+
repeated = fields[owner_t]
|
| 619 |
+
cosine = functional.cosine_similarity(repeated, options, dim=-1)
|
| 620 |
+
features = torch.cat(
|
| 621 |
+
[repeated, options, repeated * options, torch.abs(repeated - options)],
|
| 622 |
+
dim=-1,
|
| 623 |
+
)
|
| 624 |
+
residual = self.residual_scorer(features).squeeze(-1)
|
| 625 |
+
logits = prior + torch.sigmoid(self.residual_gate) * (
|
| 626 |
+
joint_scale * cosine + residual
|
| 627 |
+
)
|
| 628 |
+
per_req_flat = torch.split(logits, option_counts)
|
| 629 |
+
return [
|
| 630 |
+
list(torch.split(req_logits, q_counts))
|
| 631 |
+
for req_logits, q_counts in zip(per_req_flat, per_req_q_counts)
|
| 632 |
+
]
|
| 633 |
+
|
| 634 |
+
def _forward_reference(
|
| 635 |
self,
|
| 636 |
hidden_states: torch.Tensor,
|
| 637 |
input_ids: torch.Tensor,
|
|
|
|
| 748 |
results.append(record_logits)
|
| 749 |
return results
|
| 750 |
|
| 751 |
+
def forward(
|
| 752 |
+
self,
|
| 753 |
+
hidden_states: torch.Tensor,
|
| 754 |
+
input_ids: torch.Tensor,
|
| 755 |
+
attention_mask: torch.Tensor,
|
| 756 |
+
records: list[EncodedRecord],
|
| 757 |
+
output_embedding_weight: torch.Tensor,
|
| 758 |
+
) -> list[list[torch.Tensor]]:
|
| 759 |
+
if (
|
| 760 |
+
not torch.is_grad_enabled()
|
| 761 |
+
and hidden_states.is_cuda
|
| 762 |
+
and hidden_states.dtype in (torch.float16, torch.bfloat16)
|
| 763 |
+
and hasattr(torch.ops.aten, "_flash_attention_forward")
|
| 764 |
+
):
|
| 765 |
+
try:
|
| 766 |
+
return self._forward_fast_cuda(
|
| 767 |
+
hidden_states,
|
| 768 |
+
input_ids,
|
| 769 |
+
attention_mask,
|
| 770 |
+
records,
|
| 771 |
+
output_embedding_weight,
|
| 772 |
+
)
|
| 773 |
+
except Exception:
|
| 774 |
+
pass
|
| 775 |
+
return self._forward_reference(
|
| 776 |
+
hidden_states,
|
| 777 |
+
input_ids,
|
| 778 |
+
attention_mask,
|
| 779 |
+
records,
|
| 780 |
+
output_embedding_weight,
|
| 781 |
+
)
|
| 782 |
+
|
| 783 |
|
| 784 |
class ClefModel(torch.nn.Module):
|
| 785 |
def __init__(self, language_model: Any, head: JointSchemaHead) -> None:
|
|
|
|
| 1347 |
|
| 1348 |
|
| 1349 |
apply_schema_aware_calibration = _apply_schema_aware_calibration
|
|
|