@delali/narsil 0.1.11 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -3
- package/dist/{chunk-Q4OVNESD.mjs → chunk-HMO6OMZ3.mjs} +1766 -1131
- package/dist/{chunk-CU6BVZEU.mjs → chunk-MEW7HD75.mjs} +87 -155
- package/dist/{config-DX--2Owg.d.ts → config-CojEPOgS.d.ts} +10 -1
- package/dist/{direct-executor-6FOKJKLD.mjs → direct-executor-E52FFGDE.mjs} +1 -1
- package/dist/distribution/coordinator/etcd.d.ts +2 -2
- package/dist/distribution/coordinator/in-memory.d.ts +2 -2
- package/dist/distribution.d.ts +4 -4
- package/dist/distribution.mjs +4 -3
- package/dist/index.browser.mjs +1868 -1301
- package/dist/index.d.ts +3 -3
- package/dist/index.mjs +2 -2
- package/dist/{narsil-B3jKyXCr.d.ts → narsil-D-84Nvm4.d.ts} +2 -2
- package/dist/persistence/durability/checkpoint-worker.d.ts +2 -0
- package/dist/persistence/durability/checkpoint-worker.mjs +2 -2
- package/dist/{schema-C3VhNvfw.d.ts → schema-DCgkO1j4.d.ts} +5 -0
- package/dist/server.d.ts +4 -3
- package/dist/server.mjs +1 -0
- package/dist/{types-CTVVm4GG.d.ts → types-DHX6zGeD.d.ts} +1 -1
- package/dist/workers/entry.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,7 +12,9 @@ Distributed search, reforged.
|
|
|
12
12
|
|
|
13
13
|
Narsil is a distributed search engine with full-text, vector, hybrid, and geosearch. One codebase runs in two contexts: embedded in your application process, where queries answer without a network hop, and as a standalone search server with a REST API, a write-ahead log, and bulk NDJSON ingest. Both contexts run the same engine and store indexes in the same cross-language binary format (.nrsl), so an index built in one loads in the other.
|
|
14
14
|
|
|
15
|
-
The engine partitions large indexes across workers and merges partition results into a single ranked answer. Its BM25 ranking matches the Anserini reference within 0.005 nDCG@10 on the BEIR datasets
|
|
15
|
+
The engine partitions large indexes across workers and merges partition results into a single ranked answer. Its BM25 ranking matches the Anserini reference within 0.005 nDCG@10 on the BEIR datasets. On BEIR SciFact it ranks level with Elasticsearch and OpenSearch at 0.678 nDCG@10 and answers 1,020 keyword queries per second, about a quarter more than either ([benchmarks](https://github.com/assetcorp/narsil/blob/main/BENCHMARKS.md)). This TypeScript package is the reference implementation of the cross-language `.nrsl` format, and a second-language port in Go or Rust is the headline item on the [roadmap](https://github.com/assetcorp/narsil/blob/main/ROADMAP.md).
|
|
16
|
+
|
|
17
|
+
Try it in your browser at [narsil.sondelali.com/demo](https://narsil.sondelali.com/demo).
|
|
16
18
|
|
|
17
19
|
> *narsil* is the sword of Elendil in Tolkien's Lord of the Rings, shattered into shards and later reforged. The name maps to the architecture: data shatters into partitions, each shard is independently persisted, and every query reforges them into a unified result.
|
|
18
20
|
|
|
@@ -196,6 +198,7 @@ await narsil.createIndex('articles', {
|
|
|
196
198
|
| `stopWords` | `Set<string> \| (defaults: Set<string>) => Set<string>` | Replaces or transforms the language module's stop word set. |
|
|
197
199
|
| `tokenizer` | `CustomTokenizer` | Replaces the built-in tokenizer with your own `tokenize(text)` implementation. |
|
|
198
200
|
| `trackPositions` | `boolean` | Stores token positions for highlighting. The default is `true`. |
|
|
201
|
+
| `surfaceForms` | `boolean` | Records the original spellings of stemmed words for suggestions and prefix completions. The default is `false`. See [Suggestions](#suggestions). |
|
|
199
202
|
| `vectorPromotion` | `VectorIndexConfig` | Tunes the HNSW promotion threshold, graph parameters, and quantization. See [Vector search](#vector-search). |
|
|
200
203
|
| `strict` | `boolean` | Rejects documents that carry fields missing from the schema. |
|
|
201
204
|
| `embedding` | `EmbeddingFieldConfig` | Maps text fields to vector fields for auto-embedding. See [Embedding adapters](#embedding-adapters). |
|
|
@@ -314,6 +317,19 @@ const results = await narsil.query('products', {
|
|
|
314
317
|
})
|
|
315
318
|
```
|
|
316
319
|
|
|
320
|
+
### Search as you type
|
|
321
|
+
|
|
322
|
+
`prefix: true` treats the last word of the query as an unfinished word, so `secur` matches documents containing `security`. Earlier words must match fully, and `tolerance` keeps applying to them while the unfinished word is completed instead of typo-corrected. Completions score against a shared document frequency and rank below full-word matches, so a document containing the exact typed word comes first. The option is off by default; turn it on for queries fired on every keystroke.
|
|
323
|
+
|
|
324
|
+
Completions match against the term dictionary, which stores stemmed tokens, so a typed word that runs past the end of a stem stops matching: `security` is indexed as `secur`, and the query `securi` finds nothing. Create the index with `surfaceForms: true` to match completions against the original spellings instead; the same setting gives [suggestions](#suggestions) their display words.
|
|
325
|
+
|
|
326
|
+
```ts
|
|
327
|
+
const results = await narsil.query('products', {
|
|
328
|
+
term: 'mechanical keyb',
|
|
329
|
+
prefix: true,
|
|
330
|
+
})
|
|
331
|
+
```
|
|
332
|
+
|
|
317
333
|
### Score and coverage thresholds
|
|
318
334
|
|
|
319
335
|
`minScore` drops hits scoring below a floor. `termMatch` sets how many query terms a document must match: `'any'` (the default) accepts one term, `'all'` requires every term, and a number requires at least that many terms.
|
|
@@ -476,11 +492,16 @@ const { count, elapsed } = await narsil.preflight('products', { term: 'keyboard'
|
|
|
476
492
|
|
|
477
493
|
### Suggestions
|
|
478
494
|
|
|
479
|
-
`suggest(indexName, params)` returns autocomplete candidates
|
|
495
|
+
`suggest(indexName, params)` returns autocomplete candidates. It tokenizes the input, takes the last word as the prefix, and ranks completions by the number of documents they match. By default the candidates are the stemmed tokens the index stores, so a catalogue containing "mechanical" suggests the stem `mechan`. Create the index with `surfaceForms: true` to suggest the words as they appear in your documents; the engine then records the original spelling of every word the stemmer changed and suggests `mechanical` instead.
|
|
480
496
|
|
|
481
497
|
```ts
|
|
498
|
+
await narsil.createIndex('products', {
|
|
499
|
+
schema: { title: 'string', description: 'string' },
|
|
500
|
+
surfaceForms: true,
|
|
501
|
+
})
|
|
502
|
+
|
|
482
503
|
const suggestions = await narsil.suggest('products', { prefix: 'mech', limit: 5 })
|
|
483
|
-
// suggestions.terms => [{ term: '
|
|
504
|
+
// suggestions.terms => [{ term: 'mechanical', documentFrequency: 12 }, ...]
|
|
484
505
|
```
|
|
485
506
|
|
|
486
507
|
## Vector search
|