Upload 9 files
Browse files- README.md +156 -3
- config.json +49 -0
- generation_config.json +10 -0
- inference.py +16 -0
- model.safetensors +3 -0
- modeling_synapse.py +8 -0
- synapse_controller.py +90 -0
- tokenizer.json +0 -0
- tokenizer_config.json +32 -0
README.md
CHANGED
|
@@ -1,3 +1,156 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<p align="center">
|
| 2 |
+
<img src="./assets/khazri-2-preview-banner.png" alt="Khazri 2 Preview — flagship open-weight language model" width="100%">
|
| 3 |
+
</p>
|
| 4 |
+
|
| 5 |
+
<p align="center">
|
| 6 |
+
<img src="./assets/khazri-wordmark.png" alt="Khazri 2" width="280">
|
| 7 |
+
</p>
|
| 8 |
+
|
| 9 |
+
# Khazri 2 Preview
|
| 10 |
+
|
| 11 |
+
**Khazri 2 Preview** is the flagship preview checkpoint in the Khazri language-model family. It pairs the Khazri model with the project’s **SYNAPSE** architecture and route-aware inference system, making it suitable for research, controlled experimentation and evaluation before a full production release.
|
| 12 |
+
|
| 13 |
+
[Khazri website](https://khazri.dev) · [Contact the Khazri team](mailto:contact@khazri.dev)
|
| 14 |
+
|
| 15 |
+
> **Preview release:** Treat this checkpoint as a research preview. Validate it on your own tasks and do not make high-stakes decisions solely from its output.
|
| 16 |
+
|
| 17 |
+
## At a glance
|
| 18 |
+
|
| 19 |
+
| Item | Detail |
|
| 20 |
+
| --- | --- |
|
| 21 |
+
| Model | Khazri 2 Preview |
|
| 22 |
+
| Family position | Flagship model in the current Khazri 2 generation |
|
| 23 |
+
| Parameters | ~250M (release <code>config.json</code> is the final source of truth) |
|
| 24 |
+
| Architecture | Khazri model with SYNAPSE components |
|
| 25 |
+
| Inference export context limit | 512 tokens |
|
| 26 |
+
| Default maximum generation | 128 new tokens |
|
| 27 |
+
| Loading | Transformers with custom model code |
|
| 28 |
+
| Web-search route | Disabled by default in the supplied notebook |
|
| 29 |
+
|
| 30 |
+
## SYNAPSE-aware inference
|
| 31 |
+
|
| 32 |
+
The supplied Khazri 2 Preview notebook expects the following model-side files:
|
| 33 |
+
|
| 34 |
+
~~~text
|
| 35 |
+
config.json
|
| 36 |
+
generation_config.json
|
| 37 |
+
model.safetensors
|
| 38 |
+
tokenizer.json
|
| 39 |
+
tokenizer_config.json
|
| 40 |
+
modeling_synapse.py
|
| 41 |
+
synapse_controller.py
|
| 42 |
+
inference.py
|
| 43 |
+
~~~
|
| 44 |
+
|
| 45 |
+
The notebook loads the model with <code>trust_remote_code=True</code> and provides a fallback route system with:
|
| 46 |
+
|
| 47 |
+
- <code>NSR_CALCULATOR</code> for safe numeric calculation;
|
| 48 |
+
- <code>MATH_SOLVER</code> for symbolic math tasks;
|
| 49 |
+
- <code>TMS_CONTEXT</code> for context-grounded answers;
|
| 50 |
+
- <code>UQM_ABSTAIN</code> for abstention when information is insufficient or inappropriate;
|
| 51 |
+
- <code>WEB_SEARCH</code>, disabled by default; and
|
| 52 |
+
- <code>MODEL_FALLBACK</code> for standard generation.
|
| 53 |
+
|
| 54 |
+
The exact routing decision is implementation-dependent. Inspect the shipped Python files before enabling remote code, and pin a revision in production.
|
| 55 |
+
|
| 56 |
+
## Training data
|
| 57 |
+
|
| 58 |
+
The supplied **Khazri 2 Preview inference notebook does not disclose the training dataset composition**. It contains runtime, tokenizer and SYNAPSE inference logic—not a training manifest—so this model card does not infer a source list from it.
|
| 59 |
+
|
| 60 |
+
A separate Khazri Mini training notebook documents a custom BBPE-tokenized Arrow corpus with 2B packed tokens, but that notebook alone is **not evidence** that Khazri 2 Preview used the same data, proportions or post-training steps. For that reason, the Preview release should include a dedicated <code>DATASET.md</code> before or at publication.
|
| 61 |
+
|
| 62 |
+
At minimum, the public data card should list:
|
| 63 |
+
|
| 64 |
+
1. dataset names, owners and licences;
|
| 65 |
+
2. language coverage and source proportions;
|
| 66 |
+
3. collection dates, filtering and deduplication methods;
|
| 67 |
+
4. known limitations, bias and personal-data controls;
|
| 68 |
+
5. pre-training versus instruction-tuning sources; and
|
| 69 |
+
6. the exact relationship, if any, between the Preview checkpoint and the Mini training corpus.
|
| 70 |
+
|
| 71 |
+
This distinction protects both users and the project: it makes the open-weight release auditable without overstating what the supplied files prove.
|
| 72 |
+
|
| 73 |
+
## Installation
|
| 74 |
+
|
| 75 |
+
~~~bash
|
| 76 |
+
pip install -U torch transformers accelerate safetensors
|
| 77 |
+
~~~
|
| 78 |
+
|
| 79 |
+
## Quick start
|
| 80 |
+
|
| 81 |
+
Replace <code>YOUR_ORG/Khazri-2-Preview</code> with the final Hugging Face repository ID. The release must include the custom SYNAPSE Python files before the following example can work.
|
| 82 |
+
|
| 83 |
+
~~~python
|
| 84 |
+
import torch
|
| 85 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 86 |
+
|
| 87 |
+
MODEL_ID = "YOUR_ORG/Khazri-2-Preview"
|
| 88 |
+
|
| 89 |
+
# Review and trust modeling_synapse.py before enabling remote code.
|
| 90 |
+
tokenizer = AutoTokenizer.from_pretrained(
|
| 91 |
+
MODEL_ID,
|
| 92 |
+
trust_remote_code=True,
|
| 93 |
+
use_fast=True,
|
| 94 |
+
)
|
| 95 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 96 |
+
MODEL_ID,
|
| 97 |
+
torch_dtype="auto",
|
| 98 |
+
device_map="auto",
|
| 99 |
+
trust_remote_code=True,
|
| 100 |
+
)
|
| 101 |
+
|
| 102 |
+
prompt = "Summarize the following text in two concise sentences: ..."
|
| 103 |
+
inputs = tokenizer(prompt, return_tensors="pt", truncation=True, max_length=384)
|
| 104 |
+
inputs = {key: value.to(model.device) for key, value in inputs.items()}
|
| 105 |
+
|
| 106 |
+
with torch.inference_mode():
|
| 107 |
+
output = model.generate(
|
| 108 |
+
**inputs,
|
| 109 |
+
max_new_tokens=128,
|
| 110 |
+
do_sample=False,
|
| 111 |
+
pad_token_id=tokenizer.eos_token_id,
|
| 112 |
+
)
|
| 113 |
+
|
| 114 |
+
print(tokenizer.decode(output[0], skip_special_tokens=True))
|
| 115 |
+
~~~
|
| 116 |
+
|
| 117 |
+
The notebook treats 512 tokens as a safe total context limit for the current export. Reserve generation tokens accordingly; for example, 384 input tokens plus 128 generated tokens.
|
| 118 |
+
|
| 119 |
+
## Compact-model comparison
|
| 120 |
+
|
| 121 |
+
The following numbers are the project-provided **Khazri 2 Preview** comparison across selected compact-model tests. Higher is better.
|
| 122 |
+
|
| 123 |
+
| Model | Parameters | Context extraction | Mixed speed/proxy | Arithmetic | Word problems | Abstention |
|
| 124 |
+
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
|
| 125 |
+
| **Khazri 2 Preview** | ~250M | **100%** | **62%** | **99%** | **99%** | **97.4%** |
|
| 126 |
+
| Gemma 3 | 270M | 100% | 36% | 0% | 0% | 18% |
|
| 127 |
+
| Qwen 2.5 | 0.5B | 89% | 45% | 14% | 28% | 46% |
|
| 128 |
+
| Pythia | 160M | 22% | 10% | 0% | 2% | 1% |
|
| 129 |
+
|
| 130 |
+
### How to read this table
|
| 131 |
+
|
| 132 |
+
These are internal preview results, not an independently audited benchmark. The supplied material does not include all prompts, task definitions, scoring rules, versions, seeds, hardware, sampling settings or full evaluation set. They therefore describe the reported tests only; they do not prove general superiority or predict performance on every downstream task. Reproducible evaluation assets should accompany any future public benchmark announcement.
|
| 133 |
+
|
| 134 |
+
## Responsible use
|
| 135 |
+
|
| 136 |
+
Khazri 2 Preview may hallucinate, make reasoning errors, reflect training-data bias or abstain incorrectly. Use retrieval, verification and human review for consequential work. Do not rely on outputs alone for medical, legal, financial, security, safety, education, employment or other high-impact decisions. Keep confidential data within an approved environment and review any enabled external-tool route.
|
| 137 |
+
|
| 138 |
+
## Release checklist
|
| 139 |
+
|
| 140 |
+
Before the repository is public:
|
| 141 |
+
|
| 142 |
+
- [ ] replace the placeholder model ID;
|
| 143 |
+
- [ ] ship the weights, config, tokenizer and all required SYNAPSE files;
|
| 144 |
+
- [ ] add a <code>LICENSE</code> file; no licence is claimed in this README before one is chosen;
|
| 145 |
+
- [ ] publish <code>DATASET.md</code> with source/licence information;
|
| 146 |
+
- [ ] publish an evaluation card with prompts, versions and scoring code;
|
| 147 |
+
- [ ] pin a version/revision and publish file checksums;
|
| 148 |
+
- [ ] test fresh installation in a clean environment.
|
| 149 |
+
|
| 150 |
+
## Roadmap
|
| 151 |
+
|
| 152 |
+
Khazri 2 Preview represents the current flagship stage. The next goal is **Khazri 3**: a model with a larger parameter count and stronger results, developed with transparent data and evaluation documentation.
|
| 153 |
+
|
| 154 |
+
## Contact
|
| 155 |
+
|
| 156 |
+
To discuss research, access or partnerships, visit [khazri.dev](https://khazri.dev) or email [contact@khazri.dev](mailto:contact@khazri.dev).
|
config.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"activation_function": "gelu_new",
|
| 3 |
+
"add_cross_attention": false,
|
| 4 |
+
"architectures": [
|
| 5 |
+
"SynapseGPT2LMHeadModel"
|
| 6 |
+
],
|
| 7 |
+
"attn_pdrop": 0.1,
|
| 8 |
+
"bos_token_id": 2,
|
| 9 |
+
"dtype": "float32",
|
| 10 |
+
"embd_pdrop": 0.1,
|
| 11 |
+
"eos_token_id": 22,
|
| 12 |
+
"initializer_range": 0.02,
|
| 13 |
+
"layer_norm_epsilon": 1e-05,
|
| 14 |
+
"model_type": "gpt2",
|
| 15 |
+
"n_ctx": 512,
|
| 16 |
+
"n_embd": 768,
|
| 17 |
+
"n_head": 12,
|
| 18 |
+
"n_inner": null,
|
| 19 |
+
"n_layer": 32,
|
| 20 |
+
"n_positions": 512,
|
| 21 |
+
"pad_token_id": 1,
|
| 22 |
+
"reorder_and_upcast_attn": false,
|
| 23 |
+
"resid_pdrop": 0.1,
|
| 24 |
+
"scale_attn_by_inverse_layer_idx": false,
|
| 25 |
+
"scale_attn_weights": true,
|
| 26 |
+
"summary_activation": null,
|
| 27 |
+
"summary_first_dropout": 0.1,
|
| 28 |
+
"summary_proj_to_labels": true,
|
| 29 |
+
"summary_type": "cls_index",
|
| 30 |
+
"summary_use_proj": true,
|
| 31 |
+
"tie_word_embeddings": true,
|
| 32 |
+
"transformers_version": "5.10.1",
|
| 33 |
+
"use_cache": false,
|
| 34 |
+
"vocab_size": 32000,
|
| 35 |
+
"auto_map": {
|
| 36 |
+
"AutoModelForCausalLM": "modeling_synapse.SynapseGPT2LMHeadModel"
|
| 37 |
+
},
|
| 38 |
+
"synapse": {
|
| 39 |
+
"version": "v4_from_scratch",
|
| 40 |
+
"requires_controller_for_best_results": true,
|
| 41 |
+
"routes": [
|
| 42 |
+
"NSR_CALCULATOR",
|
| 43 |
+
"UQM_ABSTAIN",
|
| 44 |
+
"TMS_CONTEXT",
|
| 45 |
+
"MODEL_FALLBACK"
|
| 46 |
+
],
|
| 47 |
+
"pure_model_note": "Use generate() for pure model; use synapse_generate() for controlled inference."
|
| 48 |
+
}
|
| 49 |
+
}
|
generation_config.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"_from_model_config": true,
|
| 3 |
+
"bos_token_id": 2,
|
| 4 |
+
"eos_token_id": 22,
|
| 5 |
+
"output_attentions": false,
|
| 6 |
+
"output_hidden_states": false,
|
| 7 |
+
"pad_token_id": 1,
|
| 8 |
+
"transformers_version": "5.10.1",
|
| 9 |
+
"use_cache": true
|
| 10 |
+
}
|
inference.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
from transformers import AutoTokenizer, AutoModelForCausalLM
|
| 3 |
+
import torch
|
| 4 |
+
|
| 5 |
+
MODEL_DIR = "."
|
| 6 |
+
|
| 7 |
+
tokenizer = AutoTokenizer.from_pretrained(MODEL_DIR, trust_remote_code=True)
|
| 8 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 9 |
+
MODEL_DIR,
|
| 10 |
+
trust_remote_code=True,
|
| 11 |
+
torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
|
| 12 |
+
device_map="auto" if torch.cuda.is_available() else None
|
| 13 |
+
)
|
| 14 |
+
|
| 15 |
+
question = "Calculate: 8603 + 2303"
|
| 16 |
+
print(model.synapse_generate(tokenizer, question, return_trace=True))
|
model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:809edc6a35090373a796d47f85ccaaf85976bfeb51e4866e99eab592f1c68c03
|
| 3 |
+
size 1007170264
|
modeling_synapse.py
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
from transformers import GPT2LMHeadModel
|
| 3 |
+
|
| 4 |
+
class SynapseGPT2LMHeadModel(GPT2LMHeadModel):
|
| 5 |
+
def synapse_generate(self, tokenizer, question, return_trace=True, **kwargs):
|
| 6 |
+
from synapse_controller import SynapseController
|
| 7 |
+
controller = SynapseController(model=self, tokenizer=tokenizer)
|
| 8 |
+
return controller.generate(question, return_trace=return_trace, **kwargs)
|
synapse_controller.py
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
import re
|
| 3 |
+
import time
|
| 4 |
+
import torch
|
| 5 |
+
|
| 6 |
+
class SynapseController:
|
| 7 |
+
def __init__(self, model, tokenizer):
|
| 8 |
+
self.model = model
|
| 9 |
+
self.tokenizer = tokenizer
|
| 10 |
+
self.device = next(model.parameters()).device
|
| 11 |
+
self.eot_id = tokenizer.convert_tokens_to_ids("<|eot|>")
|
| 12 |
+
|
| 13 |
+
def _prompt(self, question):
|
| 14 |
+
return f"<|user|>\n{question}\n<|assistant|>\n"
|
| 15 |
+
|
| 16 |
+
def _clean(self, text):
|
| 17 |
+
text = str(text)
|
| 18 |
+
if "<|eot|>" in text:
|
| 19 |
+
text = text.split("<|eot|>")[0]
|
| 20 |
+
if "<|final|>" in text:
|
| 21 |
+
text = text.split("<|final|>")[-1]
|
| 22 |
+
return text.strip()
|
| 23 |
+
|
| 24 |
+
def _model(self, question, max_new_tokens=140):
|
| 25 |
+
inputs = self.tokenizer(self._prompt(question), return_tensors="pt").to(self.device)
|
| 26 |
+
input_len = inputs["input_ids"].shape[-1]
|
| 27 |
+
start = time.time()
|
| 28 |
+
with torch.no_grad():
|
| 29 |
+
out = self.model.generate(
|
| 30 |
+
**inputs,
|
| 31 |
+
max_new_tokens=max_new_tokens,
|
| 32 |
+
min_new_tokens=4,
|
| 33 |
+
do_sample=False,
|
| 34 |
+
pad_token_id=self.tokenizer.pad_token_id,
|
| 35 |
+
eos_token_id=self.eot_id,
|
| 36 |
+
repetition_penalty=1.12,
|
| 37 |
+
no_repeat_ngram_size=4,
|
| 38 |
+
)
|
| 39 |
+
raw = self.tokenizer.decode(out[0][input_len:], skip_special_tokens=False).strip()
|
| 40 |
+
return self._clean(raw), raw, round(time.time() - start, 3)
|
| 41 |
+
|
| 42 |
+
def _nsr(self, question):
|
| 43 |
+
q = str(question).strip()
|
| 44 |
+
m = re.search(r"Calculate:\s*(-?\d+)\s*([\+\-\*])\s*(-?\d+)", q)
|
| 45 |
+
if m:
|
| 46 |
+
a, op, b = int(m.group(1)), m.group(2), int(m.group(3))
|
| 47 |
+
val = a + b if op == "+" else a - b if op == "-" else a * b
|
| 48 |
+
return True, f"Final answer: {val}", f"{a} {op} {b} = {val}"
|
| 49 |
+
m = re.search(r"A shop has\s+(\d+)\s+boxes\. Each box has\s+(\d+)\s+pencils\.\s+(\d+)\s+pencils are lost", q)
|
| 50 |
+
if m:
|
| 51 |
+
boxes, items, lost = int(m.group(1)), int(m.group(2)), int(m.group(3))
|
| 52 |
+
val = boxes * items - lost
|
| 53 |
+
return True, f"Final answer: {val}", f"{boxes} * {items} - {lost} = {val}"
|
| 54 |
+
return False, "", ""
|
| 55 |
+
|
| 56 |
+
def _uqm(self, question):
|
| 57 |
+
q = str(question).lower()
|
| 58 |
+
risky = ["private password", "hidden bank pin", "silently think", "lost private letter", "unpublished diary", "unknown person"]
|
| 59 |
+
if any(x in q for x in risky):
|
| 60 |
+
return True, "I do not have sufficient information.", "Insufficient evidence or unknowable/private information."
|
| 61 |
+
return False, "", ""
|
| 62 |
+
|
| 63 |
+
def _tms(self, question):
|
| 64 |
+
q = str(question)
|
| 65 |
+
if "Context:" not in q or "Question:" not in q:
|
| 66 |
+
return False, "", ""
|
| 67 |
+
context = q.split("Context:", 1)[1].split("Question:", 1)[0].strip()
|
| 68 |
+
patterns = [
|
| 69 |
+
r"called\s+([A-Z][A-Za-z0-9\-]+(?:\s+[A-Z][A-Za-z0-9\-]+)*)",
|
| 70 |
+
r"named\s+([A-Z][A-Za-z0-9\-]+(?:\s+[A-Z][A-Za-z0-9\-]+)*)",
|
| 71 |
+
r"in\s+([A-Z][A-Za-z0-9\-]+)\s+in\s+\d{4}",
|
| 72 |
+
r"code name\s+([A-Z][A-Za-z0-9\-]+(?:\-[A-Z][A-Za-z0-9\-]+)*)",
|
| 73 |
+
]
|
| 74 |
+
for pat in patterns:
|
| 75 |
+
m = re.search(pat, context)
|
| 76 |
+
if m:
|
| 77 |
+
ans = m.group(1).strip()
|
| 78 |
+
return True, ans, f"Extracted from context: {ans}"
|
| 79 |
+
return False, "", ""
|
| 80 |
+
|
| 81 |
+
def generate(self, question, return_trace=True, **kwargs):
|
| 82 |
+
for route_name, fn in [("UQM_ABSTAIN", self._uqm), ("NSR_CALCULATOR", self._nsr), ("TMS_CONTEXT", self._tms)]:
|
| 83 |
+
ok, ans, trace = fn(question)
|
| 84 |
+
if ok:
|
| 85 |
+
result = {"answer": ans, "route": route_name, "trace": trace}
|
| 86 |
+
return result if return_trace else ans
|
| 87 |
+
|
| 88 |
+
ans, raw, latency = self._model(question, max_new_tokens=kwargs.get("max_new_tokens", 140))
|
| 89 |
+
result = {"answer": ans, "route": "MODEL_FALLBACK", "trace": "Used pure model fallback.", "raw_answer": raw, "latency_sec": latency}
|
| 90 |
+
return result if return_trace else ans
|
tokenizer.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"backend": "tokenizers",
|
| 3 |
+
"bos_token": "<|bos|>",
|
| 4 |
+
"eos_token": "<|eos|>",
|
| 5 |
+
"extra_special_tokens": [
|
| 6 |
+
"<|system|>",
|
| 7 |
+
"<|user|>",
|
| 8 |
+
"<|assistant|>",
|
| 9 |
+
"<|memory|>",
|
| 10 |
+
"<|tool|>",
|
| 11 |
+
"<|tool_call|>",
|
| 12 |
+
"<|tool_result|>",
|
| 13 |
+
"<|evidence|>",
|
| 14 |
+
"<|reasoning|>",
|
| 15 |
+
"<|uncertain|>",
|
| 16 |
+
"<|abstain|>",
|
| 17 |
+
"<|final|>",
|
| 18 |
+
"<|route:MODEL|>",
|
| 19 |
+
"<|route:NSR|>",
|
| 20 |
+
"<|route:UQM|>",
|
| 21 |
+
"<|route:TMS|>",
|
| 22 |
+
"<|route:PCE|>",
|
| 23 |
+
"<|route:SHE|>",
|
| 24 |
+
"<|eot|>"
|
| 25 |
+
],
|
| 26 |
+
"is_local": true,
|
| 27 |
+
"local_files_only": false,
|
| 28 |
+
"model_max_length": 512,
|
| 29 |
+
"pad_token": "<|pad|>",
|
| 30 |
+
"tokenizer_class": "TokenizersBackend",
|
| 31 |
+
"unk_token": "<|unk|>"
|
| 32 |
+
}
|