经过长时间紧锣密鼓的开发,AI 原生数据库 Infinity 已于2023年12月21日正式开源了。AI 原生数据库,定义为专门服务大模型的数据库,其具体场景即为 RAG(Retrieval Augmented Generation)。未来企业大模型应用架构的基础设施层面,将只需要一个 AI 原生数据库配合一个大模型(当下是 LLM 大语言模型,未来还会有多模态模型),就可以完全满足企业对于 AI 场景的主要需求,包括 Copilot、搜索、推荐、对话机器人等。来自企业内部的各种数据,比如文档、普通数据库(包括 OLTP 和 OLAP 等)、API、日志,还有非结构化数据,都可以集成进一个 AI 原生数据库;AI 原生数据库将业务查询得到的数据交给大模型,再由大模型生成最终结果返回给具体应用。
向量无法单独解决企业 AI 应用的落地
也许你会有这样的疑问:AI 原生数据库究竟是什么?它不过是向量数据库的新瓶装旧酒吗?当然不是!AI 原生数据库不同于向量数据库,向量只是大模型配套基础设施的必要而非充分条件。这是因为向量只能提供语义召回能力,无法提供精确查询能力,而后者恰恰是企业 AI 应用的核心需求。
举例来说,根据权限表过滤出具备相应访问权限的内容,这样一个简单却常见的需求,就无法单独靠向量实现。当然,当下流行的向量数据库已经具备了简单的过滤功能,似乎也可以服务这样的场景。但这就需要通过 ETL(Extract-Transform-Load)工作,把权限字段写到向量数据库的标量字段来提供过滤,这意味着三件事:
- 需要为简单的需求引入高成本的 ETL。
- 原始数据的更新不能及时体现到业务。
- 引入不必要的数据膨胀。权限过滤仅仅是一个例子。如果完全依赖 ETL 解决来自不同数据源的其他各种查询,那相当于在向量数据库内保存一张带有全部过滤字段的宽表。除了上述的系统维护和数据更新问题之外,这也是一种不必要的数据膨胀。在大多数情况下,企业数字化系统架构内只有离线场景的数据仓库才有引入宽表的必要。
再比如,基于 RAG 的应用大多数都需要具备精确召回能力。举例来讲,当用户针对 PDF 文档内某张表格内的内容进行提问时,仅仅依赖向量是无法提供准确回答的,这就会导致由 LLM 返回的答案包含幻觉。所以,只有依靠搜索引擎才能实现精确召回。
因此,配套 AI 的基础设施,其实是伴随了三代的演进:
- 第一代,以统计模型和数据挖掘为基础,基础设施的配套代表就是搜索引擎。因此配套的企业 AI 应用架构,往往是以 Elasticsearch,再加上 MySQL 等数据库共同支撑业务体系。
- 第二代,深度学习催生了向量搜索的需求,也催生了向量数据库这个品类。由于向量数据库仅仅提供单一的向量搜索能力,在构建企业信息系统时,还需要搭配各类数据库、数据仓库等,形成所谓的 AI 中台。
- 第三代,AI 进化到大模型之后解锁了更多场景。因此,它需要的不再是一款单纯的向量数据库,而是能够同时提供向量搜索、全文搜索和结构化数据检索,可以支撑大模型对于复杂数据的获取需求,能够配合大模型共同支撑起企业门户业务需求的基础软件产品。
传统数据库/湖仓加向量插件?
比如,传统的关系型数据库 PostgreSQL 就提供了 pgvector 插件,可以轻轻松松具备向量能力。但是,AI 原生数据库并不能通过传统数据库增加向量搜索能力来得到。下面,我们就先来看看 PostgreSQL 能否解决 AI 的 RAG 场景下的几个基本问题,相信读者很快也可以自行得出答案:
- 如何实现精确召回所需的全文搜索能力?
PostgreSQL 是一款 OLTP 数据库,OLTP 的核心设计目标是确保数据写入的 ACID,而这跟向量和全文搜索都不相关。尽管 PostgreSQL 有全文搜索的功能,而且已经存在十多年了,为何至今企业仍然采用 Elasticsearch 而不是 PostgreSQL 进行全文搜索呢?这是因为PostgreSQL 的全文搜索只适合小数据规模的简易搜索。一款搭配 RAG 的 AI 原生数据库需要胜任各种数据规模,进行可定制的相关度排序,尤其还需要与向量进行多路召回的融合排序,这些都是PostgreSQL没有办法胜任的。
- 如何兼顾伸缩性、成本等因素?
PostgreSQL 是个单机数据库,要提供分布式场景下的各种一致性约束,目前主流是采取 Share-nothing 方式的分库分表来解决伸缩性问题。而向量搜索和全文搜索,则是完全不同的约束条件和性能优化目标,完全没有必要采用这些复杂的技术来解决伸缩性问题。因此,让一款 OLTP 数据库顺道做一些事情,并非不可以,但兼职做,就一定没有专职做得好,当前的大模型时代需要的是一款专业数据库,而非传统数据库加插件的缝缝补补。
另一类工作是在数仓上为添加向量搜索能力。这类工作具备一定的合理性,但设计目标依然是有冲突的。数据仓库,传统上来说,是服务离线场景的,例如运行一个复杂的 SQL,跑几十分钟,乃至几个小时之后,给出报表,然后给公司内部看。尽管数据仓库从技术路线上有实时数仓的概念,但它们从使用场景上来讲,并非在线场景,因此并不强调并发。可是向量搜索,它所服务的搜索,推荐,对话机器人,都是高并发的在线业务场景,因此把强调高并发的向量,跟强调高吞吐却低并发的数仓结合在一起,这在场景上是割裂的。
因此,正如下面这个图的蓝色框内所示,Infinity 是一款结合 AI 基础设施和 Data 基础设施的产品,它面向的是在线场景,满足未来大模型对企业内部数据基础设施的一切需求:
Infinity 的系统架构
如上图所示,Infinity 包含存储层和计算层两大模块:
- 存储层:
- 列存(columnar storage):Infinity 的默认存储是一个列存引擎,主要服务于结构化数据检索,且它可以保证数据存储的 ACID。
- ANN 索引(Approximate Nearest Neighbor Index):即向量索引,用于服务向量搜索。Infinity 目前提供 IVF 和 内存优化的HNSW 两类索引:前者服务内存受限场景,后者服务高性能场景。Infinity 的 HNSW 索引采用了局部量化技术,可以在内存占用相较标准HNSW算法小的多情况下,提供远高于其他向量索引的搜索性能。此外,ANN 索引仅仅是针对 Infinity 表的一个向量类型列构建的索引,因此 从设计机理上Infinity 可以包含任意多的向量列,而非普通向量数据库只能提供单一向量列的能力,因此 Infinity可以很容易支持多向量查询。
- 倒排索引(Inverted Index):用于服务全文检索以及结构化数据检索。倒排索引包含两部分:一部分是针对文本类型的全文索引,默认提供基于 BM25 的相关度排序功能,也提供短语查询等常见的精确召回能力;另一部分是针对结构化数据的次级索引,提供高性能过滤能力。
- 计算层:
- Parser:为了方便 AI 开发者,Infinity 主要对外提供的是 Pythonic API。此外,Infininty还提供兼容 PostgreSQL 协议的 SQL 方言。因此,Infinity 使用全新实现的 Parser 来提供对这两种方言的支持。
- 执行器:Infinity 针对不同类型的数据,不同的数据分布,提供了多种多样的索引。它能够根据查询需求动态的决定分配哪些资源哪种存储提供哪些查询。例如,对于结构化查询能力来说,可以选择列存,也可以选择倒排索引。如果用户对延迟敏感,则可以使用多个计算单元,采用并行查询的执行逻辑;如果用户对并发敏感,就只采用单个计算单元,采用基于倒排索引的方式来执行,Infinity 的执行器会根据需要动态作出最优选择。具体来说,Infinity 采用了基于 Push 的流水线执行计划,但更进一步地改进使之同时能适应大吞吐查询和大并发查询的工作负载。除此之外,Infinity 还实现了一些重要的算子,例如 Fusion 融合算子,它负责多路召回——采用向量搜索返回的数据,跟采用全文搜索返回的数据,还有结构化过滤的数据,它们之间如何选择,如何排序,在 Infinity 内部处理完毕这个算子,既高效又便捷,避免了在多个数据库之间进行联邦搜索(Federated Search)造成的低效甚至结果错误。
Infinity 提供业界最优的向量搜索性能
Infinity 采用 C++ 20 标准开发,确保了最优的执行路径,在各种创新算法的共同加持下,Infinity 在向量搜索性能上超越了所有已知向量数据库,在八核的机器和百万 SIFT 向量数据集上,高并发场景下 Infinity 可以轻松达到 1 万QPS,单个客户端场景下查询响应延迟则是 0.1 毫秒级,且内存占用小。
此外,Infinity 还引入了 C++ Modules 提高开发效率,是最先采用 C++ Modules 的大型开源项目。这使得在普通个人笔记本上编译 Infinity 二十万行代码及其依赖的上百万行 C++ 代码的时间减少到数分钟。极大节约了传统 C++ 程序员因修改一行头文件,动辄要重新编译数百个文件,耗时十几分钟的痛点。最后,欢迎大家一起加入 Infinity 开源社区贡献代码,为 Infinity 早日 GA 添砖加瓦。
项目地址:
https://github.com/infiniflow/infinity