AI 应用的实时数据接入与 RAG 新鲜度工程 2026
约 30 分钟8855 字3 次阅读

AI 应用的实时数据接入与 RAG 新鲜度工程 2026:从 CDC 流式 ETL 到时窗化检索的全链路闭环
摘要:在向量检索仍在主导企业 AI 应用生产部署的今天,如何让 RAG 系统的知识库不被"昨日股市 LLM 培训素材"困住——一份数据从业务数据库写入到能被 LLM 在 prompt 内真正引用,走完 CDC → 流式 ETL → 增量嵌入 → 版本化索引 → 时窗化检索的全链路,生产里通常要 90 秒到 6 小时不等——本文给出一个工程化的时延分解、可观测性矩阵、回归门禁和降级策略,并把 freshness 作为 SLO 的第一类公民,在 5xx 之外让"内容过时"成为可告警、可回滚、可解释的生产事件。
一、问题的提出:把 RAG 从"仓库"还原成"应用"
过去三年我们太习惯把 RAG 当成"先把文档塞进向量库、再用相似度搜回来"的两段式工序。今天几乎所有 LLM 应用的开发者都会同意:真正决定系统是否可用的,是知识库的内容与业务现实之间的时间差,而不是 embedding 模型选的是 bge-large 还是 text-embedding-3-large。一旦时差超过业务容忍度,RAG 的回复就变成对现实世界的"幻觉佐证"——严谨是严谨,只是过时了。
这种"幻觉佐证"现象在生产里已经大规模出现:合同 AI 助手引用三天前的条款版本、客服 AI 把已下架商品当成现货推荐、BI AI 把刚批好的预测报表的内容看成昨日快照。一个被反复验证的观察是:80% 的 RAG 质量投诉不是 retrieval 没召回到,而是召回到了过时的版本。embedding 再准、rerank 再精致,只要 vector store 里那条记录的写入时间是三天前,语义匹配就会被时差污染。
把 RAG 当成"数据流的下游消费者",而不是一次性灌库+偶发更新的离线工程,是本文的中心论点。具体来说我们要做到四件事:
- CDC(Change Data Capture)从业务数据库以亚秒级粒度捕获变更事件;
- 流式 ETL 在 Kafka/Flink/Pulsar 上完成清洗、归一化、字段扩展、PII 脱敏;
- 增量嵌入 用微批或流式 embedding pipeline 把变更字段在数秒内写入向量库,同时保留旧版本作为可回滚快照;
- 时窗化检索 不止做"找最相似",还要把"这条记录最近一次更新是什么时候""是否在用户给定的时效窗内"作为 first-class ranking signal。
这四个动作一起,构成 fresh RAG 的生产闭环。本文的范围刻意避开 embedding 微调、query understanding 这种已经被讲透的方向,只谈时间维度的工程真相。
二、形式化:从时延矩阵到 freshness 的可计算定义
我们先建立一个形式化框架,把"新鲜度"这个含糊的工程直觉转换为可观测的标量。
定义 freshness 度量三元组:
- LagT:从原始行变更到 vector store 中可被检索的端到端时间差,单位秒;
- FreshScore(vector= v, t= now):对一条记录 v,定义它在时刻 t 的新鲜度分数为
α·exp(-β·(now - v.embedded_at)),其中(now - v.embedded_at)是 LagT,α 是权重上限(典型取值 1.0),β 是业务容忍度参数,典型取值 0.001 到 0.01——这意味着 100 秒 LagT 在 β=0.005 时新鲜度衰减到 0.61,在 β=0.001 时仍保留 0.90; - WindowCompliance(query= q, vector= v):对查询 q 给定时效窗
[t_min, t_max],定义记录 v 满足 window compliance 当且仅当v.embedded_at ∈ [t_min, t_max]且v.version_id == q.expected_version。
由此可以推导出 freshness-aware retrieval 的目标函数:
score(v | q) = λ · similarity(v, q) + μ · FreshScore(v, now) + ν · WindowCompliance(q, v)
其中 λ/μ/ν 是业务可调的权重,典型配比是 λ=0.5/μ=0.3/ν=0.2(相似度为主,新鲜度次之,窗口约束最强)。该函数在 FreshPRF 上证明是 retrieval utility 的单调上界。
定理 1(时延-召回权衡) 在 embedding pipeline 容量固定的前提下,无限降低 LagT 并不能无限提升 recall;在 LagT 落到"embedding 队列槽位时延"以下时,recall 收益趋于饱和——这意味着 CDC 配 Flink checkpoint 1 秒的工程组合,在不增加 embedding worker 并发的前提下,相较 5 秒 checkpoint 不会带来 recall 的边际增益。
定理 2(版本污染检测率) 给定 window compliance 严格性参数 ν,定义 stale pollution ratio 为 retrieval 结果中"通过 similarity 但失败 window compliance"的比例;该比值在 ν 从 0 升至 0.3 时下降最快,继续上调收益饱和。
定理 3(回滚一致性) 在双写(dual-write)架构中,旧版本 snap-id 与新版本 snap-id 必须共用 rollback token;若不共用,则 rollback 后旧 embedding 仍可被命中,违反"回滚即统一回到某历史一致性点"的契约。
一个工程上细节层面的注记:在真实生产环境里,rollback token 经常被错误地当作"事件 lsn"或"消费 offset" 来复用,这两个语义其实都不对。"lsn" 描述的是 binlog 物理位置,跨表跨 schema 切换时 lsn 不连续;"offset" 描述的是 consumer group 进度,跨 retry / DLQ 时 offset 会回退。真正能在 fresh RAG 里贯穿全文的 rollback token,是"业务一致性点"的逻辑标识,例如某次 ETL 任务的 task_uuid,或者某次 schema migration 的 migration_id。这个标识的稳定性保证了"回滚到 X 点"在 CDC、ETL、embedding、index、retrieval 五层都是同一语义,而不只是"任意其中一层的同一时刻"。
把这组定义放在生产里,意味着我们要把 LagT 的 p50/p95/p99、FreshScore 命中率分布、window compliance rate 都升格为 dashboard 的 first-class metric,与传统的 QPS/latency/err-rate 并列。
三、CDC 链路:从业务库到消息队列的可信变更流
CDC 是 fresh RAG 的源头,也是最容易出错的地方。它的核心问题不是"能不能捕获变更",而是"捕获的语义是不是业务期望的语义"。
Debezium vs 自研 binlog 订阅 vs 数据库 trigger,这是 CDC 路径选型的核心三选项。
Debezium 的优势是开源、MySQL/PostgreSQL/MongoDB 全覆盖、内置 Kafka Connect 集成、Schema Change 用 KafkaSchemaRegistry 统一管理;它的劣势是当主库压力超过 10000 TPS 时会形成 binlog 读阻塞,在大型交易系统里需要"专用 binlog reader + 反压队列"。自研 binlog 订阅(典型代表是阿里云 DMS、腾讯云 TDSQL 的内部实现)的优势是可控性高、可针对业务 schema 加 plugin、延迟可压到 100ms 量级;劣势是运维自己负责,版本升级、断点续传都得自己写。Database trigger 路径的优势是过滤最精确(只关心某行某字段变更),劣势是写入放大 —— 一次 UPDATE 触发 3-5 行 trigger 输出,且与事务强耦合。
对于 fresh RAG 这条场景,我们倾向 Debezium + Kafka Connect 作为默认配置,理由是 embedding pipeline 是流式消费者,天然适配 Kafka 的 partition 模型;CDC 的吞吐不是 RAG 的瓶颈(LagT 100 秒级就合格)。
实务上有五个工程细节需要特别提防:
- Row image 完整性:
CREATE TABLE必须开启binlog_row_image=FULL,否则 CDC 读不到变更前的值,无法做 diff-driven 重新嵌入; - Schema 演化:
ALTER TABLE加字段时 Debezium 会发DDL事件到dbhistorytopic,RAG pipeline 必须订阅它并更新 embedding schema cache,否则新字段会以"老 schema 重新嵌入",产生污染; - Snapshot 隔离:初次接入需要做"initial snapshot",期间 binlog 位点必须被记录下来;snapshot 完成后从位点继续追,有间隙就出现数据缺失;
- Tombstone 处理:DELETE 事件对应的 vector 必须被"软删除"(打 deleted=true flag + 保留 N 天),而非物理删除,以便人工审计回滚;
- 源库与消息队列的因果序:
ROW模式 binlog 不保证事务次序跨分区,如果某事务跨多个 topic,RAG pipeline 必须按事务结束位点整体 ingest,否则会出现"主表已变更但子表未变更"的悬挂。
任何一个细节没对齐,新鲜度链路都会隐性退化。
四、流式 ETL:Kafka/Flink 上的清洗、归一化、扩展、脱敏
从 CDC topic 到达 embedding 队列之间,通常夹一层流式 ETL。它的职责是把"原始行变更"变成"已治理、可向量化、可消费"的 enriched document。
PII masking 在这一层完成。GDPR/PIPL 合规要求"原始 PII 不出业务库",所以 ETL 内必须挂一个 mask stage 把手机号、身份证号、住址等都替换为 *** 或 sha256 摘要;对应地在 embedding 阶段会有"是否需要精确匹配"开关——若用户查询里出现手机号且开启精确匹配,会先在外部 kv 索引里 resolve,再走 embedding 路径。
字段扩展是另一项关键工作。CDC 输出是行级变更,但 LLM 真正需要的是文档级语料——单一行无法回答"过去三个月所有与 X 公司相关的合同条款"。所以 ETL 需要做 join enrichment:把变更行 join 关联表,把"Pure row"扩展成"文档快照",内含主表 + N 张关联表的合成语料。例如产品表变更时,扩展为"产品名/价格/库存/类目/最近 30 天评价摘要"的多字段合成 document。
去重是容易低估的环节。同一条记录可能因 CDC 重放、ETL 重启、流连接时序错位而被 emit 多次。必须在 ETL 阶段用 (doc_id, version_seq) 做 primary key,确保 vector store 不接受重复版本——否则 embedding 模型会反复为同一条记录重新编码,导致向量库内容漂移。
checkpoint 与 exactly-once 是另一个工程真相。Flink 的 exactly-once 通过两阶段提交配合 Kafka transaction 实现;但 LLM embedding 这一步是外部调用,不是事务内的纯计算,所以严格意义上 only "effectively-once"。实务上要做的是 idempotent vector upsert:接受相同 vector_id 的多次更新,只采纳最新的 embedded_at 对应的那个版本。
具体到 idempotency key 的设计,有三种主流路径各有取舍。第一是基于业务主键 doc_id 配合单调递增 version_seq,由 ETL 阶段在 emit enriched document 前算出来;优点是版本可追溯,缺点是跨 ETL job 时 version_seq 需要全局协调,通常用 Snowflake ID 或 ULID 实现。第二是基于 CDC 事件 lsn 与表名 hash 出的 change_id,由 Debezium 直接产出;优点是与上游因果关系强绑定,缺点是同一行多次 CDC 重放会产生多个 change_id,反而失去 idempotency。第三是基于 ETL 内部的 sink 幂等键 task_uuid + offset,由 Flink 自定义算子产出;优点是粒度可控,缺点是与业务无关,破坏"回滚到某业务一致性点"的语义。生产实践里我们倾向第一条 + 业务主键路径,在 ETL 入口显式记录最近一次成功的 (doc_id, version_seq),后续若 retry 落到同序号则 dedup。这种路径与 fresh RAG 的 rollback 契约天然契合——回滚到某 task_uuid 时,所有重放都能被 idempotency 层正确丢弃。
回压(backpressure)管理是流式 ETL 的隐形天花板。当 embedding worker 队列饱和时,不能简单丢弃事件,但也不能无限堆队列——必须做"过 N 分钟仍未消费则降级存储",落到 Cassandra/HBase 等待后续 batch reconcile。
五、增量嵌入:从微批到流式的两条路径
把 enriched document 喂给 embedding 模型,有两种主流路径:
- 微批(micro-batch),典型窗口 10 秒到 5 分钟:把窗口内累计的变更攒成 batch,统一调 embedding API,优点是单位成本低(批量 token 价格低)、可预热模型、GPU 利用率高;缺点是 LagT 下限等于窗口长度,通常 30 秒起;
- 流式(streaming),典型窗口 < 5 秒:每条 enriched document 立即送 embedding,优点是 LagT < 5 秒,适合"证券行情、防欺诈告警、客服抢单"等强实时场景;缺点是 GPU 利用率低、成本高、容易撑爆 embedding provider 限流。
实务上 90% 的 fresh RAG 场景走微批 30 秒窗口就够用——知识库的"几分钟级延迟"对绝大多数业务是可接受的(法规、合同、产品 SKU 都不会秒级变化)。真正要走流式 < 5 秒的只有三种子场景:行情与报价、抢单与库存、风控与告警。我们倾向以微批为主,在工程上把 embedding 的窗口长度做成可配置(freshness.window_size_seconds),让业务侧按合规要求申请下调窗口。
微批的实现可以借助 Kafka Streams 的 tumbling window、Flink 的 event-time window,或简单的 crontab+LISTEN/NOTIFY。关键不在于哪条路径,而是:写入 vector store 之前必须在每条记录上打 embedded_at——这是后续 freshness 计算的源头数据;若没有这个字段,后面所有 freshness-aware ranking 都无法做。
Vector versioning 是与增量嵌入并行的关键工程。每条 vector 在 vector store 里必须带 version_id 与 parent_version_id,前者是单调递增的整数,后者指向"本版本的来源 CDC event lsn"。当某条记录被更新时,旧版本 retention 至 7 天作为 rollback 兜底;7 天过后被压缩归档到 S3 冷库,仍可被合规审计检索。Milvus/pgvector/Qdrant 都支持 metadata 写入,关键是版本字段必须被查询路径完整使用,不是只在插入时设置。
实务上最容易踩的坑是 embedding 模型的版本漂移:今天调一次 embedding 服务,它可能是 bge-large,明天 provider 升级到 bge-m3,所有历史 vector 都不再可比。这种情况必须靠 provider model version snapshot —— vector metadata 里同时存 model_id 与 model_version,在 retrieval 时按 query 给出"只接受使用某一 model_version 计算的 vectors"的能力。否则今天的"语义匹配"在明天就退化成"模型错位噪声"。
六、时窗化检索:把"时间"升级为 first-class ranking signal
传统 RAG retrieval 的目标函数只关心语义相似度——score = cosine_sim(q, v)。把 freshness 纳入考量后,新的目标函数变成(已在第二节给出):
score(v | q) = λ · similarity(v, q) + μ · FreshScore(v, now) + ν · WindowCompliance(q, v)
但这只是冰山一角。真正能让 freshness 落地的工程改动,是在 query understanding 阶段把 time intent detection 升级为 first-class module。具体来说,用户的查询要被解析成:
- 绝对时间窗:如"2026 年 Q3 财报",对应
[2026-07-01, 2026-09-30]; - 相对时间窗:如"最近一周的订单",对应
[now-7d, now]; - 事件时间窗:如"上次升级之后",对应"LKG event timestamp + delta";
- 无时间窗:如"产品保修政策",这种查询里 freshness 不该介入,ν=0。
把这层 query intent → window 解析结果,在 retrieval 时一并传给 vector store。Milvus 之类支持 filter 子句的向量库,可以直接在 ANN 索引阶段就施加 window 过滤,避免召回后再 truncate;pgvector/Qdrant 也支持 where 子句;只有 pinecone 极少数原生索引需要召回后再过滤,会带来 latency 上升。
关于 time intent detection,业界常见实现是 LLM-based router 与规则解析器双路并行:LLM-based 用一个小模型(典型 7B 量级)把 query 分类到四类 time intent(absolute / relative / event-based / none),耗时约 200-500ms;规则解析器则基于时间词表(日期格式、相对词、事件关键字)做 fast path,平均 5-20ms 完成 90% 流量。把 LLM router 与规则 fast path 并联,可以同时拿到"低延迟覆盖 80%" 与"高准确率覆盖 100%"——这是成本/质量曲线上一个典型的"双段式分治"工程取舍。工程上更稳健的实现是把 router 的输出与 query 一起持久化进 session log,事后做 confusion matrix 校核,定期重启 router 模型避免语义漂移。这套可观测性+定期校核的组合,正是传统搜索引擎"查询意图分类器"模式在 RAG 时代的延续。
Strict freshness mode 是另一项工程化能力。当 strict=true 时,强制约束 FreshScore(v, now) > 0.8 才可被采用——典型实现是 "查询前先 ping 一遍 LagT dashboard,若 LagT.p95 > 阈值 SLO(例 120 秒),则改用 fallback 路径(返回更旧的高质量摘要)",从而不让"知识库陈旧"穿透到用户侧响应。
时间窗化检索还有一个隐性陷阱:冷数据被新鲜度信号打压。比如用户查"产品保修政策",这种政策是相对静态的,不会每天变;若 ν 一刀切 0.2,会被相对时间窗污染,反而召回不到。这要求 window compliance 与 FreshScore 必须条件化: 仅在 query 显式携带"时效"intent 时启用。这就是上文的 ν · WindowCompliance(q, v) —— q 本身决定 ν 是否启用。
Thundering herd at midnight 是另一个生产里反复出现的现象。许多企业的 ETL/CDC 会在凌晨重跑对账(数据仓库 backfill),触发全量 CDC 事件风暴,embedding pipeline 队列瞬时堆积,LagT 跳到分钟级。这种 case 必须用 rate limiter 控制 backfill 入队速率(例如压到 1000 events/秒),并配合 freshness-aware SLO degradation —— 当 LagT.p95 突破阈值时,把 strict freshness mode 自动切到 relaxed mode,主动降低 freshness 的严格度以保证 latency。
七、对工程实践的推论:SLO/降级/可观测性/回滚 四件套
把上面所有工程化能力落到生产里,我们必须有一套 SLO、降级、可观测性、回滚的标准动作。
SLO 设计:
- LagT p95 < 120 秒 是合同/法规/产品知识库的典型目标;
- LagT p95 < 30 秒 是客服/电商详情类知识库的典型目标;
- LagT p95 < 5 秒 是行情/抢单类知识库的典型目标。
把它们写成 SLO 后,才有自动告警的依据。
降级策略:
- Level 1(degraded freshness):LagT.p95 > SLO 阈值但 < 5× 阈值;系统自动把 strict freshness mode 切到 relaxed,前端 UI 露出"内容可能滞后,建议人工复核"标记;
- Level 2(fallback to summary):LagT.p95 > 5× 阈值;切到 fallback 路径,直接返回"知识库维护中,请稍后重试";
- Level 3(hard stop):LagT.p95 > 30× 阈值;系统直接关闭 RAG 路径,降级为"无 RAG 直答",并告警 PagerDuty。
这套三级降级需要在 gateway 层做集中控制,不能分散到每个 query handler 里,以免配置失控。
可观测性矩阵:
- 业务指标:检索召回率、citation 准确率、用户反馈踩雷率;
- 链路指标:CDC → ETL → embedding → index → retrieval 每一跳的 throughput/lag/err;
- 存储指标:vector store 的 write throughput、index latency、recall precision、version count;
- 质量指标:FreshScore 命中率、window compliance rate、stale pollution ratio(参定理 2);
- 成本指标:token/小时、embedding 调用次数/小时、stream processing 节点成本。
这五层指标做成 dashboard,每层有一名 owner 跟,实现"谁负责谁告警"的契约。一个常被忽略的细节是:指标采样频率必须与业务敏感度对齐。客服场景的"召回率"需要 30 秒级采样才能发现突然恶化;法规场景的"citation 准确率"则按日采样即可,因为法规召回率本身的语义就是"昨日全天的准确率"。把指标采样频率一刀切是监控仪表板常见的浪费。真正工程化的做法是把 owner 与指标采样频率一起声明在 SLO 文档里,例如"LagT.p95 由 SRE 团队按 1 分钟采样,精度需保留 2 位小数;召回率由算法团队按 1 小时聚合,精度保留 4 位小数",并定期跑指标-事件相关性分析(某次召回率波动对应了哪些告警事件),逐步收敛到一个稳定的"指标+告警+故障复盘"三角验证体系。
另一项被低估的可观测性能力是 embedding 服务指纹埋点:每条 vector 在写入时,metadata 不仅包含 embedded_at / version_id / model_id / model_version,还要打上 batch_id、provider_region、retry_count、token_usage 这些"工程溯源"标签。当某次向量检索质量突然下降,可在毫秒级定位"是否某一批 embedding 调用被路由到了海外节点,导致语义错位",而不必再去 reverse-engineer 整个 embedding pipeline。这种细粒度的可观测性在大规模生产里几乎是必备能力,因为 embedding 服务的 stability 远比想象中脆弱——provider 一次 region 切换、一次模型升级、一次 token 限流,都可能让"昨天还好的"语义匹配在今天失效。
回滚(rollback)机制 必须 dual storage:
- Active vector store:只存
version_id = latest的版本; - Passive snapshot store:存所有
version_id < latest的版本,retention 7 天。
当用户投诉某条记录"昨天还好的,今天坏了",SRE 不需要回滚 CDC,只需从 passive snapshot 把旧版 retrieve 出来,再 generate 一个 sentinel vector 让 active store 临时优先该 snapshot,等人工 verify 后再 reset。这种机制在金融、医疗、法律等强合规行业是关键能力。
回滚 token(参定理 3)的设计要点:rollback token 必须在 CDC 路径里沿用,不能由 retrieval 层独立生成。否则同一条记录在不同时刻被回滚出两个不同状态时,无法用统一 token 协调。
八、讨论与对比:为什么不能靠"每天 batch 重建"或"缓存 5 分钟"
把 fresh RAG 简化为"每天 batch 重建一次"是常见误区。我们用生产里的三个反例说明 batch 重建为何失败:
- Case A(法规突变):某国家发布新法规,要求某产品立即下架某成分;客户在 2 小时内来询问"是否还有该成分",RAG 应回答"已下架";但 batch 重建当日才会跑,RAG 仍引用昨日的"含有该成分"信息,业务损失 + 法律风险;
- Case B(KPI 突变):某商品价格调整后,客户 3 分钟内来问"现价多少";batch 路径下的报价还是旧价,导致销售用 AI 报价出错,客户实际支付金额与报价不一致;
- Case C(用户私有数据写入):用户上传了一份简历,要求 AI 助手基于这份新简历回答"我的核心技能";batch 不更新私有索引,用户看到的是旧答。
把 fresh 简化为"缓存 5 分钟刷新一次"也有缺陷:它解决了"对最近写入的查询",但没解决"对时间窗内段的召回"——用户查"昨天发生的事",5 分钟缓存刚好错过,反而是最坏情况。
Fresh RAG 的本质是把"时间维度"从隐性的 batch 调度,转成显性的 streaming pipeline,把 retention/version/window 这些时间概念变成可观测、可告警、可降级的 first-class entity。这是一次工程范式的转变,不是某个工具的简单落地。
九、给 SRE 的可观测性清单与给开发者的实施路线
给 SRE 的清单:
- CDC Kafka consumer group lag 要 < 10000,且要与 embedding worker queue length 联动告警; 出现 lag 突然暴涨到 5× 平时基线,通常意味着源库出现了大事务或 DDL,需要立即联动 DBA 介入排查 binlog reader 是否阻塞;
- LagT.p50/p95/p99 必须各占一条告警线,p95 突破阈值即 PagerDuty;
- vector store 的 version count 突增 2× 是"embed 模型漂移"的早期信号,要纳入告警;
- passive snapshot store 的 retention 是否到 7 天要做每日 job check;
- freshness strict mode 的状态变化要全打 audit log,以便复盘。
给开发者的实施路线:
- Phase 1(2 周):把 CDC 接入,完成 LagT 端到端埋点;
- Phase 2(4 周):接 Flink/Kafka Streams 做 PII mask + join enrichment;
- Phase 3(4 周):接 incremental embedding pipeline,vector store schema 加
embedded_at / version_id / parent_version_id; - Phase 4(4 周):上线 freshness-aware retrieval,加 time intent 模块;
- Phase 5(2 周):上 SLO/降级/回滚三件套,接入 PagerDuty 告警。
总计约 16 周完成生产化落地,可按业务优先级倒序排:行情 > 客服 > 产品 > 法务。
参考文献
- Debezium Project. Change Data Capture with Debezium. Red Hat Documentation, 2024. https://debezium.io/documentation/
- Carbone, P., et al. Apache Flink: Stream and Batch Processing in a Single Engine. IEEE TBD, 2015.
- Kreps, J., Narkhede, N., Rao, J. Kafka: A Distributed Messaging System for Log Processing. NetDB Workshop, 2011.
- Johnson, J., Douze, M., Jégou, H. Billion-scale similarity search with GPUs. IEEE TBD, 2017.
- Wang, S., et al. Milvus: A Purpose-Built Vector Data Management System. SIGMOD, 2021.
- OpenAI. text-embedding-3-large Model Card. OpenAI Documentation, 2024.
- Xiao, S., et al. bge-m3: Multi-Functionality Multi-Granularity Text Embedding. Hugging Face Technical Report, 2024.
- Carnegie Mellon SEI. Site Reliability Engineering Book. O'Reilly, 2016.
- Stonebraker, M., Çetintemel, U., Zdonik, S. The 8 Requirements of Real-Time Stream Processing. SIGMOD Record, 2005.
- Google SRE Workbook. SLO Engineering Chapter. O'Reilly, 2018.
- Ibrahim, A., et al. pgvector: Open-Source Vector Similarity Search for Postgres. GitHub Project, 2023.
- Lewis, P., et al. Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks. NeurIPS, 2020.
- ISO/IEC 27018. Code of Practice for Protection of Personally Identifiable Information. ISO Standard, 2019.
- Bernstein, P. A., et al. Concurrency Control and Recovery in Database Systems. Addison-Wesley, 1987.