|
2 | 2 |
|
3 | 3 | [](https://github.com/preciz/chunx/actions/workflows/test.yml) |
4 | 4 |
|
5 | | -Chunx is an Elixir library for splitting text into meaningful chunks using various strategies. It's particularly useful for processing large texts for LLMs, semantic search, and other NLP tasks. |
6 | | - |
7 | | -## Credit |
8 | | - |
9 | | -This library is based on [chonkie-ai/chonkie](https://github.com/chonkie-ai/chonkie) |
10 | | - |
11 | | -## Features |
12 | | - |
13 | | -- Multiple chunking strategies: |
14 | | - - Token-based chunking |
15 | | - - Word-based chunking |
16 | | - - Sentence-based chunking |
17 | | - - Semantic chunking with embeddings |
18 | | - - Recursive chunking using structural boundaries |
19 | | - |
20 | | -- Configurable options for each strategy |
21 | | -- Support for overlapping chunks |
22 | | -- Token count tracking |
23 | | -- Embedding support |
| 5 | +Chunx splits text by tokens, words, sentences, document structure, or semantic |
| 6 | +similarity. It is an Elixir implementation inspired by |
| 7 | +[Chonkie](https://github.com/chonkie-ai/chonkie). |
24 | 8 |
|
25 | 9 | ## Installation |
26 | 10 |
|
27 | | -Add `chunx` to your list of dependencies in `mix.exs`: |
| 11 | +Add Chunx to `mix.exs`: |
28 | 12 |
|
29 | 13 | ```elixir |
30 | 14 | def deps do |
|
36 | 20 |
|
37 | 21 | ## Usage |
38 | 22 |
|
39 | | -### Token-based Chunking |
40 | | - |
41 | | -```elixir |
42 | | -{:ok, tokenizer} = Tokenizers.Tokenizer.from_pretrained("gpt2") |
43 | | -{:ok, chunks} = Chunx.Chunker.Token.chunk("Your text here", tokenizer, chunk_size: 512) |
44 | | -``` |
45 | | - |
46 | | -### Word-based Chunking |
| 23 | +All chunkers require a tokenizer. They accept a `Tokenizers.Tokenizer` or a |
| 24 | +custom adapter implementing the `Chunx.Tokenizer` behaviour. |
47 | 25 |
|
48 | 26 | ```elixir |
49 | | -{:ok, tokenizer} = Tokenizers.Tokenizer.from_pretrained("gpt2") |
50 | | -{:ok, chunks} = Chunx.Chunker.Word.chunk("Your text here", tokenizer, chunk_size: 512) |
51 | | -``` |
52 | | - |
53 | | -### Sentence-based Chunking |
| 27 | +alias Chunx.Chunker.Token |
54 | 28 |
|
55 | | -```elixir |
56 | 29 | {:ok, tokenizer} = Tokenizers.Tokenizer.from_pretrained("gpt2") |
57 | | -{:ok, chunks} = Chunx.Chunker.Sentence.chunk("Your text here", tokenizer) |
| 30 | +{:ok, chunks} = Token.chunk("Text to split", tokenizer, chunk_size: 128) |
58 | 31 | ``` |
59 | 32 |
|
60 | | -### Semantic Chunking |
| 33 | +Each returned chunk contains its text, half-open byte offsets into the original |
| 34 | +text, and its content-token count. Sentence and Semantic return |
| 35 | +`Chunx.SentenceChunk` structs; the other chunkers return `Chunx.Chunk` structs. |
61 | 36 |
|
62 | | -```elixir |
63 | | -{:ok, tokenizer} = Tokenizers.Tokenizer.from_pretrained("gpt2") |
| 37 | +### Chunkers |
64 | 38 |
|
65 | | -# The embedding function must return a list of Nx.Tensor.t() |
66 | | -embedding_fn = fn texts -> |
67 | | - # Your embedding function here |
68 | | -end |
| 39 | +| Module | Splitting unit | Overlap | |
| 40 | +| --- | --- | --- | |
| 41 | +| `Chunx.Chunker.Token` | Token offsets | Token count or fraction | |
| 42 | +| `Chunx.Chunker.Word` | Whole words | Token count or fraction | |
| 43 | +| `Chunx.Chunker.Sentence` | Whole sentences | Whole sentences within a token budget | |
| 44 | +| `Chunx.Chunker.Recursive` | Configured structural levels, then tokens | None | |
| 45 | +| `Chunx.Chunker.Semantic` | Sentence-embedding similarity | None | |
69 | 46 |
|
70 | | -{:ok, chunks} = Chunx.Chunker.Semantic.chunk("Your text here", tokenizer, embedding_fn) |
71 | | -``` |
| 47 | +See the [API documentation](https://hexdocs.pm/chunx/) for each module's options |
| 48 | +and size-limit exceptions. |
72 | 49 |
|
73 | | -### Recursive Chunking |
| 50 | +Semantic chunking also requires a function that returns one `Nx.Tensor` for |
| 51 | +each input string: |
74 | 52 |
|
75 | 53 | ```elixir |
76 | | -{:ok, tokenizer} = Tokenizers.Tokenizer.from_pretrained("gpt2") |
77 | | -{:ok, chunks} = Chunx.Chunker.Recursive.chunk("Your text here", tokenizer) |
78 | | -``` |
79 | | - |
80 | | -Recursive chunking tries paragraphs, sentences, punctuation, whitespace, and |
81 | | -finally token boundaries until every chunk fits within the configured size. |
| 54 | +alias Chunx.Chunker.Semantic |
82 | 55 |
|
83 | | -## Configuration |
| 56 | +embedding_fun = &MyApp.Embeddings.embed/1 |
84 | 57 |
|
85 | | -Each chunking strategy accepts various options to customize the chunking behavior: |
86 | | - |
87 | | -- `chunk_size`: Maximum number of content tokens per chunk |
88 | | -- `chunk_overlap`: Number or proportion of content tokens shared by consecutive chunks |
89 | | -- `min_sentences_per_chunk`: Minimum number of sentences per sentence-based chunk |
90 | | -- `min_sentences`: Minimum number of sentences per semantic chunk |
91 | | -- `threshold`: Similarity threshold for semantic chunking |
92 | | -- And more... |
93 | | - |
94 | | -See the documentation for each chunker module for detailed configuration options. |
| 58 | +{:ok, chunks} = |
| 59 | + Semantic.chunk("Text to split", tokenizer, embedding_fun, |
| 60 | + chunk_size: 128, |
| 61 | + threshold: :auto |
| 62 | + ) |
| 63 | +``` |
95 | 64 |
|
96 | 65 | ## Testing |
97 | 66 |
|
98 | | -```elixir |
99 | | -# Run the test suite |
| 67 | +Run the regular suite: |
| 68 | + |
| 69 | +```bash |
100 | 70 | mix test |
101 | 71 | ``` |
102 | 72 |
|
103 | | -Real-model embedding integration tests are excluded by default because they |
104 | | -download and run a Hugging Face model. Enable them explicitly with: |
| 73 | +Embedding integration tests use |
| 74 | +`sentence-transformers/all-MiniLM-L6-v2`. They download and run the model, so |
| 75 | +they are excluded by default: |
105 | 76 |
|
106 | 77 | ```bash |
107 | | -mix test --include integration |
| 78 | +mix test --only integration |
108 | 79 | ``` |
109 | 80 |
|
110 | | -To run only the integration tests, use `mix test --only integration`. |
111 | | - |
112 | | -The default model is `sentence-transformers/all-MiniLM-L6-v2`. Override it with |
113 | | -`CHUNX_EMBEDDING_MODEL`, provided the model is supported by Bumblebee's text |
114 | | -embedding serving and `Tokenizers.Tokenizer.from_pretrained/1`. |
| 81 | +Use `mix test --include integration` to run both suites together. |
115 | 82 |
|
116 | 83 | ## License |
117 | 84 |
|
118 | | -[MIT License](LICENSE) |
| 85 | +[MIT](LICENSE) |
0 commit comments