随着人工智能技术在业务中的渗透,我们逐渐意识到:AI 不仅是提升效率的工具,更是重构数据处理与消费方式的核心驱动力。在这一背景下,我们思考:能否构建一款「AI + Data」一站式融合的数据引擎?它不仅能够统一处理文本、音视频等非结构化数据与传统结构化数据,还能为算法工程师提供流畅的数据开发体验,实现数据处理与 AI 模型无缝衔接,并能确保数据处理负载与在线服务负载完全隔离。这是 2024 年末字节跳动启动 DataMind 项目的初衷。
本文整理自字节跳动 DataMind 负责人郭泽晖在 Doris Summit 2025 中的演讲内容,并以演讲者第一视角进行叙述。
📢 号外:Doris Summit 2025 全部回放及 PPT 资料现已就绪,可前往大会官网进行资料下载 / 回放观看:doris-summit.org.cn
在项目启动前,我们评估了多种市面上的开源方案,但未能找到完全符合 AI + Data 引擎需求的产品。因此,我们决定选择一款优秀的 OLAP 数据库,并在此基础上融合和增强 AI 功能。Apache Doris 凭借完善的功能、卓越的 OLAP 性能、丰富的生态体系、活跃的社区氛围及良好的产品口碑吸引了我们的注意。
与此同时,我们了解到社区也在积极探索 Doris 与 AI 能力的结合,因此决定在 Apache Doris 基础上二次开发,打造一站式引擎——DataMind。这些能力包括:
Hybrid Search:将基于文本相似性、语义相似性、业务规则匹配这三种能力集成至 Doris 中,并在此基础上补齐了向量检索及 Tablet-level BM25 能力。(详见章节二)。
AI Function:基于 Doris 补齐了 AI_QUERY 和 TEXT_EMBEDDING ,并支持了 Python UDF。(详见章节三)
GraphRAG :在基于 Doris 的 DataMind 产品上构建了 GraphRAG,应用层研发团队能够更便捷地接入新的 AI 能力,缩短研发周期。(详见章节四)
目前,我们已将部分 AI 融合的实践成果贡献给开源社区,大家可从 Apache Doris 4.0 版本中关注。
这些能力不仅是 Datamind 的重要组成,也是构建企业级 AI 问数平台奠定了坚实的技术基础。后文将逐一展开其设计思路、实现路径与优化实践。
AI 场景下典型的混合搜索的架构可以概括为三种搜索方式:基于文本相似性、语义相似性、业务规则的匹配。这三路的搜索结果会在后端统一排序,排序方法依赖自训练的模型,分为粗排和精排两个阶段。粗排模型可提高处理性能,精排模型实现更优的重排序效果,平衡整体开销。

我们希望将这三类搜索能力集成至基于 Doris 的 DataMind 引擎之中,让用户只需导入一份数据,并在完成必要的处理及索引构建后,即可直接上线服务,无需介入其他三方工具。为实现这一目标,团队基于 Doris 补充了向量索引和 BM25 打分函数这两项核心能力。
我们基于 Faiss (Facebook 开源的 AI 相似性搜索工具)实现了 HNSW 与 IVF_PQ 两种 ANN 算法的向量索引。HNSW 在大规模数据集上性能表现更优,但资源开销较大; IVF_PQ 在大规模数据集上,成本与性能表现更加均衡。
向量索引支持与其他索引条件组合使用。比如,可将倒排索引的结果通过 Faiss 提供 IDSelector 接口传递到底层 ANN 算法实现上以控制搜索过程。基本原理是:倒排索引首先检索匹配行号的 Bitmap,这一 Bitmap 被传递给 Faiss 库。当进行向量搜索时,Faiss 会将搜索范围限制,最终输出 TopN 行号结果,代表融合后的结果集。当倒排索引在第一阶段筛选出的数据量较少时,会跳过向量索引进行暴力计算,这样耗时更短、时间更精准。

BM25 是一种用于信息检索的排名函数,用于衡量查询与文档的相关性。它基于词频(t)和文档长度进行加权计算,同时考虑逆文档频率(IDF)以惩罚常见词。在整个公式中,需重点关注总文档数 N 和文档频率 DF 等全局统计信息,这些信息直接影响实现的难度。(更多信息可自行搜索查阅)
在 Doris 的设计中,一个 segment 对应一个倒排索引的解决方案,因此在 segment 级别实施 BM25 较为简单,系统可以基于每个 segment 的统计信息(如总文档数 N 和文档频率 DF)计算每一行的得分。然而,合并小 segment 可能导致统计信息变化,从而影响 BM25 得分,造成用户评分波动,这在生产环境中不可接受。
为了避免此问题,团队将 BM25 公式提升至 tablet 级(tablet-level)。所有全局统计信息(包括 N 和 DF)需基于整个 tablet 聚合,以保持得分结果的一致性。
以 Merge on Write / Merge on Write 为例:

在 Scan 算子初始化阶段:系统会预先搜索用于 BM25 计算的 tablet 级统计信息。每个 segment 会被依次扫描,并以流式方式输出数据块。
数据收集阶段:在处理每个 segment 之前,需计算完整的 tablet 级统计信息。Scan 算子初始化时,系统使用相应搜索条件访问每个 segment 的解决方案。此过程中产生的文件操作、数据读取和内存命中等结果构成搜索上下文信息。同时,与搜索相关的对象会被缓存,以避免重复产生 IO 开销。
索引查找及数据读取:当正式进入某个索引后,索引搜索将基于此前收集的 tablet 级统计信息,为命中的每一行计算分数。最终,计算所得的分数通过虚拟列的迭代器返回到 segment,随数据块输出。
在补充了向量索引和 BM25 能力后,我们面临一个新问题:在混合搜索框架中,涉及的函数并非传统意义上在计算层基于输入直接进行求值,而是必须在索引检索的过程中计算出结果,因此需要设计一套特殊的投影下推流程,具体实现如下:

在执行计划层,我们将相关函数替换为虚拟列,并将这些虚拟列下推至 OlapScanNode。OlapScanNode 携带虚拟列的信息,将其传递到接近索引计算与查询块存储逻辑的执行路径中。
在索引计算过程中,系统基于这些虚拟列计算向量距离分数和 BM25 相似性分数,并将结果填充回对应的 block。最终,带有虚拟列计算结果的 block 由 Scan 算子输出,并传递至下游算子,以自然衔接的执行计划完成整个检索流程。
在 AI Function 上,主要基于 Doris 补齐了 AI_QUERY 和 TEXT_EMBEDDING 两种函数。
该函数用于调用大模型并能较好地处理非结构化文本这类数据,将其转化为结构化数据,再进行传统分析。例如,对于一张客户评价表,可以让大模型为每条评价打分并分类,如好评输出 1、差评输出 0,通过统计即可得出好评与差评的大致数量。
WITH reviews AS (SELECTAI_QUERY('volcengine/Doubao-pro-128k-240628', concat('判断这条产品评价是好评还是差评,好评输出1,差评输出0:', review_txt)) AS review_typeFROM customer_reviews) SELECT review_type, count(*) AS cntFROM reviewsGROUP BY review_type
该函数主要有两个阶段:
数据清洗阶段:在 AI 清洗过程中生成对应向量并构建向量索引。
数据查询阶段:此阶段提供两种使用方式。第一种是由用户的应用层代码自行生成查询向量,并作为参数传入 SQL 进行搜索,该方式需传入较长的向量 float 数组,会增加优化器的解析开销。第二种方式是直接调用 TEXT_EMBEDDING 函数,将查询文本传入并执行搜索,这种方法更为便捷,且性能更佳。
SELECTcontent,APPROX_COSINE_SIMILARITY(TEXT_EMBEDDING('volcengine/Doubao-embedding-240715', 'Doris Summit'),content_vec_col) AS scoreFROM my_tableORDER BY scoreLIMIT 7;
除上述标准函数外,我们基于 Doris 支持了 Python UDF,以满足自部署模型的需求,包括 Rerank 模型、Embedding 模型、甚至大模型的访问需求,以及依赖 Python 库进行非结构化数据处理的需求场景。
Python UDF 的核心设计主要包含几个关键点:
多进程架构:旨在解决 UDF 之间的隔离问题,避免 Python 的全局解释器锁(GIL)。每个 Python UDF 能通过虚拟环境(venv)实现依赖隔离。
生命周期绑定:执行 Python 的子进程与 Doris 的 pipeline task 生命周期绑定。当一个 pipeline task 生成时,相应的子进程也会被创建,并在任务结束时进行清理。这种设计使得并发模型与 Doris 的计算引擎密切结合,用户只需调整 Doris 的并发参数即可管理 Python UDF 的执行并发,简化了维护工作。
数据传输和序列化:主进程与子进程之间的数据传输通过管道进行。支持 Python 原生对象输入输出的版本采用 Python 的 Marshal 机制进行序列化。

生命周期绑定示意图
如下方代码示例,示例中展示了混合搜索(向量 + 全文检索)的应用,两个检索通过用户自研的 Python UDF 模型进行重排序,最终使用 Hybrid Search 进行数据摄取。在 AI Function 和 Python UDF 的加持下,用户只需通过一条简单的 SQL 语句即可串联整个业务搜索流程及数据处理流程,使用十分便捷。
CREATE FUNCTION predict_class(ARRAY) RETURNS INTPROPERTIES ("file"="https://cloud-storage/obj/datamind/pyudf.zip","symbol"="predict_class","type"="PYTHON_UDF");
WITH channel_1 AS (SELECTcontentFROM my_tableORDER BYAPPROX_COSINE_SIMILARITY(py_udf_embed('Doris Summit'), content_vec_col) DESCLIMIT 7),channel_2 AS (SELECTcontentFROM my_tableWHERE MATCH_ANY(content, 'Doris Summit')ORDERBYBM25() DESCLIMIT 7)SELECTcontentFROM (SELECT content FROM channel_1UNION ALLSELECT content FROM channel_2) tORDER BY py_udf_score('Doris Summit', content) DESCLIMIT 7;
GraphRAG 是一种结合图数据库与 RAG(Retrieval-Augmented Generation)技术。推动 DataMind 集成 GraphRAG 功能的原因是,我们在推广 AI 功能时发现多个业务团队对此有需求。与标准 RAG 相比,GraphRAG 的实现过程更为复杂,需要在基础 AI 能力上进一步构建。
构建阶段:该阶段的输入为文档或分割成的片段(chunk)。利用大模型(AI Function)进行实体抽取——从文档中提取出关键信息,实体之间的关系可以看作是图中的边,每条边具有一定的权重,这些权重由大模型自动识别,提取的实体及其描述经过向量化后存储,以构建索引。
此外,图结构和边的描述也会存储在一张表中。基于该图,系统利用 Search 发现算法(如 Lighting)进行聚类,将相似的实体归类为一个 Search,并生成 Search 报告。

查询阶段:在检索过程中,首先将 Query 转换为向量,该向量用于 Search 实体,以找到与之相关的 Top-K 实体。得到 TopK 实体后,系统将召回它们相关的边,这些边包含与实体相关的描述和信息,以及这些实体关联的报告和原始文档的片段。在有限的上下文内,系统会按优先级拼接相关内容,形成最终上下文,随后将其输入 AI 以生成回答。

基于 Apache Doris 的 DataMind 产品上如何构建 GraphRAG 呢?整体设计分为多层,如下图所示:

最底层是表结构的设计,包括实体表、Search 表以及用户自定义的源数据表等。在此基础上,通过一系列函数,包含用于文档切分的函数、Leiden 聚合函数等等,最后结合 ETL SQL、Query SQL 等,共同实现 GraphRAG 的构建与查询流程。
由于底层 SQL 相对复杂,团队在这些 SQL 上封装了 Go、Python 与 Java 的 SDK,以方便用户使用。用户只需调用如 build 或 import 等接口即可完成数据导入与构建,再通过 query 接口实现查询能力。这样一来,应用层研发能够更快速地接入新的 AI 能力。只需使用 Apache Doris 数据库并结合团队提供的 SDK,即可直接将业务流程跑通并验证效果。
企业级 AI 问数是当前行业内较为经典且热门的探索方向。行业内普遍采用 NL2SQL 直接查询 Apache Doris 等数据库的模式。那么,字节是如何落地的呢?
首先,我们基于 Doris 构建了湖仓一体的数据架构,以数据湖为中心,外部业务系统或企业内部信息系统(如 RDS、API 取数),数据经过 DTS 等工具摄入,最终沉淀在云存储中,呈现为传统 Hive 的原生 Parquet 格式。随后,数据通过 Spark 或 Flink 进行 ETL 清洗,遵循标准的 Lambda 架构,最终生成可供消费的数据,并存储至 OLAP 引擎 Apache Doris 以实现查询加速。

若要利用 AI 进行数据消费,以实现类似企业智能体的功能,它需要访问所有企业信息系统的数据。因此,我们期望的理想架构处理流程应如下图:

具体流程:AI 问数应用通过 Data Agent 调用 NL2SQL 这类外部工具,Data Agent 采用 Plan Execute 或 React 模型规划执行路径,需要元数据以及依据业务自定义的语义模型——简单理解为表字段的描述,基于这些信息,Data Agent 生成取数 SQL,并发给 Apache Doris(即 DataMind) 加速执行,最终将数据返回到 AI 问数应用层。在这其中,Apache Doris 主要作用是将湖上的数据同步到其内部进行查询加速。
而这种理想处理方式面临数据安全性及查询延迟等问题,比如:
数据湖中的数据量庞大,全部同步到 Apache Doris 并不现实,且敏感数据也不宜全量同步。
当数据加速到 DataMind 后,Apache Doris 的内表与外表存在差异。加速会影响 SQL 的 Catalog 语法,例如加速后,外表的 Catalog 名称为 Hive,内表则为 Internal。这对 AI 生成 SQL 产生一定影响,迫使 AI 必须感知是否存在加速。
为解决上述问题,我们进行了如下优化,具体改进为:
改进 Data Agent 查询的路由机制:用户只需书写库表名,系统将在优化器阶段自动判断路由、补全表名。用户对于 Data Agent 的使用,只需理解数据湖中的 Schema,无需关注表是存储在数据湖还是已加速至 Apache Doris。
数据湖权限系统的打通:我们的数据湖拥有独立的权限管理系统,控制读写访问。将数据加速至 Apache Doris 相当于复制一份数据,可能导致安全管控失效。为解决这一问题,我们设计了机制:即使数据同步至 Apache Doris,其权限仍受 Triton 数据湖权限系统管控,且与 Apache Doris 的账号密码无关。这一设计确保应用层在数据湖上申请的权限依然有效,加速后无需额外权限申请。此外,这一机制保证了即使数据同步到 Apache Doris,持有其账号密码的人员(如 DBA),未经原数据湖系统申请的权限仍无法访问。

Doris + AI 一站式融合数据引擎 DataMind 的实现,已在字节内部应用一段时间,并在持续推广之中,典型应用场景包括智能简历搜索、ByteRAG 平台、CapCut 内容治理等。且在 GraphRAG 上线后,团队与多方客户合作实现了场景落地,例如广告场景、代码搜索的场景,以及近期业界关注的 PRD2Code 等研发提效场景 。

混合搜索 + AI 函数

混合搜索 + AI 函数 + GraphRAG
未来,我们还会在 DATA + AI 上继续探索,搭建更加完善的企业 AI 问数架构。此外,我们将保持与 Doris 开源社区的紧密联系保持联系,积极参与共建并为社区提供反馈。

