use serde_json::Value;
use super::pipeline::PreTokenizer;
use super::spec::{PreTokStage, SplitBehavior, SplitPattern};
use crate::core::tokenizer::{TokenizerError, GPT2_PATTERN};
pub(super) fn gpt2_regex() -> Result<super::stage::SplitMatcher, TokenizerError> {
super::stage::SplitMatcher::compile(GPT2_PATTERN)
}
pub(super) fn whitespace_regex() -> Result<super::stage::SplitMatcher, TokenizerError> {
super::stage::SplitMatcher::compile(r"\w+|[^\w\s]+")
}
pub(crate) fn parse(pre: Option<&Value>) -> Result<Option<PreTokenizer>, TokenizerError> {
let Some(pre) = pre else {
return Ok(None);
};
let mut stages = Vec::new();
fn walk(v: &Value, stages: &mut Vec<PreTokStage>) {
match v.get("type").and_then(Value::as_str) {
Some("Sequence") => {
if let Some(list) = v.get("pretokenizers").and_then(Value::as_array) {
for item in list {
walk(item, stages);
}
}
}
Some("ByteLevel") => stages.push(PreTokStage::ByteLevel {
use_regex: v.get("use_regex").and_then(Value::as_bool).unwrap_or(true),
add_prefix_space: v.get("add_prefix_space").and_then(Value::as_bool) == Some(true),
}),
Some("Split") => {
let pat = v.get("pattern").and_then(|p| {
p.get("Regex")
.and_then(Value::as_str)
.map(|s| SplitPattern::Regex(s.to_string()))
.or_else(|| {
p.get("String")
.and_then(Value::as_str)
.map(|s| SplitPattern::Literal(s.to_string()))
})
});
if let Some(pat) = pat {
stages.push(PreTokStage::Split {
pattern: pat,
behavior: SplitBehavior::parse(v.get("behavior").and_then(Value::as_str)),
invert: v.get("invert").and_then(Value::as_bool).unwrap_or(false),
});
}
}
Some("Digits") => stages.push(PreTokStage::Digits {
individual: v
.get("individual_digits")
.and_then(Value::as_bool)
.unwrap_or(false),
}),
Some("Punctuation") => stages.push(PreTokStage::Punctuation {
behavior: SplitBehavior::parse(v.get("behavior").and_then(Value::as_str)),
}),
Some("WhitespaceSplit") => stages.push(PreTokStage::WhitespaceSplit),
Some("Whitespace") => stages.push(PreTokStage::Whitespace),
_ => {}
}
}
walk(pre, &mut stages);
if stages.is_empty() {
return Ok(None);
}
Ok(Some(PreTokenizer::new(stages)?))
}