TencentDB Agent Memory 有向量检索吗:embed 与 vector 命中 0 处
先说清楚这篇在核什么
截至 2026-08-16,TencentCloud/TencentDB-Agent-Memory 这个仓库在 GitHub 上挂的 topics 是这九个:agent、ai-agent、embedding、llm、local-first、long-term-memory、memory、openclaw-plugin、vector-search。里面有 embedding,也有 vector-search。
一个正常的读者看到这两个标签,接下来会做的事很具体:进仓库找 embedding 模型的配置项、找向量维度、找向量索引类型、找是不是要额外起一个向量数据库容器。我们也是这么找的,找的是 MemoryKnowledge/ 这一个模块——因为这个模块的自我定位就是知识服务,package.json 的 description 原文写的是 Standalone knowledge service — Code-Graph + LLM-Wiki engine for user-side deployment。
结果是:在 MemoryKnowledge/ 目录下的全部文件里搜 embed 与 vector|Vector,命中 0 处。
这就是本文的全部起点。先把两处位置摆出来:一处是仓库的 GitHub topics(embedding / vector-search),一处是 MemoryKnowledge/ 的源码树(这两个关键词一次都不出现)。两者不一致,以我们实读的仓库状态为准。至于为什么会这样、哪个更能代表项目意图,我们不推断,也不拿这件事去评价这个项目——说完差异就停。
有两个口径要先钉死,否则这条结论会被读歪:
- 我们扫的只有
MemoryKnowledge/这一个模块。同仓的MemoryCore、MemoryPanel、MemoryProxy有没有向量实现,我们没有核查,本文不覆盖,也不由此外推。 - 我们采集的是默认分支
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.db。MemoryKnowledge/src/engines/wiki/index-db.ts 的模块注释写明,每个 wiki 对应一个独立的 SQLite 文件 index.db,与正文 .md 放同一目录、同生命周期。initSchema() 在里面建四张表(该文件 72-119 行):
| 表 | 形态 | 关键列 |
|---|---|---|
wiki_fts | FTS5 虚拟表 | 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.ts 的 ftsSearch()(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_LIMIT | 20 |
DEFAULT_HOP | 0 |
DEFAULT_DECAY | 0.5 |
DEFAULT_MIN_SCORE | 0.1 |
HOP_LIMIT | 5 |
RELATED_CAP | 10 |
EXPANSION_CAP | 200 |
DEFAULT_HOP 是 0,graph-search.ts:38 的 DEFAULT_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:17 与 src/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 里挂着 embedding 和 vector-search,而 MemoryKnowledge/ 这一万一千多行代码里这两个词一次都没出现。两处位置都已标明,你可以用上面那段脚本在自己的快照上复核一遍。
顺着这条线还能带出一个更一般的习惯:**GitHub topics、README 的能力表、ROADMAP 的条目,都属于「声称」这一层;真正能兑现的是代码那一层。**这个模块里类似的两层差异不止这一处——规格自称 28 个端点而代码在 /v3 前缀下注册了 37 条,llm_binding 表在 Drizzle schema 与运行时建表 SQL 里的列不一样,端口在模块内是 8421 而仓库根安装文档写 8424,这些我们另有篇目专门讲。核到哪一层,就只按那一层写。
延伸阅读
- 从头读起:TencentDB Agent Memory 是什么:团队级 Agent 记忆中枢怎么读
- 本专题共 40 篇,完整分组目录见专题页
- TencentDB Agent Memory 的检索实现:FTS5 加 bm25 再做图扩展
- TencentDB Agent Memory 的 OpenAPI:自称 28 个端点,代码 37 条
本文依据 TencentDB Agent Memory 官方仓库(github.com/TencentCloud/TencentDB-Agent-Memory)
feat/server_team 分支上的 README、INSTALL、CHANGELOG、ROADMAP 与四个模块的源码整理,
核对日 2026-08-16,对应仓库快照 97f9465。该仓库的默认分支即为 feat/server_team。
本文内容为仓库源码与文档口径,我们没有部署、也没有运行过该项目的任何一个模块,
因此不涉及运行效果、检索质量与性能的任何描述。
该项目主模块处于 beta 阶段、其余模块版本号仍为 0.1.0,参数与接口随版本变动,请以仓库最新内容为准。
该项目会采集并存储团队的对话、文档与代码,属于敏感数据,是否使用请结合自身合规要求评估。
安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。