[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"similar-nmslib--hnswlib":3,"tool-nmslib--hnswlib":64},[4,23,32,40,48,56],{"id":5,"name":6,"github_repo":7,"description_zh":8,"stars":9,"difficulty_score":10,"last_commit_at":11,"category_tags":12,"status":22},2268,"ML-For-Beginners","microsoft\u002FML-For-Beginners","ML-For-Beginners 是由微软推出的一套系统化机器学习入门课程，旨在帮助零基础用户轻松掌握经典机器学习知识。这套课程将学习路径规划为 12 周，包含 26 节精炼课程和 52 道配套测验，内容涵盖从基础概念到实际应用的完整流程，有效解决了初学者面对庞大知识体系时无从下手、缺乏结构化指导的痛点。\n\n无论是希望转型的开发者、需要补充算法背景的研究人员，还是对人工智能充满好奇的普通爱好者，都能从中受益。课程不仅提供了清晰的理论讲解，还强调动手实践，让用户在循序渐进中建立扎实的技能基础。其独特的亮点在于强大的多语言支持，通过自动化机制提供了包括简体中文在内的 50 多种语言版本，极大地降低了全球不同背景用户的学习门槛。此外，项目采用开源协作模式，社区活跃且内容持续更新，确保学习者能获取前沿且准确的技术资讯。如果你正寻找一条清晰、友好且专业的机器学习入门之路，ML-For-Beginners 将是理想的起点。",84991,2,"2026-04-05T10:45:23",[13,14,15,16,17,18,19,20,21],"图像","数据工具","视频","插件","Agent","其他","语言模型","开发框架","音频","ready",{"id":24,"name":25,"github_repo":26,"description_zh":27,"stars":28,"difficulty_score":29,"last_commit_at":30,"category_tags":31,"status":22},2234,"scikit-learn","scikit-learn\u002Fscikit-learn","scikit-learn 是一个基于 Python 构建的开源机器学习库，依托于 SciPy、NumPy 等科学计算生态，旨在让机器学习变得简单高效。它提供了一套统一且简洁的接口，涵盖了从数据预处理、特征工程到模型训练、评估及选择的全流程工具，内置了包括线性回归、支持向量机、随机森林、聚类等在内的丰富经典算法。\n\n对于希望快速验证想法或构建原型的数据科学家、研究人员以及 Python 开发者而言，scikit-learn 是不可或缺的基础设施。它有效解决了机器学习入门门槛高、算法实现复杂以及不同模型间调用方式不统一的痛点，让用户无需重复造轮子，只需几行代码即可调用成熟的算法解决分类、回归、聚类等实际问题。\n\n其核心技术亮点在于高度一致的 API 设计风格，所有估算器（Estimator）均遵循相同的调用逻辑，极大地降低了学习成本并提升了代码的可读性与可维护性。此外，它还提供了强大的模型选择与评估工具，如交叉验证和网格搜索，帮助用户系统地优化模型性能。作为一个由全球志愿者共同维护的成熟项目，scikit-learn 以其稳定性、详尽的文档和活跃的社区支持，成为连接理论学习与工业级应用的最",65628,1,"2026-04-05T10:10:46",[20,18,14],{"id":33,"name":34,"github_repo":35,"description_zh":36,"stars":37,"difficulty_score":10,"last_commit_at":38,"category_tags":39,"status":22},3364,"keras","keras-team\u002Fkeras","Keras 是一个专为人类设计的深度学习框架，旨在让构建和训练神经网络变得简单直观。它解决了开发者在不同深度学习后端之间切换困难、模型开发效率低以及难以兼顾调试便捷性与运行性能的痛点。\n\n无论是刚入门的学生、专注算法的研究人员，还是需要快速落地产品的工程师，都能通过 Keras 轻松上手。它支持计算机视觉、自然语言处理、音频分析及时间序列预测等多种任务。\n\nKeras 3 的核心亮点在于其独特的“多后端”架构。用户只需编写一套代码，即可灵活选择 TensorFlow、JAX、PyTorch 或 OpenVINO 作为底层运行引擎。这一特性不仅保留了 Keras 一贯的高层易用性，还允许开发者根据需求自由选择：利用 JAX 或 PyTorch 的即时执行模式进行高效调试，或切换至速度最快的后端以获得最高 350% 的性能提升。此外，Keras 具备强大的扩展能力，能无缝从本地笔记本电脑扩展至大规模 GPU 或 TPU 集群，是连接原型开发与生产部署的理想桥梁。",63927,"2026-04-04T15:24:37",[20,14,18],{"id":41,"name":42,"github_repo":43,"description_zh":44,"stars":45,"difficulty_score":10,"last_commit_at":46,"category_tags":47,"status":22},2403,"crawl4ai","unclecode\u002Fcrawl4ai","Crawl4AI 是一款专为大语言模型（LLM）设计的开源网络爬虫与数据提取工具。它的核心使命是将纷繁复杂的网页内容转化为干净、结构化的 Markdown 格式，直接服务于检索增强生成（RAG）、智能体构建及各类数据管道，让 AI 能更轻松地“读懂”互联网。\n\n传统爬虫往往面临反爬机制拦截、动态内容加载困难以及输出格式杂乱等痛点，导致后续数据处理成本高昂。Crawl4AI 通过内置自动化的三级反机器人检测、代理升级策略以及对 Shadow DOM 的深度支持，有效突破了这些障碍。它能智能移除同意弹窗，处理深层链接，并具备长任务崩溃恢复能力，确保数据采集的稳定与高效。\n\n这款工具特别适合开发者、AI 研究人员及数据工程师使用。无论是需要为本地模型构建知识库，还是搭建大规模自动化信息采集流程，Crawl4AI 都提供了极高的可控性与灵活性。作为 GitHub 上备受瞩目的开源项目，它完全免费开放，无需繁琐的注册或昂贵的 API 费用，让用户能够专注于数据价值本身而非采集难题。",63242,"2026-04-02T22:29:19",[14,17],{"id":49,"name":50,"github_repo":51,"description_zh":52,"stars":53,"difficulty_score":10,"last_commit_at":54,"category_tags":55,"status":22},193,"meilisearch","meilisearch\u002Fmeilisearch","Meilisearch 是一个开源的极速搜索服务，专为现代应用和网站打造，开箱即用。它能帮助开发者快速集成高质量的搜索功能，无需复杂的配置或额外的数据预处理。传统搜索方案往往需要大量调优才能实现准确结果，而 Meilisearch 内置了拼写容错、同义词识别、即时响应等实用特性，并支持 AI 驱动的混合搜索（结合关键词与语义理解），显著提升用户查找信息的体验。\n\nMeilisearch 特别适合 Web 开发者、产品团队或初创公司使用，尤其适用于需要快速上线搜索功能的场景，如电商网站、内容平台或 SaaS 应用。它提供简洁的 RESTful API 和多种语言 SDK，部署简单，资源占用低，本地开发或生产环境均可轻松运行。对于希望在不依赖大型云服务的前提下，为用户提供流畅、智能搜索体验的团队来说，Meilisearch 是一个高效且友好的选择。",56972,"2026-04-05T22:34:33",[13,17,14,20,16,18],{"id":57,"name":58,"github_repo":59,"description_zh":60,"stars":61,"difficulty_score":10,"last_commit_at":62,"category_tags":63,"status":22},223,"Made-With-ML","GokuMohandas\u002FMade-With-ML","Made-With-ML 是一个面向实战的开源项目，旨在帮助开发者系统掌握从设计、开发到部署和迭代生产级机器学习应用的完整流程。它解决了许多人在学习机器学习时“会训练模型但不会上线”的痛点，强调将软件工程最佳实践与 ML 技术结合，构建可靠、可维护的端到端系统。\n\n该项目特别适合三类人群：一是希望将模型真正落地的开发者（包括软件工程师、数据科学家）；二是刚毕业、想补齐工业界所需技能的学生；三是需要理解技术边界以更好推动产品的技术管理者或产品经理。\n\nMade-With-ML 的亮点在于注重第一性原理讲解，避免盲目调包；同时覆盖 MLOps 关键环节（如实验跟踪、模型测试、服务部署、CI\u002FCD 等），并支持在 Python 生态内平滑扩展训练与推理任务，无需切换语言或复杂基础设施。课程内容结构清晰，配有详细代码示例和视频导览，兼顾理论深度与工程实用性。",47120,"2026-04-05T22:16:18",[19,18,14,16,20],{"id":65,"github_repo":66,"name":67,"description_en":68,"description_zh":69,"ai_summary_zh":69,"readme_en":70,"readme_zh":71,"quickstart_zh":72,"use_case_zh":73,"hero_image_url":74,"owner_login":75,"owner_name":75,"owner_avatar_url":76,"owner_bio":77,"owner_company":77,"owner_location":77,"owner_email":77,"owner_twitter":77,"owner_website":77,"owner_url":78,"languages":79,"stars":96,"forks":97,"last_commit_at":98,"license":99,"difficulty_score":29,"env_os":100,"env_gpu":101,"env_ram":101,"env_deps":102,"category_tags":107,"github_topics":77,"view_count":10,"oss_zip_url":77,"oss_zip_packed_at":77,"status":22,"created_at":108,"updated_at":109,"faqs":110,"releases":141},2956,"nmslib\u002Fhnswlib","hnswlib","Header-only C++\u002Fpython library for fast approximate nearest neighbors","hnswlib 是一款专为快速近似最近邻搜索设计的轻量级开源库，核心基于高效的 HNSW 算法。它主要解决了在海量高维数据中，如何以极低的计算成本和内存占用，迅速找到与目标最相似数据的难题，广泛应用于推荐系统、图像检索及自然语言处理等领域。\n\n这款工具特别适合需要高性能向量检索能力的开发者与研究人员。其最大亮点在于“仅头文件”的 C++ 实现，无需复杂依赖即可集成，同时提供了便捷的 Python 接口，并支持 Java 和 R 语言调用。hnswlib 支持动态增量构建索引，允许随时插入、更新甚至标记删除数据元素，无需重建整个索引，极大地提升了工程灵活性。此外，它还支持自定义距离度量（如欧氏距离、内积、余弦距离），并在多线程搜索场景下进行了深度优化，显著减少了内存足迹并加快了构建速度。无论是构建原型还是部署生产级服务，hnswlib 都能以简洁的代码结构提供卓越的检索性能。","# Hnswlib - fast approximate nearest neighbor search\nHeader-only C++ HNSW implementation with python bindings, insertions and updates.\n\n**NEWS:**\n\n**version 0.9.0**\n\n* Fixed incorrect results in bruteforce search with filter (#514) by [@lukaszsmolinski](https:\u002F\u002Fgithub.com\u002Flukaszsmolinski)\n* Fixed missing normalization check in BFIndex (#514) by [@lukaszsmolinski](https:\u002F\u002Fgithub.com\u002Flukaszsmolinski)\n* Throw an exception when fewer than k elements are available (#514) by [@lukaszsmolinski](https:\u002F\u002Fgithub.com\u002Flukaszsmolinski)\n* Remove unused variable (#531) by [@lulyon](https:\u002F\u002Fgithub.com\u002Flulyon)\n* Change cosine similarity to distance in README by [@yurymalkov](https:\u002F\u002Fgithub.com\u002Fyurymalkov)\n\n**version 0.8.0** \n\n* Multi-vector document search and epsilon search (for now, only in C++)\n* By default, there is no statistic aggregation, which speeds up the multi-threaded search (it does not seem like people are using it anyway: [Issue #495](https:\u002F\u002Fgithub.com\u002Fnmslib\u002Fhnswlib\u002Fissues\u002F495)). \n* Various bugfixes and improvements\n* `get_items` now have `return_type` parameter, which can be either 'numpy' or 'list'\n\nFull list of changes: https:\u002F\u002Fgithub.com\u002Fnmslib\u002Fhnswlib\u002Fpull\u002F523\n\n**version 0.7.0** \n\n* Added support to filtering (#402, #430) by [@kishorenc](https:\u002F\u002Fgithub.com\u002Fkishorenc)\n* Added python interface for filtering (though note its performance is limited by GIL) (#417) by [@gtsoukas](https:\u002F\u002Fgithub.com\u002Fgtsoukas)\n* Added support for replacing the elements that were marked as delete with newly inserted elements (to control the size of the index, #418) by [@dyashuni](https:\u002F\u002Fgithub.com\u002Fdyashuni)\n* Fixed data races\u002Fdeadlocks in updates\u002Finsertion, added stress test for multithreaded operation (#418) by [@dyashuni](https:\u002F\u002Fgithub.com\u002Fdyashuni)\n* Documentation, tests, exception handling, refactoring (#375, #379, #380, #395, #396, #401, #406, #404, #409, #410, #416, #415, #431, #432, #433) by [@jlmelville](https:\u002F\u002Fgithub.com\u002Fjlmelville), [@dyashuni](https:\u002F\u002Fgithub.com\u002Fdyashuni), [@kishorenc](https:\u002F\u002Fgithub.com\u002Fkishorenc), [@korzhenevski](https:\u002F\u002Fgithub.com\u002Fkorzhenevski), [@yoshoku](https:\u002F\u002Fgithub.com\u002Fyoshoku), [@jianshu93](https:\u002F\u002Fgithub.com\u002Fjianshu93), [@PLNech](https:\u002F\u002Fgithub.com\u002FPLNech)\n* global linkages (#383) by [@MasterAler](https:\u002F\u002Fgithub.com\u002FMasterAler), USE_SSE usage in MSVC (#408) by [@alxvth](https:\u002F\u002Fgithub.com\u002Falxvth)\n\n\n### Highlights:\n1) Lightweight, header-only, no dependencies other than C++ 11\n2) Interfaces for C++, Python, external support for Java and R (https:\u002F\u002Fgithub.com\u002Fjlmelville\u002Frcpphnsw).\n3) Has full support for incremental index construction and updating the elements (thanks to the contribution by Apoorv Sharma). Has support for element deletions \n(by marking them in index, later can be replaced with other elements). Python index is picklable.\n4) Can work with custom user defined distances (C++).\n5) Significantly less memory footprint and faster build time compared to current nmslib's implementation.\n\nDescription of the algorithm parameters can be found in [ALGO_PARAMS.md](ALGO_PARAMS.md).\n\n\n### Python bindings\n\n#### Supported distances:\n\n| Distance         | parameter       | Equation                |\n| -------------    |:---------------:| -----------------------:|\n|Squared L2        |'l2'             | d = sum((Ai-Bi)^2)      |\n|Inner product     |'ip'             | d = 1.0 - sum(Ai\\*Bi)   |\n|Cosine distance   |'cosine'         | d = 1.0 - sum(Ai\\*Bi) \u002F sqrt(sum(Ai\\*Ai) * sum(Bi\\*Bi))|\n\nNote that inner product is not an actual metric. An element can be closer to some other element than to itself. That allows some speedup if you remove all elements that are not the closest to themselves from the index.\n\nFor other spaces use the nmslib library https:\u002F\u002Fgithub.com\u002Fnmslib\u002Fnmslib. \n\n#### API description\n* `hnswlib.Index(space, dim)` creates a non-initialized index an HNSW in space `space` with integer dimension `dim`.\n\n`hnswlib.Index` methods:\n* `init_index(max_elements, M = 16, ef_construction = 200, random_seed = 100, allow_replace_deleted = False)` initializes the index from with no elements. \n    * `max_elements` defines the maximum number of elements that can be stored in the structure(can be increased\u002Fshrunk).\n    * `ef_construction` defines a construction time\u002Faccuracy trade-off (see [ALGO_PARAMS.md](ALGO_PARAMS.md)).\n    * `M` defines tha maximum number of outgoing connections in the graph ([ALGO_PARAMS.md](ALGO_PARAMS.md)).\n    * `allow_replace_deleted` enables replacing of deleted elements with new added ones.\n    \n* `add_items(data, ids, num_threads = -1, replace_deleted = False)` - inserts the `data`(numpy array of vectors, shape:`N*dim`) into the structure. \n    * `num_threads` sets the number of cpu threads to use (-1 means use default).\n    * `ids` are optional N-size numpy array of integer labels for all elements in `data`. \n      - If index already has the elements with the same labels, their features will be updated. Note that update procedure is slower than insertion of a new element, but more memory- and query-efficient.\n    * `replace_deleted` replaces deleted elements. Note it allows to save memory.\n      - to use it `init_index` should be called with `allow_replace_deleted=True`\n    * Thread-safe with other `add_items` calls, but not with `knn_query`.\n    \n* `mark_deleted(label)`  - marks the element as deleted, so it will be omitted from search results. Throws an exception if it is already deleted.\n\n* `unmark_deleted(label)`  - unmarks the element as deleted, so it will be not be omitted from search results.\n\n* `resize_index(new_size)` - changes the maximum capacity of the index. Not thread safe with `add_items` and `knn_query`.\n\n* `set_ef(ef)` - sets the query time accuracy\u002Fspeed trade-off, defined by the `ef` parameter (\n[ALGO_PARAMS.md](ALGO_PARAMS.md)). Note that the parameter is currently not saved along with the index, so you need to set it manually after loading.\n\n* `knn_query(data, k = 1, num_threads = -1, filter = None)` make a batch query for `k` closest elements for each element of the \n    * `data` (shape:`N*dim`). Returns a numpy array of (shape:`N*k`).\n    * `num_threads` sets the number of cpu threads to use (-1 means use default).\n    * `filter` filters elements by its labels, returns elements with allowed ids. Note that search with a filter works slow in python in multithreaded mode. It is recommended to set `num_threads=1`\n    * Thread-safe with other `knn_query` calls, but not with `add_items`.\n    \n* `load_index(path_to_index, max_elements = 0, allow_replace_deleted = False)` loads the index from persistence to the uninitialized index.\n    * `max_elements`(optional) resets the maximum number of elements in the structure.\n    * `allow_replace_deleted` specifies whether the index being loaded has enabled replacing of deleted elements.\n      \n* `save_index(path_to_index)` saves the index from persistence.\n\n* `set_num_threads(num_threads)` set the default number of cpu threads used during data insertion\u002Fquerying.\n  \n* `get_items(ids, return_type = 'numpy')` - returns a numpy array (shape:`N*dim`) of vectors that have integer identifiers specified in `ids` numpy vector (shape:`N`) if `return_type` is `list` return list of lists. Note that for cosine similarity it currently returns **normalized** vectors.\n  \n* `get_ids_list()`  - returns a list of all elements' ids.\n\n* `get_max_elements()` - returns the current capacity of the index\n\n* `get_current_count()` - returns the current number of element stored in the index\n\nRead-only properties of `hnswlib.Index` class:\n\n* `space` - name of the space (can be one of \"l2\", \"ip\", or \"cosine\"). \n\n* `dim`   - dimensionality of the space. \n\n* `M` - parameter that defines the maximum number of outgoing connections in the graph. \n\n* `ef_construction` - parameter that controls speed\u002Faccuracy trade-off during the index construction. \n\n* `max_elements` - current capacity of the index. Equivalent to `p.get_max_elements()`. \n\n* `element_count` - number of items in the index. Equivalent to `p.get_current_count()`. \n\nProperties of `hnswlib.Index` that support reading and writing:\n\n* `ef` - parameter controlling query time\u002Faccuracy trade-off.\n\n* `num_threads` - default number of threads to use in `add_items` or `knn_query`. Note that calling `p.set_num_threads(3)` is equivalent to `p.num_threads=3`.\n\n  \n        \n  \n#### Python bindings examples\n[See more examples here](examples\u002Fpython\u002FEXAMPLES.md):\n* Creating index, inserting elements, searching, serialization\u002Fdeserialization\n* Filtering during the search with a boolean function\n* Deleting the elements and reusing the memory of the deleted elements for newly added elements\n\nAn example of creating index, inserting elements, searching and pickle serialization:\n```python\nimport hnswlib\nimport numpy as np\nimport pickle\n\ndim = 128\nnum_elements = 10000\n\n# Generating sample data\ndata = np.float32(np.random.random((num_elements, dim)))\nids = np.arange(num_elements)\n\n# Declaring index\np = hnswlib.Index(space = 'l2', dim = dim) # possible options are l2, cosine or ip\n\n# Initializing index - the maximum number of elements should be known beforehand\np.init_index(max_elements = num_elements, ef_construction = 200, M = 16)\n\n# Element insertion (can be called several times):\np.add_items(data, ids)\n\n# Controlling the recall by setting ef:\np.set_ef(50) # ef should always be > k\n\n# Query dataset, k - number of the closest elements (returns 2 numpy arrays)\nlabels, distances = p.knn_query(data, k = 1)\n\n# Index objects support pickling\n# WARNING: serialization via pickle.dumps(p) or p.__getstate__() is NOT thread-safe with p.add_items method!\n# Note: ef parameter is included in serialization; random number generator is initialized with random_seed on Index load\np_copy = pickle.loads(pickle.dumps(p)) # creates a copy of index p using pickle round-trip\n\n### Index parameters are exposed as class properties:\nprint(f\"Parameters passed to constructor:  space={p_copy.space}, dim={p_copy.dim}\") \nprint(f\"Index construction: M={p_copy.M}, ef_construction={p_copy.ef_construction}\")\nprint(f\"Index size is {p_copy.element_count} and index capacity is {p_copy.max_elements}\")\nprint(f\"Search speed\u002Fquality trade-off parameter: ef={p_copy.ef}\")\n```\n\nAn example with updates after serialization\u002Fdeserialization:\n```python\nimport hnswlib\nimport numpy as np\n\ndim = 16\nnum_elements = 10000\n\n# Generating sample data\ndata = np.float32(np.random.random((num_elements, dim)))\n\n# We split the data in two batches:\ndata1 = data[:num_elements \u002F\u002F 2]\ndata2 = data[num_elements \u002F\u002F 2:]\n\n# Declaring index\np = hnswlib.Index(space='l2', dim=dim)  # possible options are l2, cosine or ip\n\n# Initializing index\n# max_elements - the maximum number of elements (capacity). Will throw an exception if exceeded\n# during insertion of an element.\n# The capacity can be increased by saving\u002Floading the index, see below.\n#\n# ef_construction - controls index search speed\u002Fbuild speed tradeoff\n#\n# M - is tightly connected with internal dimensionality of the data. Strongly affects memory consumption (~M)\n# Higher M leads to higher accuracy\u002Frun_time at fixed ef\u002FefConstruction\n\np.init_index(max_elements=num_elements\u002F\u002F2, ef_construction=100, M=16)\n\n# Controlling the recall by setting ef:\n# higher ef leads to better accuracy, but slower search\np.set_ef(10)\n\n# Set number of threads used during batch search\u002Fconstruction\n# By default using all available cores\np.set_num_threads(4)\n\nprint(\"Adding first batch of %d elements\" % (len(data1)))\np.add_items(data1)\n\n# Query the elements for themselves and measure recall:\nlabels, distances = p.knn_query(data1, k=1)\nprint(\"Recall for the first batch:\", np.mean(labels.reshape(-1) == np.arange(len(data1))), \"\\n\")\n\n# Serializing and deleting the index:\nindex_path='first_half.bin'\nprint(\"Saving index to '%s'\" % index_path)\np.save_index(\"first_half.bin\")\ndel p\n\n# Re-initializing, loading the index\np = hnswlib.Index(space='l2', dim=dim)  # the space can be changed - keeps the data, alters the distance function.\n\nprint(\"\\nLoading index from 'first_half.bin'\\n\")\n\n# Increase the total capacity (max_elements), so that it will handle the new data\np.load_index(\"first_half.bin\", max_elements = num_elements)\n\nprint(\"Adding the second batch of %d elements\" % (len(data2)))\np.add_items(data2)\n\n# Query the elements for themselves and measure recall:\nlabels, distances = p.knn_query(data, k=1)\nprint(\"Recall for two batches:\", np.mean(labels.reshape(-1) == np.arange(len(data))), \"\\n\")\n```\n\n#### C++ examples\n[See examples here](examples\u002Fcpp\u002FEXAMPLES.md):\n* creating index, inserting elements, searching, serialization\u002Fdeserialization\n* filtering during the search with a boolean function\n* deleting the elements and reusing the memory of the deleted elements for newly added elements\n* multithreaded usage\n* multivector search\n* epsilon search\n\n\n### Bindings installation\n\nYou can install from sources:\n```bash\napt-get install -y python-setuptools python-pip\ngit clone https:\u002F\u002Fgithub.com\u002Fnmslib\u002Fhnswlib.git\ncd hnswlib\npip install .\n```\n\nor you can install via pip:\n`pip install hnswlib`\n\n\n### For developers \nContributions are highly welcome!\n\nPlease make pull requests against the `develop` branch.\n\nWhen making changes please run tests (and please add a test to `tests\u002Fpython` in case there is new functionality):\n```bash\npython -m unittest discover --start-directory tests\u002Fpython --pattern \"bindings_test*.py\"\n```\n\n\n### Other implementations\n* Non-metric space library (nmslib) - main library(python, C++), supports exotic distances: https:\u002F\u002Fgithub.com\u002Fnmslib\u002Fnmslib\n* Faiss library by facebook, uses own HNSW  implementation for coarse quantization (python, C++):\nhttps:\u002F\u002Fgithub.com\u002Ffacebookresearch\u002Ffaiss\n* Code for the paper \n[\"Revisiting the Inverted Indices for Billion-Scale Approximate Nearest Neighbors\"](https:\u002F\u002Farxiv.org\u002Fabs\u002F1802.02422) \n(current state-of-the-art in compressed indexes, C++):\nhttps:\u002F\u002Fgithub.com\u002Fdbaranchuk\u002Fivf-hnsw\n* Amazon PECOS https:\u002F\u002Fgithub.com\u002Famzn\u002Fpecos \n* TOROS N2 (python, C++): https:\u002F\u002Fgithub.com\u002Fkakao\u002Fn2 \n* Online HNSW (C++): https:\u002F\u002Fgithub.com\u002Fandrusha97\u002Fonline-hnsw) \n* Go implementation: https:\u002F\u002Fgithub.com\u002FBithack\u002Fgo-hnsw\n* Python implementation (as a part of the clustering code by by Matteo Dell'Amico): https:\u002F\u002Fgithub.com\u002Fmatteodellamico\u002Fflexible-clustering\n* Julia implmentation https:\u002F\u002Fgithub.com\u002FJuliaNeighbors\u002FHNSW.jl\n* Java implementation: https:\u002F\u002Fgithub.com\u002Fjelmerk\u002Fhnswlib\n* Java bindings using Java Native Access: https:\u002F\u002Fgithub.com\u002Fstepstone-tech\u002Fhnswlib-jna\n* .Net implementation: https:\u002F\u002Fgithub.com\u002Fcuriosity-ai\u002Fhnsw-sharp\n* CUDA implementation: https:\u002F\u002Fgithub.com\u002Fjs1010\u002Fcuhnsw\n* Rust implementation https:\u002F\u002Fgithub.com\u002Frust-cv\u002Fhnsw\n* Rust implementation for memory and thread safety purposes and There is  A Trait to enable the user to implement its own distances. It takes as data slices of types T satisfying T:Serialize+Clone+Send+Sync.: https:\u002F\u002Fgithub.com\u002Fjean-pierreBoth\u002Fhnswlib-rs\n\n### 200M SIFT test reproduction \nTo download and extract the bigann dataset (from root directory):\n```bash\npython tests\u002Fcpp\u002Fdownload_bigann.py\n```\nTo compile:\n```bash\nmkdir build\ncd build\ncmake ..\nmake all\n```\n\nTo run the test on 200M SIFT subset:\n```bash\n.\u002Fmain\n```\n\nThe size of the BigANN subset (in millions) is controlled by the variable **subset_size_millions** hardcoded in **sift_1b.cpp**.\n\n### Updates test\nTo generate testing data (from root directory):\n```bash\ncd tests\u002Fcpp\npython update_gen_data.py\n```\nTo compile (from root directory):\n```bash\nmkdir build\ncd build\ncmake ..\nmake \n```\nTo run test **without** updates (from `build` directory)\n```bash\n.\u002Ftest_updates\n```\n\nTo run test **with** updates (from `build` directory)\n```bash\n.\u002Ftest_updates update\n```\n\n### HNSW example demos\n\n- Visual search engine for 1M amazon products (MXNet + HNSW): [website](https:\u002F\u002Fthomasdelteil.github.io\u002FVisualSearch_MXNet\u002F), [code](https:\u002F\u002Fgithub.com\u002FThomasDelteil\u002FVisualSearch_MXNet), demo by [@ThomasDelteil](https:\u002F\u002Fgithub.com\u002FThomasDelteil)\n\n### References\nHNSW paper:\n```\n@article{malkov2018efficient,\n  title={Efficient and robust approximate nearest neighbor search using hierarchical navigable small world graphs},\n  author={Malkov, Yu A and Yashunin, Dmitry A},\n  journal={IEEE transactions on pattern analysis and machine intelligence},\n  volume={42},\n  number={4},\n  pages={824--836},\n  year={2018},\n  publisher={IEEE}\n}\n```\n\nThe update algorithm supported in this repository is to be published in \"Dynamic Updates For HNSW, Hierarchical Navigable Small World Graphs\" US Patent 15\u002F929,802 by Apoorv Sharma, Abhishek Tayal and Yury Malkov.\n","# Hnswlib - 快速近似最近邻搜索\n仅头文件的 C++ HNSW 实现，带有 Python 绑定、插入和更新功能。\n\n**新闻：**\n\n**版本 0.9.0**\n\n* 修复了带过滤器的暴力搜索结果不正确的问题 (#514)，由 [@lukaszsmolinski](https:\u002F\u002Fgithub.com\u002Flukaszsmolinski) 完成\n* 修复了 BFIndex 中缺失的归一化检查 (#514)，由 [@lukaszsmolinski](https:\u002F\u002Fgithub.com\u002Flukaszsmolinski) 完成\n* 当可用元素少于 k 个时抛出异常 (#514)，由 [@lukaszsmolinski](https:\u002F\u002Fgithub.com\u002Flukaszsmolinski) 完成\n* 移除未使用的变量 (#531)，由 [@lulyon](https:\u002F\u002Fgithub.com\u002Flulyon) 完成\n* 将 README 中的余弦相似度改为距离，由 [@yurymalkov](https:\u002F\u002Fgithub.com\u002Fyurymalkov) 完成\n\n**版本 0.8.0**\n\n* 多向量文档搜索和 epsilon 搜索（目前仅在 C++ 中支持）\n* 默认情况下不再进行统计聚合，这加快了多线程搜索的速度（似乎也确实很少有人使用：[Issue #495](https:\u002F\u002Fgithub.com\u002Fnmslib\u002Fhnswlib\u002Fissues\u002F495)）。\n* 各种错误修复和改进\n* `get_items` 现在增加了 `return_type` 参数，可选值为 'numpy' 或 'list'\n\n完整变更列表：https:\u002F\u002Fgithub.com\u002Fnmslib\u002Fhnswlib\u002Fpull\u002F523\n\n**版本 0.7.0**\n\n* 增加了对过滤的支持 (#402, #430)，由 [@kishorenc](https:\u002F\u002Fgithub.com\u002Fkishorenc) 完成\n* 添加了用于过滤的 Python 接口（但请注意，其性能受限于 GIL）(#417)，由 [@gtsoukas](https:\u002F\u002Fgithub.com\u002Fgtsoukas) 完成\n* 支持用新插入的元素替换已被标记为删除的元素，以控制索引大小 (#418)，由 [@dyashuni](https:\u002F\u002Fgithub.com\u002Fdyashuni) 完成\n* 修复了更新\u002F插入操作中的数据竞争\u002F死锁问题，并添加了多线程操作的压力测试 (#418)，由 [@dyashuni](https:\u002F\u002Fgithub.com\u002Fdyashuni) 完成\n* 文档、测试、异常处理、重构工作 (#375, #379, #380, #395, #396, #401, #406, #404, #409, #410, #416, #415, #431, #432, #433)，由 [@jlmelville](https:\u002F\u002Fgithub.com\u002Fjlmelville)、[@dyashuni](https:\u002F\u002Fgithub.com\u002Fdyashuni)、[@kishorenc](https:\u002F\u002Fgithub.com\u002Fkishorenc)、[@korzhenevski](https:\u002F\u002Fgithub.com\u002Fkorzhenevski)、[@yoshoku](https:\u002F\u002Fgithub.com\u002Fyoshoku)、[@jianshu93](https:\u002F\u002Fgithub.com\u002Fjianshu93)、[@PLNech](https:\u002F\u002Fgithub.com\u002FPLNech) 等完成\n* 全局链接 (#383)，由 [@MasterAler](https:\u002F\u002Fgithub.com\u002FMasterAler) 完成；MSVC 中使用 USE_SSE (#408)，由 [@alxvth](https:\u002F\u002Fgithub.com\u002Falxvth) 完成\n\n### 亮点：\n1) 轻量级、仅头文件实现，除 C++11 外无其他依赖。\n2) 提供 C++ 和 Python 接口，并对外支持 Java 和 R（https:\u002F\u002Fgithub.com\u002Fjlmelville\u002Frcpphnsw）。\n3) 完全支持增量式索引构建和元素更新（感谢 Apoorv Sharma 的贡献）。同时支持元素删除操作（通过在索引中标记删除，后续可用其他元素替换）。Python 版本的索引可以被 pickle 序列化。\n4) 可与用户自定义的距离函数一起使用（C++）。\n5) 相较于当前 nmslib 的实现，内存占用显著降低，构建时间更快。\n\n算法参数的说明请参阅 [ALGO_PARAMS.md](ALGO_PARAMS.md)。\n\n### Python 绑定\n\n#### 支持的距离度量：\n\n| 距离           | 参数       | 公式                |\n| -------------  |:-----------:| -------------------:|\n| 平方 L2        |'l2'         | d = sum((Ai-Bi)^2)      |\n| 内积           |'ip'         | d = 1.0 - sum(Ai\\*Bi)   |\n| 余弦距离       |'cosine'     | d = 1.0 - sum(Ai\\*Bi) \u002F sqrt(sum(Ai\\*Ai) * sum(Bi\\*Bi))|\n\n请注意，内积并不是一个真正的度量。某个元素可能比它自身更接近另一个元素。如果从索引中移除所有不与自身最近的元素，这可以带来一定的性能提升。\n\n对于其他空间，请使用 nmslib 库：https:\u002F\u002Fgithub.com\u002Fnmslib\u002Fnmslib。\n\n#### API 描述\n* `hnswlib.Index(space, dim)` 在空间 `space` 中创建一个未初始化的 HNSW 索引，维度为整数 `dim`。\n\n`hnswlib.Index` 方法：\n* `init_index(max_elements, M = 16, ef_construction = 200, random_seed = 100, allow_replace_deleted = False)` 初始化一个空的索引。\n    * `max_elements` 定义了结构中可存储的最大元素数量（可以增加或减少）。\n    * `ef_construction` 定义了构建时间与准确性之间的权衡（参见 [ALGO_PARAMS.md](ALGO_PARAMS.md)）。\n    * `M` 定义了图中每个节点的最大出边数（参见 [ALGO_PARAMS.md](ALGO_PARAMS.md)）。\n    * `allow_replace_deleted` 允许用新添加的元素替换已删除的元素。\n    \n* `add_items(data, ids, num_threads = -1, replace_deleted = False)` 将 `data`（形状为 `N*dim` 的向量 NumPy 数组）插入到结构中。\n    * `num_threads` 设置使用的 CPU 线程数（-1 表示使用默认值）。\n    * `ids` 是可选的 N 大小的整数标签 NumPy 数组，用于 `data` 中的所有元素。\n      - 如果索引中已经存在具有相同标签的元素，其特征将被更新。请注意，更新操作比插入新元素慢，但更节省内存且查询效率更高。\n    * `replace_deleted` 会替换已删除的元素。注意，这有助于节省内存。\n      - 要使用此功能，必须在调用 `init_index` 时设置 `allow_replace_deleted=True`。\n    * 该方法与其他 `add_items` 调用是线程安全的，但与 `knn_query` 不是。\n    \n* `mark_deleted(label)` 标记元素为已删除，使其不会出现在搜索结果中。如果元素已被标记为已删除，则会抛出异常。\n\n* `unmark_deleted(label)` 取消标记已删除的元素，使其会出现在搜索结果中。\n\n* `resize_index(new_size)` 更改索引的最大容量。与 `add_items` 和 `knn_query` 不是线程安全的。\n\n* `set_ef(ef)` 设置查询时间、准确性和速度之间的权衡，由 `ef` 参数定义（[ALGO_PARAMS.md](ALGO_PARAMS.md)）。请注意，该参数目前不会与索引一起保存，因此在加载后需要手动设置。\n\n* `knn_query(data, k = 1, num_threads = -1, filter = None)` 对 `data` 中的每个元素进行批量查询，返回每个元素最接近的 `k` 个元素。\n    * `data`（形状为 `N*dim`）。返回形状为 `N*k` 的 NumPy 数组。\n    * `num_threads` 设置使用的 CPU 线程数（-1 表示使用默认值）。\n    * `filter` 按标签过滤元素，只返回具有允许 ID 的元素。请注意，在多线程模式下，使用过滤器进行搜索的速度较慢。建议将 `num_threads` 设置为 1。\n    * 该方法与其他 `knn_query` 调用是线程安全的，但与 `add_items` 不是。\n    \n* `load_index(path_to_index, max_elements = 0, allow_replace_deleted = False)` 从持久化存储中加载索引到未初始化的索引中。\n    * `max_elements`（可选）重置结构中的最大元素数量。\n    * `allow_replace_deleted` 指定正在加载的索引是否启用了替换已删除元素的功能。\n      \n* `save_index(path_to_index)` 将索引保存到持久化存储中。\n\n* `set_num_threads(num_threads)` 设置数据插入\u002F查询过程中默认使用的 CPU 线程数。\n  \n* `get_items(ids, return_type = 'numpy')` 返回形状为 `N*dim` 的向量 NumPy 数组，这些向量的整数标识符在 `ids` NumPy 向量中指定（形状为 `N`）。如果 `return_type` 为 `list`，则返回列表的列表。请注意，对于余弦相似度，当前返回的是**归一化**向量。\n  \n* `get_ids_list()` 返回所有元素的 ID 列表。\n\n* `get_max_elements()` 返回索引的当前容量。\n\n* `get_current_count()` 返回索引中当前存储的元素数量。\n\n`hnswlib.Index` 类的只读属性：\n\n* `space` - 空间名称（可以是 \"l2\"、\"ip\" 或 \"cosine\"）。\n\n* `dim` - 空间的维数。\n\n* `M` - 定义图中每个节点最大出边数的参数。\n\n* `ef_construction` - 控制索引构建过程中速度与准确性之间权衡的参数。\n\n* `max_elements` - 索引的当前容量。等同于 `p.get_max_elements()`。\n\n* `element_count` - 索引中的项目数量。等同于 `p.get_current_count()`。\n\n`hnswlib.Index` 支持读写的属性：\n\n* `ef` - 控制查询时间与准确性之间权衡的参数。\n\n* `num_threads` - 在 `add_items` 或 `knn_query` 中默认使用的线程数。请注意，调用 `p.set_num_threads(3)` 等同于 `p.num_threads=3`。\n\n  \n\n#### Python 绑定示例\n[在此处查看更多示例](examples\u002Fpython\u002FEXAMPLES.md)：\n* 创建索引、插入元素、搜索、序列化\u002F反序列化\n* 使用布尔函数在搜索过程中进行过滤\n* 删除元素并重新利用已删除元素的内存来存储新添加的元素\n\n创建索引、插入元素、搜索和 pickle 序列化的示例：\n```python\nimport hnswlib\nimport numpy as np\nimport pickle\n\ndim = 128\nnum_elements = 10000\n\n# 生成示例数据\ndata = np.float32(np.random.random((num_elements, dim)))\nids = np.arange(num_elements)\n\n# 声明索引\np = hnswlib.Index(space = 'l2', dim = dim) # 可能的选项是 l2、cosine 或 ip\n\n# 初始化索引 - 必须事先知道最大元素数量\np.init_index(max_elements = num_elements, ef_construction = 200, M = 16)\n\n# 插入元素（可以多次调用）：\np.add_items(data, ids)\n\n# 通过设置 ef 来控制召回率：\np.set_ef(50) # ef 值应始终大于 k\n\n# 查询数据集，k 表示最接近的元素数量（返回两个 NumPy 数组）\nlabels, distances = p.knn_query(data, k = 1)\n\n# 索引对象支持 pickle 序列化\n# 注意：使用 pickle.dumps(p) 或 p.__getstate__() 进行序列化与 p.add_items 方法不线程安全！\n# 注意：ef 参数包含在序列化中；随机数生成器在加载索引时使用 random_seed 进行初始化\np_copy = pickle.loads(pickle.dumps(p)) # 使用 pickle 循环创建索引 p 的副本\n\n### 索引参数作为类属性公开：\nprint(f\"传递给构造函数的参数：space={p_copy.space}, dim={p_copy.dim}\") \nprint(f\"索引构建：M={p_copy.M}, ef_construction={p_copy.ef_construction}\")\nprint(f\"索引大小为 {p_copy.element_count}，索引容量为 {p_copy.max_elements}\")\nprint(f\"搜索速度与质量的权衡参数：ef={p_copy.ef}\")\n```\n\n序列化\u002F反序列化后的更新示例：\n```python\nimport hnswlib\nimport numpy as np\n\ndim = 16\nnum_elements = 10000\n\n# 生成示例数据\ndata = np.float32(np.random.random((num_elements, dim)))\n\n# 我们将数据分为两个批次：\ndata1 = data[:num_elements \u002F\u002F 2]\ndata2 = data[num_elements \u002F\u002F 2:]\n\n# 声明索引\np = hnswlib.Index(space='l2', dim=dim)  # 可选值为 l2、cosine 或 ip\n\n# 初始化索引\n# max_elements - 最大元素数量（容量）。如果在插入元素时超出此限制，将会抛出异常。\n# 容量可以通过保存\u002F加载索引来增加，详见下文。\n#\n# ef_construction - 控制索引构建速度与查询速度之间的权衡。\n#\n# M - 与数据的内部维度紧密相关。强烈影响内存消耗（约与 M 成正比）。\n# 较高的 M 值可在固定的 ef\u002FefConstruction 下提高检索准确性和运行时间。\n\np.init_index(max_elements=num_elements\u002F\u002F2, ef_construction=100, M=16)\n\n# 通过设置 ef 来控制召回率：\n# 较高的 ef 值可提高准确性，但会降低查询速度。\np.set_ef(10)\n\n# 设置批量搜索\u002F构建过程中使用的线程数\n# 默认使用所有可用核心\np.set_num_threads(4)\n\nprint(\"添加第一批次 %d 个元素\" % (len(data1)))\np.add_items(data1)\n\n# 查询这些元素自身并测量召回率：\nlabels, distances = p.knn_query(data1, k=1)\nprint(\"第一批次的召回率：\", np.mean(labels.reshape(-1) == np.arange(len(data1))), \"\\n\")\n\n# 序列化并删除索引：\nindex_path='first_half.bin'\nprint(\"将索引保存到 '%s'\" % index_path)\np.save_index(\"first_half.bin\")\ndel p\n\n# 重新初始化并加载索引\np = hnswlib.Index(space='l2', dim=dim)  # 空间可以更改——这会保留数据，但改变距离函数。\n\nprint(\"\\n从 'first_half.bin' 加载索引\\n\")\n\n# 增加总容量（max_elements），以便容纳新数据\np.load_index(\"first_half.bin\", max_elements = num_elements)\n\nprint(\"添加第二批次 %d 个元素\" % (len(data2)))\np.add_items(data2)\n\n# 查询这些元素自身并测量召回率：\nlabels, distances = p.knn_query(data, k=1)\nprint(\"两批次的召回率：\", np.mean(labels.reshape(-1) == np.arange(len(data))), \"\\n\")\n```\n\n#### C++ 示例\n[在此处查看示例](examples\u002Fcpp\u002FEXAMPLES.md)：\n* 创建索引、插入元素、搜索、序列化\u002F反序列化\n* 在搜索过程中使用布尔函数进行过滤\n* 删除元素并将已删除元素的内存空间重新用于新插入的元素\n* 多线程使用\n* 多向量搜索\n* ε 搜索\n\n\n### 绑定库安装\n\n您可以从源代码安装：\n```bash\napt-get install -y python-setuptools python-pip\ngit clone https:\u002F\u002Fgithub.com\u002Fnmslib\u002Fhnswlib.git\ncd hnswlib\npip install .\n```\n\n或者您也可以通过 pip 安装：\n`pip install hnswlib`\n\n\n### 针对开发者\n我们非常欢迎贡献！\n\n请针对 `develop` 分支提交拉取请求。\n\n在进行更改时，请运行测试（如果有新功能，请在 `tests\u002Fpython` 中添加测试）：\n```bash\npython -m unittest discover --start-directory tests\u002Fpython --pattern \"bindings_test*.py\"\n```\n\n\n### 其他实现\n* 非度量空间库（nmslib）——主库（Python、C++），支持多种特殊距离：https:\u002F\u002Fgithub.com\u002Fnmslib\u002Fnmslib\n* Facebook 的 Faiss 库，使用其自有的 HNSW 实现进行粗量化处理（Python、C++）：\nhttps:\u002F\u002Fgithub.com\u002Ffacebookresearch\u002Ffaiss\n* 论文“重访十亿级近似最近邻的倒排索引”中的代码\n（目前压缩索引领域的最先进方法，C++）：\nhttps:\u002F\u002Fgithub.com\u002Fdbaranchuk\u002Fivf-hnsw\n* Amazon PECOS https:\u002F\u002Fgithub.com\u002Famzn\u002Fpecos \n* TOROS N2（Python、C++）：https:\u002F\u002Fgithub.com\u002Fkakao\u002Fn2 \n* 在线 HNSW（C++）：https:\u002F\u002Fgithub.com\u002Fandrusha97\u002Fonline-hnsw) \n* Go 实现：https:\u002F\u002Fgithub.com\u002FBithack\u002Fgo-hnsw\n* Python 实现（作为 Matteo Dell'Amico 聚类代码的一部分）：https:\u002F\u002Fgithub.com\u002Fmatteodellamico\u002Fflexible-clustering\n* Julia 实现 https:\u002F\u002Fgithub.com\u002FJuliaNeighbors\u002FHNSW.jl\n* Java 实现：https:\u002F\u002Fgithub.com\u002Fjelmerk\u002Fhnswlib\n* 使用 Java Native Access 的 Java 绑定：https:\u002F\u002Fgithub.com\u002Fstepstone-tech\u002Fhnswlib-jna\n* .Net 实现：https:\u002F\u002Fgithub.com\u002Fcuriosity-ai\u002Fhnsw-sharp\n* CUDA 实现：https:\u002F\u002Fgithub.com\u002Fjs1010\u002Fcuhnsw\n* Rust 实现 https:\u002F\u002Fgithub.com\u002Frust-cv\u002Fhnsw\n* Rust 实现注重内存和线程安全，并提供一个 Trait 接口，允许用户实现自己的距离函数。该接口接受类型为 T 的切片，其中 T 需满足 Serialize+Clone+Send+Sync 的要求：https:\u002F\u002Fgithub.com\u002Fjean-pierreBoth\u002Fhnswlib-rs\n\n### 2 亿 SIFT 数据集复现\n从根目录下载并解压 bigann 数据集：\n```bash\npython tests\u002Fcpp\u002Fdownload_bigann.py\n```\n编译步骤：\n```bash\nmkdir build\ncd build\ncmake ..\nmake all\n```\n\n运行 2 亿 SIFT 子集测试：\n```bash\n.\u002Fmain\n```\n\nBigANN 子集的大小（以百万为单位）由 **sift_1b.cpp** 文件中硬编码的变量 **subset_size_millions** 控制。\n\n### 更新测试\n从根目录生成测试数据：\n```bash\ncd tests\u002Fcpp\npython update_gen_data.py\n```\n编译步骤（从根目录开始）：\n```bash\nmkdir build\ncd build\ncmake ..\nmake \n```\n运行不包含更新的测试（从 `build` 目录）：\n```bash\n.\u002Ftest_updates\n```\n\n运行包含更新的测试（从 `build` 目录）：\n```bash\n.\u002Ftest_updates update\n```\n\n### HNSW 示例演示\n\n- 用于 100 万件亚马逊商品的视觉搜索引擎（MXNet + HNSW）：[网站](https:\u002F\u002Fthomasdelteil.github.io\u002FVisualSearch_MXNet\u002F)，[代码](https:\u002F\u002Fgithub.com\u002FThomasDelteil\u002FVisualSearch_MXNet)，演示者：[@ThomasDelteil](https:\u002F\u002Fgithub.com\u002FThomasDelteil)\n\n### 参考文献\nHNSW 论文：\n```\n@article{malkov2018efficient,\n  title={高效且鲁棒的近似最近邻搜索：基于分层可导航小世界图},\n  author={Malkov, Yu A 和 Yashunin, Dmitry A},\n  journal={IEEE 模式分析与机器智能汇刊},\n  volume={42},\n  number={4},\n  pages={824--836},\n  year={2018},\n  publisher={IEEE}\n}\n```\n\n本仓库支持的更新算法即将发表于“Apoorv Sharma、Abhishek Tayal 和 Yury Malkov 提交的 US Patent 15\u002F929,802：HNSW 的动态更新，分层可导航小世界图”。","# hnswlib 快速上手指南\n\nhnswlib 是一个轻量级、仅头文件的 C++ HNSW（分层可导航小世界）算法实现，提供 Python 绑定。它支持增量索引构建、元素更新与删除，具有内存占用小、构建速度快、查询效率高等特点，适用于大规模向量近似最近邻搜索。\n\n## 环境准备\n\n- **操作系统**：Linux \u002F macOS \u002F Windows\n- **Python 版本**：Python 3.6+\n- **依赖库**：\n  - `numpy`\n  - C++11 兼容编译器（如 g++、clang++ 或 MSVC）\n- **可选依赖**：无额外第三方库依赖（header-only C++ 实现）\n\n> 💡 提示：国内用户可使用清华或阿里云镜像加速 pip 安装。\n\n## 安装步骤\n\n### 方式一：通过 pip 安装（推荐）\n\n```bash\npip install hnswlib\n```\n\n**使用国内镜像加速（推荐）：**\n\n```bash\npip install hnswlib -i https:\u002F\u002Fpypi.tuna.tsinghua.edu.cn\u002Fsimple\n```\n\n或\n\n```bash\npip install hnswlib -i https:\u002F\u002Fmirrors.aliyun.com\u002Fpypi\u002Fsimple\u002F\n```\n\n### 方式二：从源码安装（适用于开发或自定义编译）\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Fnmslib\u002Fhnswlib.git\ncd hnswlib\u002Fpython_bindings\npython setup.py install\n```\n\n## 基本使用\n\n以下是最简单的使用示例，涵盖索引创建、数据插入、近邻搜索和序列化。\n\n```python\nimport hnswlib\nimport numpy as np\nimport pickle\n\n# 设置参数\ndim = 128\nnum_elements = 10000\n\n# 生成随机向量数据\ndata = np.float32(np.random.random((num_elements, dim)))\nids = np.arange(num_elements)\n\n# 创建索引（支持空间：'l2', 'ip', 'cosine'）\np = hnswlib.Index(space='l2', dim=dim)\n\n# 初始化索引\np.init_index(max_elements=num_elements, ef_construction=200, M=16)\n\n# 插入数据\np.add_items(data, ids)\n\n# 设置查询精度参数（ef 应大于 k）\np.set_ef(50)\n\n# 执行 KNN 查询（查找每个向量的 1 个最近邻）\nlabels, distances = p.knn_query(data, k=1)\n\n# 验证召回率（可选）\nprint(\"Recall:\", np.mean(labels.reshape(-1) == ids))\n\n# 序列化索引（支持 pickle）\nwith open(\"index.pkl\", \"wb\") as f:\n    pickle.dump(p, f)\n\n# 反序列化\nwith open(\"index.pkl\", \"rb\") as f:\n    p_loaded = pickle.load(f)\n\n# 继续查询\nlabels_new, distances_new = p_loaded.knn_query(data[:5], k=1)\nprint(\"Top-1 labels for first 5 queries:\", labels_new)\n```\n\n### 关键参数说明\n\n- `space`: 距离度量方式，可选 `'l2'`（欧氏距离平方）、`'ip'`（内积）、`'cosine'`（余弦距离）\n- `dim`: 向量维度\n- `max_elements`: 索引最大容量（可后续扩容）\n- `M`: 图中每个节点的最大连接数，影响内存与精度\n- `ef_construction`: 构建时的搜索宽度，越大越准但越慢\n- `ef`: 查询时的搜索宽度，需手动设置且应 > k\n\n> ⚠️ 注意：`ef` 参数不会自动保存，加载索引后需重新设置。\n\n此指南适用于快速集成 hnswlib 到项目中。更多高级功能（如过滤、删除、多线程）请参考官方示例与文档。","某电商平台的推荐系统团队需要在毫秒级内，从千万级商品向量库中为用户实时检索最相似的“猜你喜欢”商品。\n\n### 没有 hnswlib 时\n- **响应延迟极高**：采用暴力穷举或传统索引算法，面对千万级数据时单次查询耗时超过数百毫秒，导致用户刷新页面时出现明显卡顿。\n- **内存资源爆炸**：全量加载高精度索引占用数十 GB 内存，迫使团队不得不升级昂贵的服务器集群以维持服务。\n- **数据更新困难**：商品上下架或价格变动导致向量特征改变时，重建索引需要停机维护数小时，无法支持业务所需的实时性。\n- **开发集成复杂**：引入重型依赖库增加了环境配置难度，且缺乏灵活的 Python 接口，阻碍了算法工程师的快速迭代验证。\n\n### 使用 hnswlib 后\n- **查询速度飞跃**：利用 HNSW 图的近似最近邻搜索特性，将千万级数据的检索时间压缩至 5 毫秒以内，实现丝滑的实时推荐体验。\n- **内存大幅优化**：凭借轻量级的头文件设计和高效的图结构，内存占用降低约 60%，直接在现有普通服务器上即可流畅运行。\n- **支持动态增删**：借助其增量构建和元素标记删除功能，新商品向量可即时插入索引，旧商品可在线标记替换，无需重启服务。\n- **无缝 Python 集成**：通过简洁的 Python 绑定直接调用 C++ 核心性能，算法团队能快速原型开发并轻松部署到生产环境。\n\nhnswlib 通过极致的速度与低资源消耗，让大规模向量实时检索从“昂贵的基础设施挑战”变成了“开箱即用的标准能力”。","https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fnmslib_hnswlib_f86c0bd3.png","nmslib","https:\u002F\u002Foss.gittoolsai.com\u002Favatars\u002Fnmslib_2e38bc3a.png",null,"https:\u002F\u002Fgithub.com\u002Fnmslib",[80,84,88,92],{"name":81,"color":82,"percentage":83},"C++","#f34b7d",76.6,{"name":85,"color":86,"percentage":87},"Python","#3572A5",21.7,{"name":89,"color":90,"percentage":91},"CMake","#DA3434",1.6,{"name":93,"color":94,"percentage":95},"Makefile","#427819",0.1,5153,807,"2026-04-02T20:06:49","Apache-2.0","Linux, macOS, Windows","未说明",{"notes":103,"python":101,"dependencies":104},"该工具为仅头文件（header-only）的 C++ 实现，除 C++11 标准外无其他外部依赖。支持通过 Python 绑定使用，利用 GIL 限制可能在多线程过滤搜索时影响性能。支持增量索引构建、元素更新及逻辑删除。在 Windows 上使用 MSVC 编译时需注意 SSE 指令集的支持配置。",[105,106],"numpy","C++11 编译器",[14],"2026-03-27T02:49:30.150509","2026-04-06T09:43:32.880859",[111,116,121,126,131,136],{"id":112,"question_zh":113,"answer_zh":114,"source_url":115},13645,"导入 hnswlib 时出现 'Illegal instruction (core dumped)' 错误怎么办？","这通常是由于系统环境差异或缓存了不兼容的二进制文件导致的。解决方法是卸载并强制重新安装，务必使用 --no-cache-dir 参数以避免 reinstall 相同的损坏版本。\n具体命令如下：\npip uninstall hnswlib\npip install --no-cache-dir hnswlib\n此外，该问题在 0.8.0 版本中已修复，如果使用的是 0.7.0 或更早版本，建议升级。","https:\u002F\u002Fgithub.com\u002Fnmslib\u002Fhnswlib\u002Fissues\u002F17",{"id":117,"question_zh":118,"answer_zh":119,"source_url":120},13646,"遇到 'module 'hnswlib' has no attribute 'Index''  AttributeError 错误如何解决？","最常见的原因是用户将自己的 Python 脚本文件命名为了 'hnswlib.py'，导致 Python 优先导入本地文件而不是安装的库。\n解决方法：检查当前目录下是否有名为 hnswlib.py 的文件，将其重命名为其他名称（例如 my_script.py），然后重新运行代码即可。","https:\u002F\u002Fgithub.com\u002Fnmslib\u002Fhnswlib\u002Fissues\u002F181",{"id":122,"question_zh":123,"answer_zh":124,"source_url":125},13647,"如何合并不同的索引文件（index.bin）？","目前库中没有直接合并两个 .bin 文件的函数。变通方法是：分别从不同的索引文件中读取数据项（使用 get_items() 方法），然后将这些数据项添加到一个新的索引实例中（使用 add_items() 方法）来实现逻辑上的合并。","https:\u002F\u002Fgithub.com\u002Fnmslib\u002Fhnswlib\u002Fissues\u002F157",{"id":127,"question_zh":128,"answer_zh":129,"source_url":130},13648,"如何处理特征向量中的缺失值（missing values）？","目前 hnswlib 原生不支持在查询向量或训练数据中直接处理缺失值（即维度少于 d 的情况）。维护者表示尚未添加此功能，但如果社区有人愿意贡献，可以在不损失性能的前提下实现该功能。目前用户需要自行在传入库之前处理缺失值（如填充或降维）。","https:\u002F\u002Fgithub.com\u002Fnmslib\u002Fhnswlib\u002Fissues\u002F90",{"id":132,"question_zh":133,"answer_zh":134,"source_url":135},13649,"如何设置 M 和 efConstruction 参数以获得最佳准确率？","M 和 efConstruction 没有绝对的“最佳”固定值，通常需要经验调整。\n1. M 值：通常在 6 到 48 之间效果较好。对于非常大的数据集（如数百万级），可能需要更大的 M，但如果结果不理想，首先应检查代码逻辑（如索引跟踪错误）。\n2. efConstruction：这是一个经验参数，范围通常在 10-200 之间。选择原则是：当搜索参数 ef 等于 efConstruction 且 k=M 时，召回率（recall）应接近 1.0（例如 0.9-0.95）。如果为了高召回率需要将 ef 设得很高（如 1000），而 efConstruction 很低（如 80），说明构建时的搜索不够准确，应适当增加 efConstruction 以优化查询时间。","https:\u002F\u002Fgithub.com\u002Fnmslib\u002Fhnswlib\u002Fissues\u002F164",{"id":137,"question_zh":138,"answer_zh":139,"source_url":140},13650,"efConstruction 和 efSearch (ef) 参数有什么区别？如何选择？","efConstruction 用于构建索引阶段，efSearch (常简写为 ef) 用于查询阶段。\n虽然它们作用阶段不同，但原理相似。选择 efConstruction 的一个好方法是：调整该值，直到使用 ef=efConstruction 进行查询且 k=M 时，召回率接近 1.0。如果构建时设置的 efConstruction 过低，会导致生成的图结构不够精确，从而在查询时需要极高的 ef 值才能达到高召回率，这会降低查询效率。","https:\u002F\u002Fgithub.com\u002Fnmslib\u002Fhnswlib\u002Fissues\u002F3",[142,147,152,157,162,167,172,177,182,187],{"id":143,"version":144,"summary_zh":145,"released_at":146},72491,"v0.9.0","修复了使用过滤器进行暴力搜索时的错误结果（#514），由 [@lukaszsmolinski](https:\u002F\u002Fgithub.com\u002Flukaszsmolinski) 完成  \n修复了 BFIndex 中缺失的归一化检查（#514），由 [@lukaszsmolinski](https:\u002F\u002Fgithub.com\u002Flukaszsmolinski) 完成  \n当可用元素少于 k 个时抛出异常（#514），由 [@lukaszsmolinski](https:\u002F\u002Fgithub.com\u002Flukaszsmolinski) 完成  \n移除未使用的变量（#531），由 [@lulyon](https:\u002F\u002Fgithub.com\u002Flulyon) 完成  \n将 README 中的余弦相似度改为距离度量，由 [@yurymalkov](https:\u002F\u002Fgithub.com\u002Fyurymalkov) 完成  \n\n## 变更内容\n* 修复暴力搜索结果、更新 CI，并将版本号提升至 0.9.0，由 @ilyajob05 在 https:\u002F\u002Fgithub.com\u002Fnmslib\u002Fhnswlib\u002Fpull\u002F658 中完成\n\n\n**完整变更日志**：https:\u002F\u002Fgithub.com\u002Fnmslib\u002Fhnswlib\u002Fcompare\u002Fv0.8.0...v0.9.0","2026-03-28T22:48:34",{"id":148,"version":149,"summary_zh":150,"released_at":151},72492,"v0.8.0","亮点：\n\n* 多向量文档搜索和 epsilon 搜索（目前仅支持 C++）\n* 默认情况下不进行统计聚合，这加快了多线程搜索的速度（似乎也确实很少有人使用该功能：[Issue #495](https:\u002F\u002Fgithub.com\u002Fnmslib\u002Fhnswlib\u002Fissues\u002F495)）。\n* 各种错误修复和改进\n* `get_items` 现在新增了 `return_type` 参数，可选择 'numpy' 或 'list'\n\n特别感谢以下贡献者：\n\n1. [Dmitry Yashunin (dyashuni)](https:\u002F\u002Fgithub.com\u002Fdyashuni) - 主导实现了自定义停止条件、多向量搜索和 epsilon 搜索功能，并进行了多项代码优化和错误修复。\n2. [Alexander Vieth (alxvth)](https:\u002F\u002Fgithub.com\u002Falxvth) - 贡献了解决全局链接问题以及改进 CI 环境中 Mac 系统设置的工作。\n3. [Taras Tsugrii (ttsugriy)](https:\u002F\u002Fgithub.com\u002Fttsugriy) - 专注于修复构建警告、增强暴力移除点的功能并改善内存管理。\n4. [aurora327](https:\u002F\u002Fgithub.com\u002Faurora327) - 在函数中实现了更高效的 AVX512 指令集。\n5. [Étienne Mollier (emollier)](https:\u002F\u002Fgithub.com\u002Femollier) - 添加了对参数 'M' 的上限限制，并修正了一个拼写错误。\n6. [Johan Rade (jrade)](https:\u002F\u002Fgithub.com\u002Fjrade) - 解决了使用 Visual Studio 编译时的链接错误。\n7. [James Melville (jlmelville)](https:\u002F\u002Fgithub.com\u002Fjlmelville) - 处理了重新排序警告、循环中的符号不匹配问题，并通过宏统一了错误处理方式（详情见 #508）。\n8. [stephematician](https:\u002F\u002Fgithub.com\u002Fstephematician) - 解决了 GNU 编译器中的初始化顺序警告。\n9. [moritz-h](https:\u002F\u002Fgithub.com\u002Fmoritz-h) - 添加了 CMake 安装目标，并设置了 CMake 版本范围。\n10. [drons](https:\u002F\u002Fgithub.com\u002Fdrons) - 实现了精确控制内存占用的函数，并修复了内存泄漏问题。\n11. [Atsushi Tatsuma (yoshoku)](https:\u002F\u002Fgithub.com\u002Fyoshoku) - 为 BaseFilterFunctor 类添加了缺失的虚析构函数。","2023-12-03T03:49:47",{"id":153,"version":154,"summary_zh":155,"released_at":156},72493,"v0.7.0","**版本 0.7.0**\n\n* 增加了过滤功能的支持（#402、#430），由 [@kishorenc](https:\u002F\u002Fgithub.com\u002Fkishorenc) 实现\n* 增加了 Python 接口用于过滤（但请注意，其性能受限于 GIL）（#417），由 [@gtsoukas](https:\u002F\u002Fgithub.com\u002Fgtsoukas) 实现\n* 增加了将标记为删除的元素替换为新插入元素的功能（以控制索引大小，#418），由 [@dyashuni](https:\u002F\u002Fgithub.com\u002Fdyashuni) 实现\n* 修复了更新\u002F插入操作中的数据竞争和死锁问题，并增加了多线程操作的压力测试（#418），由 [@dyashuni](https:\u002F\u002Fgithub.com\u002Fdyashuni) 实现\n* 文档、测试、异常处理及代码重构工作（#375、#379、#380、#395、#396、#401、#406、#404、#409、#410、#416、#415、#431、#432、#433），由 [@jlmelville](https:\u002F\u002Fgithub.com\u002Fjlmelville)、[@dyashuni](https:\u002F\u002Fgithub.com\u002Fdyashuni)、[@kishorenc](https:\u002F\u002Fgithub.com\u002Fkishorenc)、[@korzhenevski](https:\u002F\u002Fgithub.com\u002Fkorzhenevski)、[@yoshoku](https:\u002F\u002Fgithub.com\u002Fyoshoku)、[@jianshu93](https:\u002F\u002Fgithub.com\u002Fjianshu93)、[@PLNech](https:\u002F\u002Fgithub.com\u002FPLNech) 完成\n* 全局链接设置（#383），由 [@MasterAler](https:\u002F\u002Fgithub.com\u002FMasterAler) 实现；在 MSVC 中使用 USE_SSE（#408），由 [@alxvth](https:\u002F\u002Fgithub.com\u002Falxvth) 实现","2023-02-07T20:10:08",{"id":158,"version":159,"summary_zh":160,"released_at":161},72494,"v0.6.2","* 修复了大型 pickle 文件保存时的一个 bug。大于 4GB 的 pickle 文件可能会损坏。感谢 Kai Wohlfahrt 的报告。\n* 感谢 ([@GuyAv46](https:\u002F\u002Fgithub.com\u002FGuyAv46))，hnswlib 中的内积计算现在在不同架构（SSE、AVX 等）上更加一致。","2022-02-14T22:10:46",{"id":163,"version":164,"summary_zh":165,"released_at":166},72495,"v0.6.1","感谢 ([@tony-kuo](https:\u002F\u002Fgithub.com\u002Ftony-kuo))，hnswlib 的 AVX512 和 AVX 构建版本与较旧的 SSE 以及非 AVX512 架构不兼容。\n感谢 ([@psobot](https:\u002F\u002Fgithub.com\u002Fpsobot))，现在在向 get_items 方法传递标量时，不会再出现段错误，而是会显示一条清晰的提示信息。\n感谢 ([@urigoren](https:\u002F\u002Fgithub.com\u002Furigoren))，hnswlib 现在提供了一个惰性索引创建的 Python 封装。","2022-02-06T22:41:01",{"id":168,"version":169,"summary_zh":170,"released_at":171},72496,"v0.6.0","感谢 (@dyashuni)，hnswlib 现在使用 GitHub Actions 进行持续集成；在某些包含删除操作的场景下，搜索速度有所提升。unmark_deleted(label) 现在也已成为 Python 接口的一部分（注意，现在对重复删除会抛出异常）。\n感谢 (@slice4e)，我们现在支持 AVX512 指令集；感谢 (@LTLA)，该库的 CMake 接口现已更新。\n感谢 (@alonre24)，我们现在提供了暴力搜索的 Python 绑定，并附带了用于调整召回率的示例：TESTING_RECALL.md。\n感谢 (@dorosy-yeong)，我们在处理大量已删除元素和较大 K 值时的一个 bug 已被修复。","2021-12-09T22:30:29",{"id":173,"version":174,"summary_zh":175,"released_at":176},72497,"v0.5.2","错误修复和改进。特别感谢：\n[@marekhanus](https:\u002F\u002Fgithub.com\u002Fmarekhanus) 修复了缺失的参数问题，在 Travis 中增加了对 Python 3.8 和 3.9 的支持，改进了 Python 封装并修正了拼写及代码风格；\n[@apoorv-sharma](https:\u002F\u002Fgithub.com\u002Fapoorv-sharma) 修复了插入\u002F删除逻辑中的 bug；\n[@shengjun1985](https:\u002F\u002Fgithub.com\u002Fshengjun1985) 简化了内存重新分配的逻辑；\n[@TakaakiFuruse](https:\u002F\u002Fgithub.com\u002FTakaakiFuruse) 改进了 `add_items` 的描述；\n[@psobot ](https:\u002F\u002Fgithub.com\u002Fpsobot) 改进了错误处理；\n[@ShuAiii](https:\u002F\u002Fgithub.com\u002FShuAiii) 报告了 Python 接口中存在的 bug。","2021-06-30T05:20:31",{"id":178,"version":179,"summary_zh":180,"released_at":181},72498,"v0.5.0","新增了对索引序列化的支持，支持 PEP-517 和 PEP-518 构建方式，进行了小幅性能优化，修复了一些 bug，并改进了文档。\n`setup.py` 文件现已移至项目根目录。\n\n特别感谢 @dbespalov、@dyashuni、@groodt、@uestc-lfs、@vinnitu、@fabiencastan、@JinHai-CN、@js1010！","2021-01-29T03:38:10",{"id":183,"version":184,"summary_zh":185,"released_at":186},72499,"v0.4.0","感谢 Apoorv Sharma @apoorv-sharma，hnswlib 现在支持真正的元素更新（接口保持不变，但在更新元素嵌入时，性能和内存使用不应下降）。\n\n感谢 Dmitry @2ooom，对于向量维度不是 4 的倍数的情况，hnswlib 的性能得到了提升。\n\n修复了若干 bug，并进行了其他更新（@xiejianqiao、@Shujian2015、@mohamed-ali、@hussamaa）。\n\n衷心感谢所有贡献者！","2020-06-27T04:33:29",{"id":188,"version":189,"summary_zh":190,"released_at":191},72500,"v0.3.4","修复了大量 bug 和错误提示。\n新增了将元素标记为已删除的功能。\n停止对旧索引的支持。\n\n非常感谢所有贡献者！","2019-12-16T23:37:01"]