Skip to content

Commit 8a9a3ee

Browse files
save
1 parent dcba4fc commit 8a9a3ee

5 files changed

Lines changed: 170 additions & 39 deletions

File tree

Cargo.lock

Lines changed: 79 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ name = "rusty_tokey"
99
crate-type = ["cdylib"]
1010

1111
[dependencies]
12+
fancy-regex = "0.14.0"
1213
once_cell = "1.21.3"
1314
rand = "0.9.0"
15+
rayon = "1.10.0"
1416
regex = "1.11.1"
1517

1618
[dependencies.pyo3]

python/rusty_tokey/py.typed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
stub_only

python/rusty_tokey/rlly_serious.py

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
import pstats
88
from collections import Counter
99
import heapq
10-
from rusty_tokey import rusty_merge
11-
from rusty_tokey import rusty_pre_tok
10+
# from rusty_tokey import rusty_merge
11+
from rusty_tokey import rusty_full_merge
12+
# from rusty_tokey import rusty_pre_tok
1213

1314

1415
PAT = r"""'(?:[sdmt]|ll|ve|re)| ?\p{L}+| ?\p{N}+| ?[^\s\p{L}\p{N}]+|\s+(?!\S)|\s+"""
@@ -73,23 +74,23 @@ def pre_tokenize_chunk(input_path: str, start: int, end: int, pattern: re.Patter
7374
store[res_bytes] += 1
7475
return store
7576

76-
def rusty_pre_tokenize_chunk(input_path: str, start: int, end: int, special_tokens: list[str]) -> dict[list[]]:
77-
with open(input_path, "rb") as f:
78-
f.seek(start)
79-
chunk = f.read(end - start).decode("utf-8", errors="ignore")
77+
# def rusty_pre_tokenize_chunk(input_path: str, start: int, end: int, pattern: re.Pattern[str], special_tokens: list[str]) -> dict[list[list[int]],int]:
78+
# with open(input_path, "rb") as f:
79+
# f.seek(start)
80+
# chunk = f.read(end - start).decode("utf-8", errors="ignore")
8081

81-
return rusty_pre_tok(chunk,special_tokens)
82+
# result = rusty_pre_tok(chunk,special_tokens)
8283

83-
# sub_chunks = pattern.split(chunk)
84-
# # run tokenization for each of the sub_chunks.
85-
# iterators = [PAT_RE.finditer(sub_chunk) for sub_chunk in sub_chunks]
86-
# flattened_iterators = itertools.chain(*iterators)
87-
# store = Counter()
88-
# for match in flattened_iterators:
89-
# res = match.group()
90-
# res_bytes = tuple(bytes([c]) for c in res.encode("utf-8"))
91-
# store[res_bytes] += 1
92-
# return store
84+
# sub_chunks = pattern.split(chunk)
85+
# # run tokenization for each of the sub_chunks.
86+
# iterators = [PAT_RE.finditer(sub_chunk) for sub_chunk in sub_chunks]
87+
# flattened_iterators = itertools.chain(*iterators)
88+
# store = Counter()
89+
# for match in flattened_iterators:
90+
# res = match.group()
91+
# res_bytes = tuple(bytes([c]) for c in res.encode("utf-8"))
92+
# store[res_bytes] += 1
93+
# return store
9394

9495

9596
def get_all_simple_pairs(
@@ -192,19 +193,22 @@ def train_bpe(
192193
with open(input_path, "rb") as f:
193194
# find the chunk boundaries
194195
boundaries = find_chunk_boundaries(f, 16, "<|endoftext|>".encode("utf-8"))
195-
num_workers = min(mp.cpu_count(), len(boundaries) - 1)
196-
with mp.Pool(processes=num_workers) as pool:
197-
results = pool.starmap(
198-
rusty_pre_tokenize_chunk,
199-
[(input_path, start, end, special_tokens) for start, end in zip(boundaries[:-1], boundaries[1:])],
200-
)
196+
# num_workers = min(mp.cpu_count(), len(boundaries) - 1)
197+
# with mp.Pool(processes=num_workers) as pool:
198+
# results = pool.starmap(
199+
# rusty_pre_tokenize_chunk,
200+
# [(input_path, start, end, pattern, special_tokens) for start, end in zip(boundaries[:-1], boundaries[1:])],
201+
# )
201202
# results = [pre_tokenize_chunk(chunk) for chunk in chunks]
202-
combined = Counter()
203+
# combined = Counter()
204+
205+
# for d in results:
206+
# combined.update(d)
203207

204-
for d in results:
205-
combined.update(d)
208+
# max_pairs = rusty_merge(combined, stopping_condition)
206209

207-
max_pairs = rusty_merge(combined, stopping_condition)
210+
max_pairs = rusty_full_merge(input_path, boundaries, special_tokens, vocab_size)
211+
# print('max_pairs', max_pairs)
208212
vocab: dict[int, bytes] = {}
209213
# single-bytes
210214
for i in range(0, 256):

src/lib.rs

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
use pyo3::prelude::*;
22
use std::collections::{HashMap, HashSet};
3-
use std::fmt::Error;
43
use std::hash::Hash;
54
use std::collections::hash_map::Entry;
6-
use std::num::ParseIntError;
7-
use regex::Regex;
5+
use fancy_regex::Regex;
86
use once_cell::sync::Lazy;
97
use std::fs::File;
10-
use std::io::{self, Read, BufReader};
8+
use std::io::{self, Read, Seek, SeekFrom};
9+
use rayon::prelude::*;
1110

1211
const PAT: &str = r"'(?:[sdmt]|ll|ve|re)| ?\p{L}+| ?\p{N}+| ?[^\s\p{L}\p{N}]+|\s+(?!\S)|\s+";
1312

@@ -83,7 +82,7 @@ fn get_pairs(
8382
#[pyfunction]
8483
fn rusty_merge(mut tok_to_count: HashMap<Vec<Vec<u8>>, usize>, max: usize) -> PyResult<Vec<(Vec<u8>, Vec<u8>)>> {
8584
println!("we are inside rusty_merge");
86-
println!("{:?}", tok_to_count);
85+
// println!("{:?}", tok_to_count);
8786
let mut max_pairs = vec![(vec![0; 0], vec![0; 0]); max];
8887
let (mut pair_to_count, mut pair_to_toks) = get_pairs(&tok_to_count);
8988
// TODO: maintain heap of max-pairs, instead of finding the max_pair on every loop.
@@ -194,18 +193,26 @@ fn rusty_merge(mut tok_to_count: HashMap<Vec<Vec<u8>>, usize>, max: usize) -> Py
194193

195194

196195
};
197-
println!("{:?}", max_pairs);
196+
// println!("{:?}", max_pairs);
198197
Ok(max_pairs)
199198
}
200199

200+
#[pyfunction]
201+
fn rusty_full_merge(filepath: &str, boundaries: Vec<u64>, special_tokens:Vec<String>, max: usize) -> PyResult<Vec<(Vec<u8>, Vec<u8>)>> {
202+
let tok_to_count = rusty_get_pre_toks(filepath, boundaries, special_tokens);
203+
// println!("tok_to_count {:?}", tok_to_count);
204+
return rusty_merge(tok_to_count.unwrap(), max)
205+
}
206+
207+
201208
#[pyfunction]
202209
fn rusty_pre_tok(chunk:&str, special_tokens:Vec<String>) -> HashMap<Vec<Vec<u8>>, usize> {
203210
let mut tok_to_count: HashMap<Vec<Vec<u8>>, usize> = HashMap::new();
204211
let pat_special_toks = special_tokens.iter().map(|x: &String| regex::escape(x)).collect::<Vec<String>>().join("|");
205212
let re_special_toks: Regex = Regex::new(&pat_special_toks).unwrap();
206213

207-
for regex_match in re_special_toks.split(chunk).flat_map(|subchunk| RE.find_iter(subchunk)) {
208-
let key: Vec<Vec<u8>> = regex_match.as_str().chars().map(|c| c.to_string().as_bytes().to_vec()).collect();
214+
for regex_match in re_special_toks.split(chunk).flat_map(|subchunk| RE.find_iter(subchunk.unwrap())) {
215+
let key: Vec<Vec<u8>> = regex_match.unwrap().as_str().chars().map(|c| c.to_string().as_bytes().to_vec()).collect();
209216

210217
// += 1
211218
*tok_to_count.entry(key).or_insert(1) += 1;
@@ -215,18 +222,56 @@ fn rusty_pre_tok(chunk:&str, special_tokens:Vec<String>) -> HashMap<Vec<Vec<u8>>
215222
tok_to_count
216223
}
217224

225+
fn rusty_get_chunk_pre_toks(filepath: &str, start: u64, end: u64, special_tokens:Vec<String>) -> io::Result<HashMap<Vec<Vec<u8>>, usize>> {
226+
let mut tok_to_count: HashMap<Vec<Vec<u8>>, usize> = HashMap::new();
227+
let pat_special_toks = special_tokens.iter().map(|x: &String| regex::escape(x)).collect::<Vec<String>>().join("|");
228+
let re_special_toks: Regex = Regex::new(&pat_special_toks).unwrap();
229+
let mut file = File::open(filepath)?;
230+
file.seek(SeekFrom::Start(start))?;
231+
let mut buffer = vec![0u8; (end - start) as usize];
232+
let bytes_read = file.read(&mut buffer)?;
233+
let chunk = String::from_utf8_lossy(&buffer[..bytes_read]);
234+
println!("------ chunk ------");
235+
println!("{}", chunk);
236+
println!("------ chunk ------");
237+
for regex_match in re_special_toks.split(&chunk).flat_map(|subchunk| RE.find_iter(subchunk.unwrap())) {
238+
println!("match {}", regex_match.clone().unwrap().as_str());
239+
let key: Vec<Vec<u8>> = regex_match.unwrap().as_str().chars().map(|c| c.to_string().as_bytes().to_vec()).collect();
240+
241+
// += 1
242+
*tok_to_count.entry(key).or_insert(1) += 1;
243+
244+
}
245+
Ok(tok_to_count)
246+
}
247+
218248
#[pyfunction]
219-
fn rusty_get_pre_toks(filepath: String) -> Result<(), std::io::Error>{
220-
let file = File::open(filepath)?;
221-
222-
Ok(())
249+
fn rusty_get_pre_toks(filepath: &str, boundaries: Vec<u64>, special_tokens:Vec<String>) -> io::Result<HashMap<Vec<Vec<u8>>, usize>> {
250+
251+
// let pat_special_toks = special_tokens.iter().map(|x: &String| regex::escape(x)).collect::<Vec<String>>().join("|");
252+
let r: Vec<(u64, u64)> = boundaries.windows(2).map(|x| (x[0],x[1])).collect();
253+
let map = r
254+
.par_iter()
255+
.map(|(start,end)| {
256+
rusty_get_chunk_pre_toks(filepath,*start,*end, special_tokens.clone())
257+
})
258+
.collect::<Vec<_>>()
259+
.into_iter()
260+
.fold(HashMap::new(), |mut acc, chunk_map| {
261+
for (key, value) in chunk_map.unwrap() {
262+
*acc.entry(key).or_insert(0) += value;
263+
}
264+
acc
265+
});
266+
Ok(map)
223267
}
224268

225269
/// A Python module implemented in Rust.
226270
#[pymodule]
227271
fn rusty_tokey(m: &Bound<'_, PyModule>) -> PyResult<()> {
228272
m.add_function(wrap_pyfunction!(sum_as_string, m)?)?;
229273
m.add_function(wrap_pyfunction!(rusty_merge, m)?)?;
274+
m.add_function(wrap_pyfunction!(rusty_full_merge, m)?)?;
230275
m.add_function(wrap_pyfunction!(rusty_pre_tok, m)?)?;
231276
m.add_function(wrap_pyfunction!(rusty_get_pre_toks, m)?)?;
232277
m.add_function(wrap_pyfunction!(simpl, m)?)?;

0 commit comments

Comments
 (0)