TencentDB Agent Memory 有向量检索吗:embed 与 vector 命中 0 处

2026-08-16

先说清楚这篇在核什么

截至 2026-08-16,TencentCloud/TencentDB-Agent-Memory 这个仓库在 GitHub 上挂的 topics 是这九个:agentai-agentembeddingllmlocal-firstlong-term-memorymemoryopenclaw-pluginvector-search。里面有 embedding,也有 vector-search

一个正常的读者看到这两个标签,接下来会做的事很具体:进仓库找 embedding 模型的配置项、找向量维度、找向量索引类型、找是不是要额外起一个向量数据库容器。我们也是这么找的,找的是 MemoryKnowledge/ 这一个模块——因为这个模块的自我定位就是知识服务,package.jsondescription 原文写的是 Standalone knowledge service — Code-Graph + LLM-Wiki engine for user-side deployment

结果是:在 MemoryKnowledge/ 目录下的全部文件里搜 embedvector|Vector命中 0 处

这就是本文的全部起点。先把两处位置摆出来:一处是仓库的 GitHub topics(embedding / vector-search),一处是 MemoryKnowledge/ 的源码树(这两个关键词一次都不出现)。两者不一致,以我们实读的仓库状态为准。至于为什么会这样、哪个更能代表项目意图,我们不推断,也不拿这件事去评价这个项目——说完差异就停。

有两个口径要先钉死,否则这条结论会被读歪:

  • 我们扫的只有 MemoryKnowledge/ 这一个模块。同仓的 MemoryCoreMemoryPanelMemoryProxy 有没有向量实现,我们没有核查,本文不覆盖,也不由此外推。
  • 我们采集的是默认分支 feat/server_team 上的快照 97f9465,核对日 2026-08-16。这个仓库的默认分支就是 feat/server_team,不是 main 也不是 master,所以下文提到的任何文件路径,都请按这个分支去对。该模块 package.json 里的版本还是 0.1.0,整仓处于 beta 阶段,参数、默认值与接口随版本变动,请以仓库最新内容为准。

你自己怎么复核这一条

这类结论最怕的就是「作者说没有就没有」。所以把动作给你,你在自己拉的快照里跑一遍就行。进到 MemoryKnowledge/ 目录下执行:

python -c "
import os,re
for r,d,fs in os.walk('.'):
    for f in fs:
        fp=os.path.join(r,f).replace(os.sep,'/')
        for i,l in enumerate(open(fp,encoding='utf-8',errors='replace'),1):
            if re.search(r'embed|vector|Vector',l): print(fp,i,l.strip())
"

Windows 下在 PowerShell 或 Git Bash 里都可以执行。脚本里的 encoding='utf-8' 不要去掉——这个仓库里有中文注释,按系统默认编码读容易读成乱码,我们做这次统计时也是全程显式指定 UTF-8 的。我们这边跑出来没有任何输出行。

作为参照,这个模块并不小:.ts 文件 58 个,合计 11,289 行(src/ 下是 56 文件 11,249 行),均为我们在 2026-08-16 的快照上数出来的。这两个关键词在这一万一千多行里一次都没有出现。

顺带说一句判定边界:如果你搜的是仓库根目录而不是 MemoryKnowledge/,那命中不为 0 也很正常,因为根 README、ROADMAP 以及另外三个模块都不在本文的核查范围里。搜出东西来不等于本文这条结论被推翻,而是你扫的范围和我们不是同一个。

那这个模块的检索到底是怎么做的

关键词搜不到向量,不代表这个模块没有检索能力——它的检索层是实打实存在的,只是走的是另一条技术路线。沿着代码走一遍:

第一层:每个 wiki 一个私有的 index.dbMemoryKnowledge/src/engines/wiki/index-db.ts 的模块注释写明,每个 wiki 对应一个独立的 SQLite 文件 index.db,与正文 .md 放同一目录、同生命周期。initSchema() 在里面建四张表(该文件 72-119 行):

形态关键列
wiki_ftsFTS5 虚拟表page_id UNINDEXED, title_tok, content_tok
page_meta普通表page_id(PK) title type rel_path snippet
graph_edge普通表source_id target_id,联合主键
source普通表filename(PK) sha256 size status

检索能力就落在第一张表 wiki_fts 上,它的 tokenize 参数写死为 'unicode61 remove_diacritics 0'(该文件 75-82 行)。第二张 page_meta 有一行注释值得注意:正文不入库,留磁盘——所以库里只有分词后的索引和元数据,正文本体还在 .md 文件里。

**第二层:BM25 排序。**实际的检索实现在 MemoryKnowledge/src/engines/wiki/manager.tsftsSearch()(381-391 行):把 query 过一遍 tokenize(),每个 token 加 * 做前缀匹配,用 OR 连起来去 wiki_fts MATCH,排序用的是 bm25(wiki_fts, 5.0, 1.0)——即 title_tok 权重 5.0、content_tok 权重 1.0,再取负号把 SQLite 的 BM25 值转成越大越相关。

这个 5.0 : 1.0 是代码里写死的常量,不是环境变量,也不在 src/config.ts 的配置表里。想改它就得改代码。

第三层:中文怎么切。tokenize() 在同一文件的 340-374 行:英文按空格和标点切开并过一遍停用词,中文走 bigram + 整词双路,中英混合的 token 先拆开再分别处理。停用词表 STOP_WORDS 在 308-314 行,中英各一批。这一层是纯手写的规则分词,package.json 里虽然声明了 @node-rs/jieba,但我们在 src/ 下 grep 不到对它的 import——这里只陈述「grep 不到 import」这个事实,不推断这个依赖还有没有别的用途。

**第四层:图扩展。**BM25 出的结果不是终点。MemoryKnowledge/src/engines/wiki/graph-search.ts 会从 BM25 命中的种子节点出发,沿着 [[wikilink]] 形成的边做多跳 BFS,每跳按 decay 衰减分数,种子固定 hop=0。图对象用的是 graphology,每次查询时从 graph_edge 表临时构建内存图(manager.ts:9,14,177)。

这一层的默认值(manager.ts:439-445)值得单独列,因为它们决定了默认行为长什么样:

常量默认值
DEFAULT_LIMIT20
DEFAULT_HOP0
DEFAULT_DECAY0.5
DEFAULT_MIN_SCORE0.1
HOP_LIMIT5
RELATED_CAP10
EXPANSION_CAP200

DEFAULT_HOP 是 0,graph-search.ts:38DEFAULT_MAX_NODES 是 200。也就是说,按代码语义,调用方不显式传 hop 时,图扩展这一层默认是不展开的,只剩下纯 BM25。路由层还会做参数校验:hop 必须是 0 到 5 的整数、decay 在 0 到 1 之间、minScore 非负(MemoryKnowledge/src/routes/wiki.ts:490,498,506)。

这些都是配置里的默认值,不是「你用起来会怎样」的保证。这套检索在你的语料上召回如何、和向量检索相比在哪些场景更合适——我们没有部署、没有跑过一次查询,没有依据评价,这里不给结论。

三个能佐证「这一层确实不存在」的旁证

单靠一次关键词扫描下结论是不够稳的,还有三处可以互相印证:

一,OpenAPI 规格里的措辞。MemoryKnowledge/openapi.yaml 第 408 行,POST /wiki/search 这个端点的 summary 原文写的是 Search wiki pages (BM25 full-text)。规格自己就把这个端点标成了 BM25 全文检索,没有出现语义检索、向量、相似度一类的字眼。

二,容器编排里没有向量库。MemoryKnowledge/docker-compose.yml 全文 50 行,只声明了 knowledge 一个 service,build: .,端口 ${TEAM_KNOWLEDGE_HOST_PORT:-8421}:8421,一个命名卷 knowledge-data:/app/data。它没有依赖任何数据库、缓存或消息队列容器——没有 postgres、没有 redis、没有 clickhouse,也没有任何向量库服务。整套数据落地就是文件系统上的 .md 加 SQLite。

三,被替换掉的旧方案留在注释里。package.json 里声明了 minisearch,但我们在 src/ 下 grep 不到对它的 import,它只在注释中作为「被替换掉的旧方案」出现,位置是 src/engines/wiki/index-db.ts:17src/engines/wiki/manager.ts:8,379。这条同样只记录现象。

这件事对你意味着什么

如果你正准备把这个模块接进自己的系统,这处差异会直接改变你的准备清单:

**你不需要为它准备 embedding 服务,也不需要准备向量库。**按仓库里能核到的内容,这个模块的检索链路是 SQLite FTS5 + BM25 + wikilink 图扩展,落地形态是每个 wiki 一个 index.db。至于 embedding 模型名、向量维度、向量索引类型这些参数——未指定,因为仓库里根本没有这一层。你在 src/config.ts 的环境变量表里翻不到它们不是配漏了,是它们不存在。

**LLM 是用在生成侧,不是检索侧。**这个模块确实要调 LLM,src/engines/wiki/ingest-v2/llm.ts 用 Vercel AI SDK 的 generateText,走的是「文档进来 → LLM 抽取成结构化页面 → 落盘 → 建 FTS 索引」这条摄取链路。检索的时候查的是 FTS5 索引,不是再过一次模型。把这两段分清楚,你估算的调用面会完全不同。

**如果你确实需要语义检索,得自己在外面加一层。**要不要加、怎么加,取决于你的用法,项目没给通用值,也没在 ROADMAP 里给出方向——我们通读了 ROADMAP_CN.md 全文 108 行,里面没有任何 Knowledge / Wiki / Code-Graph 相关的待办条目,所以「本模块的向量检索计划」在这个仓库里查不到出处。查不到就是查不到,不代表没有,只代表本仓库里读不到。

收尾:标签是标签,代码是代码

这一篇其实没什么复杂结论,就一件事:仓库的 topics 里挂着 embeddingvector-search,而 MemoryKnowledge/ 这一万一千多行代码里这两个词一次都没出现。两处位置都已标明,你可以用上面那段脚本在自己的快照上复核一遍。

顺着这条线还能带出一个更一般的习惯:**GitHub topics、README 的能力表、ROADMAP 的条目,都属于「声称」这一层;真正能兑现的是代码那一层。**这个模块里类似的两层差异不止这一处——规格自称 28 个端点而代码在 /v3 前缀下注册了 37 条,llm_binding 表在 Drizzle schema 与运行时建表 SQL 里的列不一样,端口在模块内是 8421 而仓库根安装文档写 8424,这些我们另有篇目专门讲。核到哪一层,就只按那一层写。

延伸阅读


本文依据 TencentDB Agent Memory 官方仓库(github.com/TencentCloud/TencentDB-Agent-Memoryfeat/server_team 分支上的 README、INSTALL、CHANGELOG、ROADMAP 与四个模块的源码整理, 核对日 2026-08-16,对应仓库快照 97f9465。该仓库的默认分支即为 feat/server_team。 本文内容为仓库源码与文档口径,我们没有部署、也没有运行过该项目的任何一个模块, 因此不涉及运行效果、检索质量与性能的任何描述。 该项目主模块处于 beta 阶段、其余模块版本号仍为 0.1.0,参数与接口随版本变动,请以仓库最新内容为准。 该项目会采集并存储团队的对话、文档与代码,属于敏感数据,是否使用请结合自身合规要求评估。 安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。