资讯动态

Mastra 的 DuckDB 一体化存储实战:HNSW 向量检索与全量可观测性追踪

发布时间:2026/9/15 10:52:56 来源:尧图企业网站定制
Mastra 的 DuckDB 一体化存储实战HNSW 向量检索与全量可观测性追踪【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastramastra/duckdb是 Mastra 框架中一个单进程内嵌数据库式的双域存储包一方面通过 DuckDB VSS 扩展提供 HNSW 索引的向量相似度检索DuckDBVector另一方面基于 DuckDB 的 OLAP 能力为 traces、metrics、logs、scores、feedback 五类可观测性信号提供持久化与高级查询DuckDBStore。读完本文你将掌握如何在 Mastra 应用中以组合存储的方式接入 DuckDB配置内存与线程参数规避大库查询导致的 CPU/内存尖峰并熟练使用从基础列表到 1.8.0 新增的 span 属性、feedback、score 与顶层 metadata 谓词在内的完整 trace 查询语法。包定位一个进程、两份能力从仓库入口文件 stores/duckdb/src/index.ts 可以看到mastra/duckdb同时导出了两条产品线export { DuckDBVector } from ./vector/index; export type { DuckDBVectorConfig, DuckDBVectorFilter } from ./vector/types; export { DuckDBConnection, DuckDBStore, ObservabilityStorageDuckDB } from ./storage/index; export type { DuckDBStorageConfig, DuckDBStoreConfig, ObservabilityDuckDBConfig } from ./storage/index;向量存储DuckDBVector实现MastraVector接口使用 DuckDB VSS 扩展创建 HNSW 索引不需要额外部署向量数据库服务。可观测性存储DuckDBStore组合存储只暴露observability域内部由惰性加载的ObservabilityStorageDuckDB委托实现DuckDBConnection则封装了底层连接、参数绑定、事务与关闭逻辑。根据 stores/duckdb/package.json该包唯一运行时依赖是duckdb/node-api^1.5.2-r.2对mastra/core的 peer 依赖区间为1.58.0-0 2.0.0-0要求 Node.js22.13.0。也就是说只要你的应用已有 Mastra 核心运行时安装这一个包即可同时获得检索与追踪两大存储能力。安装与向量存储HNSW 相似度检索开箱即用安装命令对应 stores/duckdb/README.mdnpm install mastra/duckdb初始化一个持久化向量库并注册到 Mastraimport { Mastra } from mastra/core; import { DuckDBVector } from mastra/duckdb; const vectorStore new DuckDBVector({ id: rag-store, path: ./rag-vectors.duckdb, }); // 接入 Mastra 的 RAG 系统 const mastra new Mastra({ vectors: { ragStore: vectorStore, }, });包在 1.0.0 引入向量存储时给出的完整示例见 stores/duckdb/CHANGELOG.md 1.0.0 条目包含了建索引、写入与查询三步import { DuckDBVector } from mastra/duckdb; const vectorStore new DuckDBVector({ id: my-store, path: :memory:, // 或 ./vectors.duckdb 用于持久化 }); await vectorStore.createIndex({ indexName: docs, dimension: 1536, metric: cosine, }); await vectorStore.upsert({ indexName: docs, vectors: [[0.1, 0.2, ...]], metadata: [{ text: hello world }], }); const results await vectorStore.query({ indexName: docs, queryVector: [0.1, 0.2, ...], topK: 10, filter: { text: hello world }, });从源码 stores/duckdb/src/vector/index.ts 可以看到底层机制初始化时执行INSTALL vss; LOAD vss;加载向量扩展若 VSS 不可用则降级为基本数组运算并打印VSS extension not available, using basic array operations警告第 75-86 行。createIndex阶段创建USING HNSW (vector)的 HNSW 索引第 337-348 行若索引创建失败同样降级为线性扫描。构造器默认值为path: :memory:、dimensions: 1536、metric: cosine第 42-47 行这些默认值都可被传入的DuckDBVectorConfig覆盖。可观测性存储以组合存储接入 Mastra1.1.0 起包新增了 DuckDB 可观测性存储支持 traces、metrics、logs、scores、feedback 五类信号。官方推荐的接入方式是使用MastraCompositeStore把 DuckDB 专门用作 observability 域其余域交给其他存储如 LibSQLimport { Mastra } from mastra/core/mastra; import { DefaultExporter, Observability } from mastra/observability; import { MastraCompositeStore } from mastra/core/storage; import { LibSQLStore } from mastra/libsql; import { DuckDBStore } from mastra/duckdb; const duckDBStore new DuckDBStore(); const libSqlStore new LibSQLStore(); const storage new MastraCompositeStore({ id: composite, domains: { ...libSqlStore.stores, observability: duckDBStore.observability, }, }); export const mastra new Mastra({ agents: {/* your agents here */}, observability: new Observability({ configs: { default: { serviceName: obs-test, exporters: [new DefaultExporter()], }, }, }), storage, });DuckDBStore的构造与close()语义stores/duckdb/src/storage/index.ts构造器默认id: duckdb内部创建DuckDBConnection并装配observability域stores只包含 observability 一项因此文档明确建议通过组合存储补齐其他域。close()会释放 DuckDB 的原生文件锁。1.4.1 的修复说明这一点很关键开发模式下mastra dev热重载若不释放文件锁重启进程会遇到Conflicting lock is held错误Mastra.shutdown()会自动调用它重复调用是安全的 no-op。底层连接管理stores/duckdb/src/storage/db/index.ts提供query、execute、executeTransactionBEGIN/COMMIT/ROLLBACK、executeBatch单连接批量执行无参 DDL用于加速 schema 初始化等方法。参数绑定使用bindParam显式类型化方法bindNull/bindVarchar/bindInteger/bindDouble/bindBoolean/bindBigInt/bindTimestamp这修复了依赖 DuckDB 类型推断时在json_extract_string等 SQL 上下文报Cannot create values of type ANY的问题1.1.0 Patch。高级 Trace 查询1.8.0 的四种谓词形态1.7.0 为 DuckDB 引入了与 ClickHouse 对齐的 advanced trace query 能力过滤、分组、排序、游标分页与共享跨适配器语义1.8.0 在此基础上补齐了四类更丰富的谓词全部通过mastraClient.queryTraces使用。1. 同 span 属性谓词span properties—— 可基于status、model、duration、outcome、identity、lineage 等字段过滤await mastraClient.queryTraces({ timeRange: { from: 2026-08-01T00:00:00.000Z, to: 2026-08-08T00:00:00.000Z }, where: { spans: { some: { op: eq, left: { path: status }, right: { literal: error } } } }, });2. 关联 feedback 过滤—— 按反馈类型等字段筛选 trace同一feedbackId的重复写入会保留最新一条保证谓词求值结果一致await mastraClient.queryTraces({ timeRange: { from: 2026-08-01T00:00:00.000Z, to: 2026-08-08T00:00:00.000Z }, where: { feedback: { some: { op: eq, left: { path: feedbackType }, right: { literal: rating } } } }, });3. 更丰富的 score 谓词—— 例如按scoreSource过滤await mastraClient.queryTraces({ timeRange: { from: 2026-08-01T00:00:00.000Z, to: 2026-08-08T00:00:00.000Z }, where: { scores: { some: { op: eq, left: { path: scoreSource }, right: { literal: automated } } } }, });4. 顶层 metadata 谓词—— 直接针对 trace 的顶层元数据做存在性判断await mastraClient.queryTraces({ timeRange: { from: 2026-08-01T00:00:00.000Z, to: 2026-08-08T00:00:00.000Z, }, where: { op: notExists, path: metadata.parentMessageId }, });这些谓词最终编译为 SQL。查询编译器位于 stores/duckdb/src/storage/domains/observability/trace-query.ts通过字段注册表将逻辑字段映射到具体 SQL 列与参数类型TRACE_FIELDStraceId、threadId、resourceId、startedAt、endedAt、entityName、entityType、environment、statusstatus 由CASE WHEN r.error IS NOT NULL THEN error ELSE success END计算得出SPAN_FIELDSname、spanType、model、provider、durationMs、error以及entityVersionId系列版本字段SCORE_FIELDSscorerId、scorerVersion、scoreSource、score、spanId等FEEDBACK_FIELDSfeedbackType、feedbackSource、feedbackUserId、sourceId、comment等。指标查询count_distinct 聚合与服务端 TopK1.3.0 为指标存储 API 引入了两个面向高基数场景的能力stores/duckdb/CHANGELOG.md 1.3.0 条目。count_distinct 聚合getMetricAggregate、getMetricBreakdown、getMetricTimeSeries接受aggregation: count_distinct并配合distinctColumn。DuckDB 后端映射为approx_count_distinctClickHouse 则用uniq从而让基于threadId、resourceId等高基数维度构建的仪表盘保持快速且结果有界。distinctColumn被限制在低/中基数的分类允许列表内entityType、entityName、parentEntityType、parentEntityName、rootEntityType、rootEntityName、name、provider、model、environment、executionSource、serviceNameID 列被禁止——因为对近似唯一的值做去重计数会退化为行数几乎没有分析价值。await store.getMetricAggregate({ name: [mastra_llm_tokens_total], aggregation: count_distinct, distinctColumn: model, filters: { timestamp: { start, end } }, });服务端 TopKgetMetricBreakdown支持limit与orderDirection让 breakdown 永远不从数据库拉回列的全量基数。排序始终按聚合后的value进行orderDirection在 top-NDESC默认与 bottom-NASC之间切换await store.getMetricBreakdown({ name: [mastra_agent_duration_ms], aggregation: sum, groupBy: [threadId], limit: 20, orderDirection: DESC, });1.6.0 还加入了批量 trace ID 过滤可一次查询多个指定 trace 的指标明细const result await observability.getMetricBreakdown({ name: [mastra_model_total_input_tokens], aggregation: sum, groupBy: [traceId], filters: { traceIds: [trace-1, trace-2] }, });评分与反馈分析聚合、分桶、时间序列与分位数1.1.0 起 DuckDB 支持基于 score 与 feedback 的分析查询包括计数、平均等聚合、按 model/environment 等维度的分桶、固定间隔的时间序列以及 p50/p95 等分位数计算。官方示例const result await store.observability.getScorePercentiles({ scorerId: relevance, percentiles: [0.5, 0.95], interval: 1h, }); // { series: [{ percentile: 0.5, points: [{ timestamp, value }] }, ...] }1.2.0 为所有可观测性信号logId、metricId、scoreId、feedbackId统一引入了唯一 ID用于框架管线内的去重与跨系统关联用户侧 APIlogger.info()、metrics.emit()、addScore()、addFeedback()保持不变。1.3.0 增加了按scoreId直接取回评分记录的能力getScoreById无需扫描分页的评分列表。1.6.4 为 feedback 增加reviewStatus列默认needs-review支持读写映射、按状态列表过滤以及updateFeedbackReviewStatus更新方法。1.8.0 补充了按 ID 删除 feedback 与 score 的能力并支持可选的 organization 与 resource 过滤await observability.deleteFeedback({ feedbackIds: [feedback-1] }); await observability.deleteScores({ scoreIds: [score-1], resourceId: resource-1 });性能调优memoryLimit 与 threads1.5.2 修复了一个针对大型 DuckDB 库的严重问题在 Studio 打开 traces 页或调用列表 API 时每次翻页/轮询都会解压整个span_events表导致 CPU 全核打满、内存膨胀数 GB。修复手段有三分页查询只扫描请求 span 所在的时间范围带过滤与自定义排序的查询先在窄列集上分页再重建完整 span 负载无新数据时 delta 轮询直接短路。同时该版本为DuckDBStore增加了两个资源控制参数const store new DuckDBStore({ path: mastra.duckdb, memoryLimit: 4GB, // 默认 2GB threads: 2, // 默认每个 CPU 核心一个线程 });这两个参数在 stores/duckdb/src/storage/db/index.ts 中直接映射为 DuckDB 实例选项memoryLimit对应max_memory默认2GB。DuckDB 自身的默认值是系统内存的 80%对一个内嵌在应用服务器里的存储来说过于激进——单条大查询就可能把进程撑到 swap文件型数据库可以把超内存操作溢写磁盘而:memory:数据库无法溢写所以对超大内存库查询需要调高此值。threads对应 DuckDB 的threads选项默认每 CPU 核一个线程在多租户共享服务器上调低可以避免查询独占所有核心。1.5.2 的描述给出了量级参考在 multi-GB 数据库上trace 列表查询的 CPU 开销大约下降为原来的五分之一并保持在有界内存预算内。1.6.2 还修复了 Studio 对 DuckDB 可观测性存储的 metrics/logs 探测问题确保资源页能被正确识别。轻量列表与增量轮询delta polling围绕大库列表性能包提供了轻量 增量的组合能力1.3.2 暴露GET /observability/traces/light及对应的存储支持用于拉取不含 span 负载的分页 trace 列表行。1.5.1 修复了listTracesLight因惰性存储门面缺少转发方法而抛This storage provider does not support listing lightweight traces的问题——DuckDB 本身完全支持该操作。1.6.1 修复了轻量列表忽略 delta 轮询参数的问题listTracesLight之前忽略mode、after、limit导致客户端每次轮询都重新拉取首页且永远拿不到delta/deltaCursor。现在 delta 请求只返回游标之后新记录的轻量行行数据携带短inputPreview替代完整 input、计算出的status与 spanmetadata页面响应包含deltaCursor轮询可以随时切换到 delta 模式。该实现依赖mastra/core 1.57.0提供的buildInputPreview与computeTraceStatus共享助手。1.4.0 在 core、DuckDB、ClickHouse 三端统一加入了可观测性列表 API 的 delta polling 支持1.7.0 的高级 trace 查询则自带游标分页。ObservabilityStorageDuckDB门面会依据mastra/core是否声明observability-delta-polling特性来切换静态特性列表[metrics, logs, trace-query]与[metrics, logs, delta-polling, trace-query]见 stores/duckdb/src/storage/index.ts 第 14-16 行保证与旧版核心运行时组合时能够优雅降级。迁移与版本兼容要点信号 ID 迁移从旧版升级到 1.2.0 时对既有的 DuckDB 可观测性信号表需要先执行npx mastra migrate再初始化 store以便应用新的信号 ID schema同样适用于 ClickHouse。版本字段迁移1.1.2 为 spans、metrics、scores、feedback、logs 表新增了entityVersionId、parentEntityVersionId、rootEntityVersionId列用于按实体版本过滤/分组 trace并附带了针对现有库的 ALTER TABLE 迁移。reviewStatus 迁移1.6.4 新增 feedback 的reviewStatus列默认值needs-review。core 版本约束1.6.1 起该包的 peer 依赖下限被提高到与所使用 API 匹配1.58.0-01.1.0 曾明确较老的mastra/core在使用 DuckDB 可观测性存储时会显示升级错误。若ObservabilityStorageDuckDB加载具体实现时发现 core 缺少对应导出如does not provide an export named等会抛出结构化的MastraErrorErrorCategory.SYSTEM错误 IDOBSERVABILITY_STORAGE_DUCKDB_CORE_UPGRADE_NOT_IMPLEMENTED提示升级 core。dev 热重载升级到 1.4.1DuckDBStore.close()会在关闭时释放原生文件锁避免mastra dev热重载时出现Conflicting lock is held。供应链修复1.4.3 为 2026-06-17 easy-day-js 供应链事件做了版本清理patch bump 发布干净版本并前移latestdist-tag。安装兼容1.2.0 起使用可解析的duckdb/node-api版本区间解决安装失败问题。版本能力速览版本核心能力1.0.0引入DuckDBVectorHNSW 索引向量检索支持:memory:与文件持久化1.1.0引入 DuckDB 可观测性存储traces/metrics/logs/scores/feedbackscore/feedback 聚合、分桶、时间序列与分位数分析1.2.0全信号唯一 ID需npx mastra migrategetTraceLight1.3.0listBranches/getSpanscount_distinct聚合与服务端 TopKgetScoreById1.4.0可观测性列表 API 的 delta polling1.4.1 修复热重载文件锁1.4.3 供应链清理1.5.1修复listTracesLight门面转发1.5.2大库列表性能修复新增memoryLimit默认 2GB与threads配置1.6.x指标批量 trace ID 过滤Studio metrics/logs 探测修复feedbackreviewStatus1.7.0高级 trace 查询过滤/分组/排序/游标分页、跨适配器语义一致、查询形态感知的关系读取1.8.0span 属性、feedback、score、顶层 metadata 四类谓词feedback/score 按 ID 删除综上所述mastra/duckdb的价值在于零外部服务向量检索与可观测性都跑在进程内天然适合本地开发、单机部署与边缘场景。生产化时请重点关注三点——用MastraCompositeStore把 observability 域交给 DuckDB、按机器资源显式设置memoryLimit/threads、在升级涉及 schema 的版本后及时执行npx mastra migrate。相关实现与测试可继续在仓库 stores/duckdb/src向量、连接、各可观测性域与 stores/duckdb/src/storage/domains/observability/index.test.ts、stores/duckdb/src/storage/domains/observability/trace-query.test.ts 中深入研读。【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价