Anthology Search

A highly extensible/customizable search engine, written in Typescript.
Stand-alone or embeddable.
$ bun serve
# "Server running at http://0.0.0.0:8080/..."

$ curl \
    -X POST \
    -H "Content-Type: application/json" \
    --data '{"id: "1", "content": "Hello, world!"}' \
    http://0.0.0.0:8080/documents
# {"success":true,"id":"1"}

$ curl \
    -X GET \
    'http://0.0.0.0:8080/search/basic?q=hello'
# {"success": true, "query": "hello", "results": [{"id": "1", "locations": [{"originalWord": "Hello,", "location": 0}], "score": 0.46153846153846156, "docLength": 13}]}
          

As Stand-Alone HTTP Service...

Anthology ships with a standalone RESTful HTTP service that speaks JSON. It ships with everything you need to run at all scales:

  • Purely in-memory (great for running tests)
  • Lightweight JSON (perfect for development purposes)
  • (Planned for v0.2.0) SQLite-backed (for small websites)
  • (Planned for v0.3.0) Filesystem-backed (for large corpuses)

Customizing the configuration of the server is clear, well-documented, & easy.

And it ships with an OpenAPI schema, so creating a custom client for your language/toolchain is a breeze.

...Or Embeddable In Your Codebase

Anthology can also be embedded in your existing Typescript project. It can scale all the way down to an in-page/in-memory engine; or all the way up to thousands of documents in your backend service.

It's built to be modular/customizable. If there's something that doesn't suit your needs, you should be able to easily swap it out.

And it's extensible. Should you need to go custom, the primitives are there to make building whatever you need possible (and hopefully easy).

const engine = new SearchEngine({
  index: new InMemoryIndex(),
  tokenizer: new SimpleTokenizer(),
  preprocessor: new Preprocessor()
    .register(new HTMLPreprocessor())
    .register(new MarkdownPreprocessor())
    .register(new PDFPreprocessor()),
});

await engine.addDocument({
  id: "page-1",
  content: "

Hello world

", contentType: "text/html", }); const results = await engine.search("Hello"); for (let res of results) { console.log(`* ${res.id} (Score: ${res.score})`); }