{"id":15765840,"url":"https://github.com/maxleiter/client-vector-search","last_synced_at":"2026-01-20T13:01:25.582Z","repository":{"id":248177537,"uuid":"793298390","full_name":"MaxLeiter/client-vector-search","owner":"MaxLeiter","description":null,"archived":false,"fork":false,"pushed_at":"2024-04-29T03:52:14.000Z","size":469,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-22T07:36:06.604Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MaxLeiter.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-04-29T00:12:46.000Z","updated_at":"2024-07-12T23:29:22.000Z","dependencies_parsed_at":"2024-07-12T22:43:00.957Z","dependency_job_id":null,"html_url":"https://github.com/MaxLeiter/client-vector-search","commit_stats":null,"previous_names":["maxleiter/client-vector-search"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/MaxLeiter/client-vector-search","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxLeiter%2Fclient-vector-search","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxLeiter%2Fclient-vector-search/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxLeiter%2Fclient-vector-search/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxLeiter%2Fclient-vector-search/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MaxLeiter","download_url":"https://codeload.github.com/MaxLeiter/client-vector-search/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxLeiter%2Fclient-vector-search/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28603402,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-20T12:01:53.233Z","status":"ssl_error","status_checked_at":"2026-01-20T12:01:46.545Z","response_time":117,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-04T13:00:34.019Z","updated_at":"2026-01-20T13:01:25.561Z","avatar_url":"https://github.com/MaxLeiter.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# client-vector-search\n\nA client side vector search library that can embed, search, and cache. Works on the browser and server side.\n\nIt outperforms OpenAI's text-embedding-ada-002 and is way faster than Pinecone and other VectorDBs.\n\nI'm the founder of [searchbase.app](https://searchbase.app) and we needed this for our product and customers. We'll be using this library in production. You can be sure it'll be maintained and improved.\n\n- Embed documents using transformers by default: gte-small (~30mb).\n- Calculate cosine similarity between embeddings.\n- Create an index and search on the client side\n- Cache vectors with browser caching support.\n\nLots of improvements are coming!\n\n## Roadmap\n\nOur goal is to build a super simple, fast vector search that works with couple hundred to thousands vectors. ~1k vectors per user covers 99% of the use cases.\n\nWe'll initially keep things super simple and sub 100ms\n\n### TODOs\n- [ ] add HNSW index that works on node and browser env, don't rely on hnsw binder libs\n- [ ] add a proper testing suite and ci/cd for the lib\n  - [ ] simple health tests\n    - [ ] mock the @xenova/transformers for jest, it's not happy with it\n  - [ ] performance tests, recall, memory usage, cpu usage etc.\n\n\n## Installation\n\n```bash\nnpm i client-vector-search\n```\n\n\n## Quickstart\n\nThis library provides a plug-and-play solution for embedding and vector search. It's designed to be easy to use, efficient, and versatile. Here's a quick start guide:\n\n\n```ts\n  import { getEmbedding, EmbeddingIndex } from 'client-vector-search';\n\n  // getEmbedding is an async function, so you need to use 'await' or '.then()' to get the result\n  const embedding = await getEmbedding(\"Apple\"); // Returns embedding as number[]\n\n  // Each object should have an 'embedding' property of type number[]\n  const initialObjects = [\n  { id: 1, name: \"Apple\", embedding: embedding },\n  { id: 2, name: \"Banana\", embedding: await getEmbedding(\"Banana\") },\n  { id: 3, name: \"Cheddar\", embedding: await getEmbedding(\"Cheddar\")},\n  { id: 4, name: \"Space\", embedding: await getEmbedding(\"Space\")},\n  { id: 5, name: \"database\", embedding: await getEmbedding(\"database\")},\n  ];\n  const index = new EmbeddingIndex(initialObjects); // Creates an index\n\n  // The query should be an embedding of type number[]\n  const queryEmbedding = await getEmbedding('Fruit'); // Query embedding\n  const results = await index.search(queryEmbedding, { topK: 5 }); // Returns top similar objects\n\n  // specify the storage type\n  await index.saveIndex('indexedDB');\n  const results = await index.search([1, 2, 3], {\n    topK: 5,\n    useStorage: 'indexedDB',\n    // storageOptions: { // use only if you overrode the defaults\n    //   indexedDBName: 'clientVectorDB',\n    //   indexedDBObjectStoreName: 'ClientEmbeddingStore',\n    // },\n  });\n\n  console.log(results);\n\n  await index.deleteIndexedDB(); // if you overrode default, specify db name\n```\n\n## Trouble-shooting\n\n### NextJS\nTo use it inside NextJS projects you'll need to update the `next.config.js` file to include the following:\n\n```js\nmodule.exports = {\n  // Override the default webpack configuration\n  webpack: (config) =\u003e {\n    // See https://webpack.js.org/configuration/resolve/#resolvealias\n    config.resolve.alias = {\n      ...config.resolve.alias,\n      sharp$: false,\n      \"onnxruntime-node$\": false,\n    };\n    return config;\n  },\n};\n```\n\n#### Model load after page is loaded\n\nYou can initialize the model before using it to generate embeddings. This will ensure that the model is loaded before you use it and provide a better UX.\n\n```js\nimport { initializeModel } from \"client-vector-search\"\n...\n  useEffect(() =\u003e {\n    try {\n      initializeModel();\n    } catch (e) {\n      console.log(e);\n    }\n  }, []);\n```\n\n## Usage Guide\n\nThis guide provides a step-by-step walkthrough of the library's main features. It covers everything from generating embeddings for a string to performing operations on the index such as adding, updating, and removing objects. It also includes instructions on how to save the index to a database and perform search operations within it.\n\nUntil we have a reference documentation, you can find all the methods and their usage in this guide. Each step is accompanied by a code snippet to illustrate the usage of the method in question. Make sure to follow along and try out the examples in your own environment to get a better understanding of how everything works.\n\nLet's get started!\n\n### Step 1: Generate Embeddings for String\nGenerate embeddings for a given string using the `getEmbedding` method.\n\n```ts\nconst embedding = await getEmbedding(\"Apple\"); // Returns embedding as number[]\n```\n\u003e **Note**: `getEmbedding` is asynchronous; make sure to use `await`.\n\n---\n\n### Step 2: Calculate Cosine Similarity\nCalculate the cosine similarity between two embeddings.\n\n```ts\nconst similarity = cosineSimilarity(embedding1, embedding2, 6);\n```\n\u003e **Note**: Both embeddings should be of the same length.\n\n---\n\n### Step 3: Create an Index\nCreate an index with an initial array of objects. Each object must have an 'embedding' property.\n\n```ts\nconst initialObjects = [...];\nconst index = new EmbeddingIndex(initialObjects);\n```\n\n---\n\n### Step 4: Add to Index\nAdd an object to the index.\n\n```ts\nconst objectToAdd = { id: 6, name: 'Cat', embedding: await getEmbedding('Cat') };\nindex.add(objectToAdd);\n```\n\n---\n\n### Step 5: Update Index\nUpdate an existing object in the index.\n\n```ts\nconst vectorToUpdate = { id: 6, name: 'Dog', embedding: await getEmbedding('Dog') };\nindex.update({ id: 6 }, vectorToUpdate);\n```\n\n---\n\n### Step 6: Remove from Index\nRemove an object from the index.\n\n```ts\nindex.remove({ id: 6 });\n```\n\n---\n\n### Step 7: Retrieve from Index\nRetrieve an object from the index.\n\n```ts\nconst vector = index.get({ id: 1 });\n```\n\n---\n\n### Step 8: Search the Index\nSearch the index with a query embedding.\n\n```ts\nconst queryEmbedding = await getEmbedding('Fruit');\nconst results = await index.search(queryEmbedding, { topK: 5 });\n```\n\n---\n\n### Step 9: Print the Index\nPrint the entire index to the console.\n\n```ts\nindex.printIndex();\n```\n\n---\n\n### Step 10: Save Index to IndexedDB (for browser)\nSave the index to a persistent IndexedDB database. Note\n\n```ts\nawait index.saveIndex(\"indexedDB\", { DBName: \"clientVectorDB\", objectStoreName:\"ClientEmbeddingStore\"})\n```\n\n---\n\n### Important: Search in indexedDB\nPerform a search operation in the IndexedDB.\n\n```ts\nconst results = await index.search(queryEmbedding, {\n  topK: 5,\n  useStorage: \"indexedDB\",\n  storageOptions: { // only if you want to override the default options, defaults are below\n    indexedDBName: 'clientVectorDB',\n    indexedDBObjectStoreName: 'ClientEmbeddingStore'\n  }\n});\n\n---\n\n### Delete Database\nTo delete an entire database.\n\n```ts\nawait IndexedDbManager.deleteIndexedDB(\"clientVectorDB\");\n```\n\n---\n\n### Delete Object Store\nTo delete an object store from a database.\n\n```ts\nawait IndexedDbManager.deleteIndexedDBObjectStore(\"clientVectorDB\", \"ClientEmbeddingStore\");\n```\n\n---\n\n### Retrieve All Objects\nTo retrieve all objects from a specific object store.\n\n```ts\nconst allObjects = await IndexedDbManager.getAllObjectsFromIndexedDB(\"clientVectorDB\", \"ClientEmbeddingStore\");\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxleiter%2Fclient-vector-search","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaxleiter%2Fclient-vector-search","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxleiter%2Fclient-vector-search/lists"}