@gortron: S3 是存储数据的绝佳场所,直到你试图搜索它。两个月前我发布了 Firn:开源向量+…
摘要
Firn 是一个开源的多租户向量与全文搜索引擎,基于 AWS S3 等对象存储,提供分层存储架构,配备 RAM 和 NVMe 缓存以提升性能。通过 IVF_PQ 索引实现亚秒级冷查询,并通过结果缓存实现微秒级热命中。
查看缓存全文
缓存时间: 2026/07/07 11:30
S3 是存储数据的绝佳场所——直到你需要搜索它。两个月前,我发布了 Firn:基于 S3 的开源向量 + 全文搜索引擎。至今已获得 400+ Star、Python 客户端(pip install firn)、多向量支持、语义缓存、7 个已验证的存储提供商。
gordonmurray/firnflow
来源:https://github.com/gordonmurray/firnflow
Firn
Firn 是一个多租户向量与全文搜索引擎,后端基于对象存储(AWS S3、MinIO、Cloudflare R2、Tigris、DigitalOcean Spaces、Google Cloud Storage)。它是专有对象存储搜索服务的可靠开源替代方案,展示了RAM → NVMe → 对象存储三层存储架构可以完全由开源组件构建。完整兼容性矩阵见存储后端。
它结合了 LanceDB(直接在对象存储上运行向量和 BM25 搜索)与 foyer(RAM + NVMe 缓存),因此数据存放在低成本的对象存储上,而重复查询则从缓存响应,无需后端往返。
性能
在 eu-west-1 区域的 AWS S3 上,针对 100,000 个 1536 维向量(OpenAI 嵌入大小)进行基准测试:
| 查询路径 | p50 延迟 |
|---|---|
| 冷启动,无索引(对 S3 进行暴力扫描) | ~25.1 秒 |
| 冷启动,IVF_PQ 索引(给定查询的首次运行) | ~979 毫秒 |
| 热启动(字节完全相同重复,从缓存响应) | ~72 微秒 |
| 端到端 HTTP,热启动 | < 5 毫秒 |
判断 Firn 是否适合你的工作负载的因素:
- IVF_PQ 索引使对象存储上的搜索变得可行。 无索引时,每次查询都是约 25 秒的暴力扫描;有索引后,冷查询约为 979 毫秒。在首次批量写入后构建索引(
POST /ns/{ns}/index)。 - 结果缓存加速的是重复查询,而非新查询。 热命中是对同一命名空间版本的字节完全相同重复查询;它在微秒级返回,并且一旦句柄变热,就不需要任何后端请求。新查询会错过缓存,需承担上述冷启动成本。参见缓存能做什么和不能做什么。
- 两个可选层扩展了跳过后端的情况。 语义缓存在输入查询向量足够接近时重用近期结果(近似重用,因此是可选的)。对象缓存将 Lance 读取的对象存储字节保存在本地 NVMe 上,因此即使是对已读取数据的新查询,也能避免重复 S3 往返。
缓存能做什么和不能做什么
结果缓存存储完整的序列化查询结果集,键由命名空间、其当前 Lance 表版本以及完整查询的哈希组成。命中需要同一版本下的完全相同查询重复。任何已提交的写入都会推进版本,并使该命名空间的缓存结果不可达——因此运行中的服务器在写入后绝不会返回过时结果;由于版本已持久化,重启后仍然有效。键形成时会读取版本,因此进程中首个针对某命名空间的查询(即使是缓存命中)会打开其表句柄(一次清单读取);后续命中则从内存中读取版本。
Firn 从未见过的查询会错过结果缓存,并需承担完整的 LanceDB 在对象存储上的开销。一旦存在 IVF_PQ 索引,该开销已经较低;LanceDB 自身的索引、每个命名空间的连接池以及操作系统页面缓存会进一步降低。
两个可选层更进一步:
- 语义缓存。 将命中扩展至近重复查询,返回未经全新搜索的近似结果。参见可选语义缓存。
- 对象缓存。 将 Lance 读取的不可变对象存储字节(数据片段和索引文件)保留在本地 NVMe 上,因此对于已经拉取过一次的数据,冷查询或真正的新查询将从磁盘响应,而非重复那些主导冷延迟的小型 S3 GET 请求。它仅缓存一次性写入对象(清单及任何有条件的或版本化读取始终穿透),因此无需失效步骤:写入、删除、压缩或索引构建会立即反映。磁盘使用采用带 LRU 淘汰的字节预算,重启后保持。默认关闭;设置
FIRNFLOW_OBJECT_CACHE_ENABLED=true并将FIRNFLOW_OBJECT_CACHE_DIR指向快速本地磁盘。firnflow_object_cache_*指标显示其有效性,配置文档(https://firnflow.io/configuration.html#object-cache)说明了字节预算和每项限制。
如果你的流量主要是唯一查询,结果缓存命中率按设计会很低。其价值在于对象存储搜索的成本和多租户模型,并可选择通过对象缓存吸收底层重复字节读取。
演示
60 秒内的冷查询、热查询、全文搜索和缓存验证,针对本地 MinIO(无索引),因此冷查询在这里仅约 109 毫秒。在真实 S3 上,无索引冷查询接近约 25 秒,IVF_PQ 索引使其降至约 979 毫秒,重复查询微秒级从缓存返回。
Firn 演示
Python 包
该引擎也以 firn 形式提供于 PyPI(https://pypi.org/project/firn/),将 Firn 嵌入你的 Python 进程,无需运行服务器。支持针对本地目录或任何受支持对象存储后端的向量、BM25 全文及混合搜索。
pip install firn
import firn
db = firn.connect("./firn_data") # 本地文件夹;或 storage_url="s3://bucket"
db.add([
{"id": 1, "vector": [1.0, 0.0, 0.0, 0.0], "text": "the quick brown fox"},
{"id": 2, "vector": [0.0, 1.0, 0.0, 0.0], "text": "a lazy dog sleeps"},
{"id": 3, "vector": [0.0, 0.0, 1.0, 0.0], "text": "the fox runs fast"},
])
# 全文+向量,一次调用融合
for hit in db.search("fox", vector=[1.0, 0.0, 0.0, 0.0], limit=3):
print(hit.id, hit.score, hit.text)
firn Python 包演示
tenant="customer-42" 在任何调用中选择物理上独立的命名空间,与服务器提供的隔离相同。wheel 包支持 Linux x86_64 和 aarch64 以及 macOS,Python 3.10 及以上;包的版本独立于服务器,使用 firn-v* 标签(当前:firn 0.1.0)。可运行示例(包括在对象存储上使用 CLIP 嵌入进行图像搜索)位于 examples/ 目录中。v0.1 范围仅限于嵌入式使用:该包不连接正在运行的 Firn 服务器,每一行都携带一个向量(text 随附用于全文和混合搜索),删除是命名空间级别而非行级别。
架构
Firn 基于“分层存储”理念构建:
- L1:RAM 缓存(通过 foyer):针对最频繁查询的微秒级读取。
- L2:NVMe 缓存(通过 foyer):快速、持久化的缓存,用于高吞吐量搜索结果。
- L3:对象存储(通过 LanceDB 在 AWS S3 / MinIO / R2 / Tigris / Spaces / 原生 GCS 上):真相来源,每个命名空间在其自己的对象存储前缀下隔离。
可选的对象缓存位于 LanceDB 与对象存储之间,将 Lance 读取的字节范围保留在本地 NVMe 上。这与上述的 foyer 结果缓存不同(后者存储整个查询结果)。默认关闭;参见缓存能做什么和不能做什么。
关键技术
- axum: 高性能异步 REST API。
- LanceDB: 原生运行于对象存储上的向量和 BM25 搜索引擎。
- foyer: 高级混合缓存(RAM + NVMe),支持 LFU/LRU 淘汰。
- Prometheus: 全面运营可见性,监控缓存命中、未命中及对象存储请求节省情况。
存储后端
Firn 的正确性依赖于底层对象存储在并发写入器之间提供严格线性化的比较并交换(CAS)。LanceDB 的提交协议使用此保证来序列化清单更新,因此忽略或错误处理条件写入契约的后端将静默丢失写入。对于 S3 系列后端,契约为 If-None-Match: *;对于原生 Google Cloud Storage,则是生成前提条件(GCS XML API 上的 x-goog-if-generation-match: 0),lancedb 的 gcs 特性透明地进行了传递。
以下每个提供商都经过了相同测试:顺序条件 PUT 预检、8 个写入器 × 100 行并发压力测试,以及(对于通过的后端)针对真实存储桶连续运行 100 次该压力测试。测试工具位于 crates/firnflow-core/tests/。
| 提供商 | 支持 | 原因 |
|---|---|---|
AWS S3(eu-west-1 已验证) | ✅ | 严格 CAS,100 次压力测试通过。 |
| MinIO(自托管/本地) | ✅ | S3 协议的参考实现;100 次压力测试通过。 |
| Cloudflare R2 | ✅ | 正确执行 If-None-Match: *;100 次压力测试通过。每次迭代延迟约为 AWS 的 7 倍(由于 R2 的多区域提交路径),但正确性是门槛检查的重点。零出站流量使其成为非 AWS 目标中最有趣的。请使用路径样式寻址。 |
| Backblaze B2(S3 兼容层) | ❌ | 首次 PutObject 返回 HTTP 501 NotImplemented。B2 原生 API 通过 X-Bz-* 标头支持条件写入,但 S3 兼容网关未进行转换。显式失败,易于检测,不适用于 Firn。 |
| Tigris(双区域 + 单区域) | ✅ | 并发提交时 If-None-Match: * 得到执行;截至 2026-04-19 上游 CAS 修复后,双区域和单区域存储桶上的 100 次压力测试均通过。请对 t3.storage.dev 使用路径样式寻址。 |
DigitalOcean Spaces(lon1 已验证) | ✅ | 严格 CAS,100 次压力测试通过。每次迭代延迟约 3.10 秒,与 AWS eu-west-1 相近,是测试过最快的非 AWS 后端。使用区域端点(https://<region>.digitaloceanspaces.com),而非虚拟主机形式,并采用路径样式寻址。 |
Google Cloud Storage(原生,europe-west1 已验证) | ✅ | 通过 lancedb 的原生 gcs 特性和 object_store::gcp 路由,使用 GCS XML API 的生成前提条件(x-goog-if-generation-match: 0)代替 If-None-Match: *。针对 firn-gcs-bucket-europe-west1 的 100 次 Lance 级并发写入器压力测试通过;8 写入器屏障栅栏式竞争键微压力测试及顺序预检也通过(参见 crates/firnflow-core/tests/lance_concurrent_writes.rs 和 s3_conditional_writes.rs)。认证通过标准的 GOOGLE_* 环境变量中的服务账户 JSON 完成。使用 gs://... URI;通过 s3:// URI 加自定义 GCS_ENDPOINT 访问的 GCS S3 互操作端点不受支持,因为该路径静默丢弃 If-None-Match: * 并在竞争条件下丢失写入器。 |
两个专用测试位于 crates/firnflow-core/tests/s3_conditional_writes.rs 和 crates/firnflow-core/tests/lance_concurrent_writes.rs。两者均标记为 #[ignore],需要凭据才能运行。如果你想评估表中未列出的后端,从任一文件复制一个代码块并指向你自己的存储桶。
后端配置
后端选择是运维配置决策,无需重新编译。设置 FIRNFLOW_STORAGE_URI 使 Firn 指向你所需的存储桶。在任何两个已验证后端之间切换只需更改环境变量。FIRNFLOW_S3_BUCKET 仍作为遗留 S3 专用回退受支持;若两者都设置,则必须一致,否则启动失败。FIRNFLOW_STORAGE_URI 接受 s3:// 或 gs:// URI,并带有可选固定前缀,例如 s3://shared-bucket/tenants/acme/prod 或 gs://shared-bucket/tenants/acme/prod。当多个部署共享单个存储桶时,前缀非常有用;命名空间表位于 {root}/{namespace}/。
AWS S3
FIRNFLOW_STORAGE_URI=s3://my-firn-bucket
FIRNFLOW_S3_REGION=eu-west-1
# 凭据从标准 AWS 链获取(实例配置文件、
# AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY、~/.aws/credentials)。
FIRNFLOW_S3_REGION 是可选的:若未设置,Firn 回退到标准 AWS_REGION,然后 AWS_DEFAULT_REGION,最后才到 us-east-1。设置 FIRNFLOW_S3_REGION 以显式固定 Firn 的区域,或依赖你的主机已导出的 AWS_* 变量(在 EC2/ECS 上通常如此)。区域与存储桶区域不匹配会导致请求失败,因此对于强制区域的后端(真正的 AWS S3 会这样做;MinIO 和大多数模拟器忽略它),这一点很重要。
MinIO(本地/自托管)
FIRNFLOW_STORAGE_URI=s3://firnflow
FIRNFLOW_S3_ENDPOINT=http://localhost:9000
FIRNFLOW_S3_ACCESS_KEY=minioadmin
FIRNFLOW_S3_SECRET_KEY=minioadmin
Cloudflare R2
FIRNFLOW_STORAGE_URI=s3://firn-r2
FIRNFLOW_S3_ENDPOINT=https://<accountid>.r2.cloudflarestorage.com
FIRNFLOW_S3_ACCESS_KEY=<accesskey>
FIRNFLOW_S3_SECRET_KEY=<secretkey>
FIRNFLOW_S3_REGION=auto
Tigris
FIRNFLOW_STORAGE_URI=s3://firn-tigris
FIRNFLOW_S3_ENDPOINT=https://t3.storage.dev
FIRNFLOW_S3_ACCESS_KEY=<accesskey>
FIRNFLOW_S3_SECRET_KEY=<secretkey>
FIRNFLOW_S3_REGION=auto
DigitalOcean Spaces
FIRNFLOW_STORAGE_URI=s3://firn-spaces
FIRNFLOW_S3_ENDPOINT=https://<region>.digitaloceanspaces.com
FIRNFLOW_S3_ACCESS_KEY=<accesskey>
FIRNFLOW_S3_SECRET_KEY=<secretkey>
FIRNFLOW_S3_REGION=<region>
Google Cloud Storage(原生)
FIRNFLOW_STORAGE_URI=gs://my-firn-bucket
GOOGLE_APPLICATION_CREDENTIALS=/etc/firnflow/gcp-sa.json
# 或者:GOOGLE_SERVICE_ACCOUNT_PATH=/etc/firnflow/gcp-sa.json,
# 或 GOOGLE_SERVICE_ACCOUNT_KEY=<key>。
使用 gs://... 而非 GCS S3 互操作端点。互操作路径静默丢弃 If-None-Match: *,不受支持。
特性
- 多租户设计: 每个命名空间映射到已配置
FIRNFLOW_STORAGE_URI下的一个隔离对象存储前缀(例如s3://bucket/namespace/或gs://bucket/namespace/),空闲成本几乎为零。 - 即时失效: 缓存结果以 Lance 表版本为键,因此写入会推进版本,并以 O(1) 时间使该命名空间过时结果不可达,无需单独记账。
- 可选对象缓存: 存储引擎下方的本地 NVMe 字节范围缓存。启用后,冷查询和新查询背后的对象存储读取从磁盘响应(而不仅仅是完全重复查询)。默认关闭(详情)。
- CAS 一致性: 使用后端条件写入原语(S3 系列后端使用
If-None-Match: *,原生 GCS 使用生成前提条件)验证并发安全性,防止多个写入器争夺同一存储桶时数据丢失。 - 后期交互搜索: 每个命名空间可以是单向量(每行一个稠密向量)或多向量(每行一组小向量,通过 MaxSim 评分)。多向量形状正是 ColBERT、ColPali 和 ColQwen2 生成的,也是像 “一个衬衫上有标志的男人” 这样的组合查询独立匹配每个元素所需要的。参见下面的多向量命名空间。
- 紧凑序列化: 查询结果使用
bincode序列化,并预留了在需要零拷贝的工作负载下使用rkyv的路径。 - 卓越运维: 原生 Prometheus 指标跟踪缓存命中率和后端请求计数(成本节省的主要信号)。
快速开始
1. 启动堆栈
你所需的一切(MinIO 存储 + Firn API)通过 Docker Compose 编排:
git clone https://github.com/gordonmurray/firnflow
cd firnflow
docker compose up --build
2. 更新向量
API 位于 http://localhost:3000。将向量保存到 demo 命名空间:
curl -X POST http://localhost:3000/ns/demo/upsert \
-H 'Content-Type: application/json' \
-d '{
"rows": [
{"id": 1, "vector": [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]}
]
}'
Upsert 以 id 为键,且以最新写入为准:重新发送已存在 id 的行会完全替换存储的行,而非添加第二个副本,因此重试和真正的更新都是安全的。ID 在单个请求内必须唯一。_ingested_at 时间戳跟踪行的最近一次写入,而非首次插入。
对命名空间的首次写入会构建一个基于 id 的 BTree 索引,以支持高效的删除和版本表清理。目前,每行可以包含一个向量(vector 字段)或一个多向量集合(vectors 字段),但不能同时包含;参见多向量命名空间以了解多向量模式。
3. 搜索
curl -X POST http://localhost:3000/ns/demo/search \
-H 'Content-Type: application/json' \
-d '{
"vector": [0.9, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
"top_k": 5
}'
你也可以使用全文搜索(作为 BM25 运行)或混合搜索(向量 + 全文加权组合):
curl -X POST http://localhost:3000/ns/demo/search \
-H 'Content-Type: application/json' \
-d '{
"vector": [0.9, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
"text_query": "fox",
"top_k": 5
}'
默认评分权重为 alpha = 0.5(向量 = 全文),可由调用者覆盖为 alpha: 0.3 以偏向文本或 alpha: 0.7 以偏向向量相似度。
多向量命名空间
在默认的单向量模式中,每行包含一个稠密向量(浮点数组)。在多向量模式中,每行包含一组较小的向量(vectors 字段),通过后期交互 MaxSim 评分。当行在概念上是由多个独立部分组成的复合体时——例如文档中的段落、图像中的物体、或句子中的短语——多向量模式允许每个子向量独立匹配查询中的不同方面。
对于像 ColBERT、ColPali 或 ColQwen2 生成的向量,多向量模式是它们的自然格式。
curl -X POST http://localhost:3000/ns/demo/upsert \
-H 'Content-Type: application/json' \
-d '{
"rows": [
{
"id": 4,
"vectors": [
[0.1, 0.2, 0.3, ...],
[0.4, 0.5, 0.6, ...]
],
"text": "a red car and a blue sign"
}
]
}'
在此模式下,每一行存储一个 bag of vectors(一组向量),而不是单个向量。每个命名空间声明自己是单向量或多向量。
可选语义缓存
语义缓存是结果缓存上的一层。当新查询的向量足够接近同一个命名空间版本下的先前查询时,语义缓存会返回该先前查询的(最近)结果,而不是运行一次新的 LanceDB 搜索。它通过近似重用减少后端负载,代价是结果可能反映上次搜索时数据库的状态,而非当前状态。
它由两个参数控制:
FIRNFLOW_SEMANTIC_CACHE_ENABLED(布尔值,默认false)FIRNFLOW_SEMANTIC_CACHE_DISTANCE_P99_THRESHOLD(浮点数,默认0.2)
距离阈值是如何衡量的?Firn 使用向量的余弦距离。对于经过 L2 标准化的单位向量,余弦距离是 1 - cosine_similarity,取值范围为 [0, 2]。阈值 0.2 意味着两个向量必须具有至少约 0.8 的余弦相似度(余弦距离 ≤ 0.2)才能匹配。这对于近似句子级重复语义是合理的,但可能需要为你的数据调整。
什么是 p99 距离?语义缓存为每个报告其自身 p99 距离的最近已知活跃查询保留一个条目,这是该查询过去 10 个匹配结果的第 99 百分位距离。新查询会检查是否有任何现有条目满足 p99_distance <= threshold,并重用匹配条目的结果。非匹配距离会增加,而匹配更好的距离会随时间降低 p99。
设置一个过于严格的阈值(例如 0.01)会使语义缓存基本上等同于精确结果缓存,但计算开销更大。设置过于宽松的阈值(例如 0.8)会导致不相关的结果被重用。一个好的起点是使用你的查询数据的余弦距离直方图。
即使在语义缓存命中时,命中也会记录在 Prometheus 指标 firnflow_semantic_cache_hits 和 firnflow_semantic_cache_misses 中。
可选的查询去重。在语义缓存层下方,Firn 可选地将查询向量去重到分布式哈希环上(通过 ketama 哈希),以便来自同一向量查询的并发请求合并到单个后端数据库命中。这由 FIRNFLOW_REQUEST_DEDUP_ENABLED(默认 false)控制。
维度与距离度量
默认情况下,Firn 为密集向量假设 L2 归一化单位向量,并配套使用余弦距离。这对于像 OpenAI 嵌入(默认归一化)和句子转换器(通常通过归一化或余弦相似度使用)适用。你可以在启动时将 FIRNFLOW_DISTANCE_TYPE 设置为 l2(欧几里得距离)、cosine(余弦距离)或 dot(点积)来覆盖距离度量。距离度量影响索引和搜索行为,尤其是与 IVF_PQ 索引结合时。
索引
为每个命名空间构建一个 IVF_PQ 索引。IVF(倒排文件)将向量空间划分为单元格并限制搜索范围;PQ(乘积量化)压缩存储的向量以减少内存和 I/O。没有索引时,每次搜索都是对全部向量的暴力扫描,随着集合变大,延迟会迅速增加。
curl -X POST http://localhost:3000/ns/demo/index
索引是幂等的:如果命名空间已有索引,则静默跳过。索引参数(IVF 质心数、PQ 子量化器大小)可从环境变量配置,或使用合理的默认值。
索引构建会消耗 CPU 和内存,尤其是在大型命名空间上。它应在一次或多次写入后执行一次(如果计划完全重新索引,则执行多次)。在索引构建期间,查询仍然有效——LanceDB 在索引准备好的提交之前使用旧路径。
重新索引。想要为现有命名空间构建新的索引(例如更改索引参数后)时,请发送带有查询参数 ?force=true 的 POST 请求。这将删除当前索引并从头开始重建。
写入与最终一致性
Firn 的写入在服务器端进行确认后是立即持久化的。LanceDB 事务性提交协议确保并发写入器以一致的方式更新清单文件,而 Firn 对你的部分使用条件写入(If-None-Match: *)实现分布式互斥。一旦服务器成功返回 200 OK,后续查询就一定能看到该写入。
对于不支持严格条件写入的后端(例如 GCS S3 互操作端点、配置不当的模拟器),Firn 会回退到基于时间的互斥(一个租约文件,要求在提交之前独占创建),这在所有经过验证的正确后端上均能正常工作——详细信息见存储后端表格。
在写入操作与相关 GET 之间进行请求重试或按顺序执行是安全的。
删除
Firn 支持按 ID 删除行:
curl -X POST http://localhost:3000/ns/demo/delete \
-H 'Content-Type: application/json' \
-d '{"ids": [1, 2, 3]}'
删除是版本化的:已删除的行会从查询结果中排除,但它们的历史记录(包括支持表清理的 _deleted_at 时间戳)可能被保留到下一次压缩。重复的 ID 会被静默忽略。
多区域/跨区域注意事项
Firn 尚未正式支持跨区域复制。对于 AWS,所有实例必须连接到同一区域内的同一存储桶。由于条件写入的延迟要求,跨区域写入(例如从 us-west-2 写入 eu-west-1 中的存储桶)不被支持。对于多区域读取,基于区域的服务发现是可能的,但尚需验证 Firn 的缓存层能否正确处理产生不同清单版本(由于并发写入)的两个区域。
管理 API
Firn 公开了一组管理端点:
GET /health— 健康检查,返回200 OK及{"status": "ok"}。GET /metrics— Prometheus 格式指标。DELETE /ns/{ns}— 删除整个命名空间及其所有数据。
还提供了额外的日志记录和调试端点;更多细节请查看 API 参考。
配置参考
所有配置通过环境变量完成。
| 环境变量 | 类型 | 默认值 | 描述 |
|---|---|---|---|
FIRNFLOW_STORAGE_URI | 字符串 | — | 带可选前缀的 s3:// 或 gs:// URI(推荐配置方式) |
FIRNFLOW_S3_BUCKET | 字符串 | — | 遗留配置,仅 S3 存储桶名称(若与 STORAGE_URI 均设置,必须一致) |
FIRNFLOW_S3_ENDPOINT | 字符串 | — | 用于 S3 兼容服务的自定义端点(MinIO、R2、Tigris、Spaces) |
FIRNFLOW_S3_REGION | 字符串 | 自动检测 | S3 区域(对于真实 AWS S3 需要;对于 MinIO/R2/Spaces 请参阅提供商文档) |
FIRNFLOW_S3_ACCESS_KEY | 字符串 | — | S3 访问密钥(如果未设置,则使用标准 AWS 链) |
FIRNFLOW_S3_SECRET_KEY | 字符串 | — | S3 秘密密钥 |
FIRNFLOW_HTTP_PORT | 整数 | 3000 | HTTP 服务器端口 |
FIRNFLOW_HTTP_HOST | 字符串 | 0.0.0.0 | HTTP 服务器绑定地址 |
FIRNFLOW_CACHE_SIZE | 字符串(例如 1GB) | 512MB | 结果缓存(RAM 部分)的最大大小 |
FIRNFLOW_CACHE_NVME_SIZE | 字符串(例如 10GB) | 禁用 | NVMe 结果缓存的最大大小(未设置时禁用) |
FIRNFLOW_CACHE_NVME_DIR | 字符串 | /var/cache/firnflow | NVMe 缓存目录 |
FIRNFLOW_DISTANCE_TYPE | 字符串 | cosine | 距离度量:cosine、l2 或 dot |
FIRNFLOW_SEMANTIC_CACHE_ENABLED | 布尔值 | false | 启用语义缓存 |
FIRNFLOW_SEMANTIC_CACHE_DISTANCE_P99_THRESHOLD | 浮点数 | 0.2 | 语义缓存相似度阈值 |
FIRNFLOW_REQUEST_DEDUP_ENABLED | 布尔值 | false | 启用并发请求去重 |
FIRNFLOW_OBJECT_CACHE_ENABLED | 布尔值 | false | 启用对象存储字节范围缓存 |
FIRNFLOW_OBJECT_CACHE_DIR | 字符串 | /var/cache/firnflow-obj | 对象缓存目录 |
FIRNFLOW_OBJECT_CACHE_BUDGET | 字符串(例如 20GB) | 10GB | 对象缓存字节预算 |
FIRNFLOW_OBJECT_CACHE_MAX_ENTRY_SIZE | 字符串(例如 100MB) | 50MB | 对象缓存每项最大大小 |
FIRNFLOW_IVF_NLIST | 整数 | 4096 | IVF 质心数 |
FIRNFLOW_PQ_NBITS | 整数 | 8 | PQ 子量化器位数(通常为 8) |
FIRNFLOW_PQ_NSUBSQ | 整数 | 64 | PQ 子量化器数量 |
FIRNFLOW_DEFAULT_SEARCH_LIMIT | 整数 | 10 | 搜索默认 top_k |
FIRNFLOW_LOG_LEVEL | 字符串 | info | 日志级别(trace、debug、info、warn、error) |
可观测性
Firn 在 GET /metrics 上提供 Prometheus 格式的指标。关键指标包括:
firnflow_cache_hits/firnflow_cache_misses— 结果缓存命中与未命中firnflow_semantic_cache_hits/firnflow_semantic_cache_misses— 语义缓存命中与未命中firnflow_request_dedup_hits— 合并的并发请求数firnflow_backend_requests— 对对象存储的总后端请求数(成本信号)firnflow_object_cache_hits/firnflow_object_cache_misses— 对象字节范围缓存命中与未命中firnflow_storage_bytes_read/firnflow_storage_bytes_written— 对象存储 I/O 字节数firnflow_query_duration_seconds— 查询执行时间直方图firnflow_ingested_rows— 已摄取的行总数
可以使用 FIRNFLOW_METRICS_PREFIX 为指标添加前缀,以便在存在其他 firnflow 实例时防止冲突。
许可证
Firn 根据 MIT 许可证发布。
相似文章
@techwith_ram:一个1000万文档的语料库以float32格式占用31GB内存。大多数团队遇到这一瓶颈后会转向托管向量数据库。每月400美元……
turbovec 是一个开源的 Rust 向量索引,使用 Google Research 的 TurboQuant 算法,实现了16倍压缩,搜索速度比 FAISS 更快,并且集成了 LangChain、LlamaIndex 和 Haystack 等 RAG 框架。
@hasantoxr:向量数据库不再是云产品。它们正在变成 pip install。一个名为 turbovec 的新开源项目……
一个名为 turbovec 的开源项目在 GitHub 上获得了 1 万星标。它是一个基于 Rust、带有 Python 绑定的向量索引,使用谷歌研究的 TurboQuant 算法将嵌入压缩到接近理论香农极限,使得完全本地的 RAG(检索增强生成)成为可能——1000 万文档仅需 4 GB RAM,且搜索速度快于 FAISS。
Fluree DB(GitHub 仓库)
Fluree DB 是一个开源的时间图数据库,具有类似 Git 的分支、集成的向量/文本/地理搜索、细粒度的访问控制,并支持 SPARQL、JSON-LD 和 Open Cypher。它针对 AI 代理记忆进行了优化,在十亿级图上实现了高性能。
@msimoni: 我一直在思考的一件事:以类似S3的对象存储为原语,你可以构建一个具有无限吞吐量的事务数据库…
一条推文讨论了使用类似S3的对象存储和内容寻址构建具有无限吞吐量的事务数据库的想法,其中块被并行写入,根哈希定期更新。
FlashTrie:一种用于生成式检索的GPU加速约束束搜索方法
FlashTrie提出了一种GPU加速的约束束搜索方法用于生成式检索,利用简洁的trie布局和协作式CUDA内核来降低解码延迟,实现大规模实时服务,在商业搜索引擎中实现了高达24倍的加速和0.71%的收入提升。