<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>潘锦的空间 &#187; OpenViking</title>
	<atom:link href="https://www.phppan.com/tag/openviking/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.phppan.com</link>
	<description>SaaS SaaS架构 团队管理 技术管理 技术架构 PHP 内核 扩展 项目管理</description>
	<lastBuildDate>Sun, 30 Aug 2026 05:26:34 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.9.40</generator>
	<item>
		<title>做 Agent 架构时，OpenViking 的几个可以学习的点</title>
		<link>https://www.phppan.com/2026/07/agent-openviking/</link>
		<comments>https://www.phppan.com/2026/07/agent-openviking/#comments</comments>
		<pubDate>Sun, 26 Jul 2026 03:59:43 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[架构和远方]]></category>
		<category><![CDATA[Agent]]></category>
		<category><![CDATA[OpenViking]]></category>

		<guid isPermaLink="false">https://www.phppan.com/?p=2521</guid>
		<description><![CDATA[设计 Agent 架构时，有一个模块的边界经常画不清晰：上下文。规划、工具调用、执行循环这些组件的职责都好切分 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p style="color: #191b1f;" data-first-child="" data-pid="EAu8Ffnz">设计 Agent 架构时，有一个模块的边界经常画不清晰：上下文。规划、工具调用、执行循环这些组件的职责都好切分，唯独「Agent 该知道什么」这件事，散落在 prompt 模板、RAG 管道、记忆插件和会话历史四个地方，各管一段，互不通气。</p>
<p style="color: #191b1f;" data-pid="aMUyz_Cj">比较常见的状态是知识走一条 RAG 管道，用户记忆走一个独立的 memory 服务，工具使用经验干脆没有沉淀机制，靠 system prompt 里手写的几条注意事项撑着。跑长周期任务时问题集中爆发：第三十轮时 Agent 忘了第五轮的约束；召回了一段错误文档，事后想归因，向量库只给一个相似度 0.83，别的什么都没有。</p>
<p style="color: #191b1f;" data-pid="el4iar4w">这两个 case 背后是同一个架构缺陷：上下文没有被当作一个独立子系统来设计，它只是若干条数据管道的松散集合。</p>
<p style="color: #191b1f;" data-pid="-LSVd0qA">最近把火山引擎开源的 OpenViking 看了一遍，它把自己定位成「面向 AI 智能体的上下文数据库」，GitHub 上 27.2k star。这个定位本身就是一个架构主张：上下文应该是 Agent 架构里一个有统一接口、有存储模型、有检索语义、可观测的独立组件，地位类比业务系统里的数据库。</p>
<p style="color: #191b1f;" data-pid="cvQ_eRuL">沿着这个主张往下拆，它有几个设计决策对做 Agent 架构的人有一些参考价值。</p>
<h2 style="font-weight: 500; color: #191b1f;">统一存储模型</h2>
<p style="color: #191b1f;" data-pid="OXbI9IFm">Agent 架构里第一个要回答的问题：记忆、知识、技能这三类上下文，存储模型是分开还是统一。</p>
<p style="color: #191b1f;" data-pid="_C15LbGR">分开是多数团队的现状，也是我们踩过的坑——三套 schema、三套检索接口、三套更新逻辑，Agent 侧要维护三种访问心智。OpenViking 的选择是统一：全部抽象成文件，挂在 <code>viking://</code> 协议下的虚拟文件系统里，每个条目一个唯一 URI。它给出的目录结构：</p>
<div class="highlight" style="color: #191b1f;">
<pre><code class="language-text">viking://
├── resources/              # 资源：项目文档、代码库、网页等
│   └── my_project/
│       ├── docs/
│       │   ├── api/
│       │   └── tutorials/
│       └── src/
└── user/
    └── {user_id}/
        ├── memories/
        │   └── preferences/
        │       ├── writing_style
        │       └── coding_habits
        ├── resources/
        │   └── private_project/
        ├── skills/
        │   ├── search_code
        │   └── analyze_data
        └── peers/
            └── web-visitor-alice/</code></pre>
</div>
<p style="color: #191b1f;" data-pid="vT6qFbFR">Agent 用 <code>ls</code>、<code>tree</code>、<code>find</code> 浏览自己的上下文。</p>
<p style="color: #191b1f;" data-pid="2Yhb04Wj">从架构角度来看，这个统一带来两个收益。第一，定位从概率性变成确定性。扁平向量库里想精确更新某个用户的编码习惯记忆，只能靠 metadata filter 打补丁；文件系统里就是一个路径寻址，<code>viking://user/{user_id}/memories/preferences/coding_habits</code>，增删改查全部确定。多租户隔离也顺带解决了——<code>user/{user_id}</code> 这层目录天然就是隔离边界，商业版文档里明确把多租户共享和隔离列为核心场景。</p>
<p style="color: #191b1f;" data-pid="PgrcTj5b">第二，Agent 与上下文之间的接口收敛成了一套文件操作原语。这一点对架构的影响比看起来大。我们之前自研记忆系统时设计过一套 <code>memory.query(scope, filter, ...)</code> 风格的 API，模型调用的出错率明显高于让它直接操作路径。文件系统是 LLM 预训练语料里高频出现的心智模型，<code>ls</code> 和 <code>tree</code> 的语义模型天然理解，不需要在 prompt 里教。接口设计顺着模型先验走，省下的是持续的 prompt 工程成本。</p>
<p style="color: #191b1f;" data-pid="bMOXDRk6">代价在写入侧的分类决策。内容归置到哪个路径，做错了后续检索会系统性偏航，扁平向量库至少没有「放错文件夹」这种失败模式。OpenViking 靠写入时的自动语义处理来做归置，这个环节的质量上限决定了整棵文件树的可用性，我认为是它工程上最脆弱的一环。</p>
<h2 style="font-weight: 500; color: #191b1f;">预算分层供给</h2>
<p style="color: #191b1f;" data-pid="mHGZ2zN3">第二个架构问题：上下文以什么粒度供给给模型。</p>
<p style="color: #191b1f;" data-pid="H33IvGor">传统 RAG 的答案是 chunk 全量——检索 top-k 塞进 prompt，k 靠拍脑袋。这在架构上等于把上下文预算的管理责任丢给了一个魔法数字。OpenViking 的方案是写入时预计算三层表示：</p>
<ul style="color: #191b1f;">
<li data-pid="Tmtm70Kr">L0（摘要）：约 100 tokens，一句话总结，快速判断相关性</li>
<li data-pid="4oKtO6wj">L1（概览）：约 2k tokens，核心信息和使用场景，供规划阶段决策</li>
<li data-pid="-APyM9Yd">L2（详情）：完整原始数据，确有必要时才读</li>
</ul>
<p style="color: #191b1f;" data-pid="zBH3NtWe">每个目录也带自己的 <code>.abstract</code> 和 <code>.overview</code>，Agent 读任何完整文件之前，先花 100 个 token 判断这个方向值不值得深入。</p>
<p style="color: #191b1f;" data-pid="4-aXPxb3">放到 Agent 的执行循环里看，这三层恰好对应了三个阶段的信息需求：候选筛选阶段用 L0 扫一遍，规划阶段对少数目标加载 L1，执行阶段只对必要条目读 L2。上下文供给从一次性的赌博变成了跟随 Agent 决策流程的渐进加载，粒度和阶段对齐了。</p>
<p style="color: #191b1f;" data-pid="obq4ONV6">数据上，OpenViking 0.3.22 在 LoCoMo 长对话记忆评测里，三种 Agent 集成的准确率到 80–83%，原生记忆只有 24–57%；输入 token 减少 34.3%–91.0%，查询时延降低 58.45%–66.10%。token 降幅区间这么宽，说明收益高度依赖任务形态：判断型任务能省九成，需要全量细节的任务省不了多少。评测脚本在仓库 <code>./benchmark</code> 目录，可自行复现。</p>
<p style="color: #191b1f;" data-pid="ZChgUhTf">架构上的 trade-off 转移到了写入路径。L0/L1 由模型生成，每次数据摄入都有一笔推理开销，且是异步的——README 明确提示 <code>add-resource</code> 不加 <code>--wait</code> 时语义处理需要等待。写入吞吐敏感或数据高频变更的场景，这条路径会成为瓶颈。更隐蔽的风险是摘要写歪：L0 错了，后续所有基于它的相关性判断连带出错，等于在检索链路最上游埋单点。官方提供 <code>ov reindex &lt;uri&gt; --mode semantic_and_vectors</code> 重新生成语义产物再刷新向量，说明他们自己也预期摘要需要返工。</p>
<p style="color: #191b1f;" data-pid="zcid3ZaV">即便不引入 OpenViking，「写入时预计算多粒度表示、按 Agent 决策阶段供给」这个模式可以直接抄进自建架构。</p>
<h2 style="font-weight: 500; color: #191b1f;">检索即导航</h2>
<p style="color: #191b1f;" data-pid="kSImNmZF">检索组件在 Agent 架构里通常被实现成一个无状态函数：query 进，top-k 出。OpenViking 把它改成了一个有过程的导航。</p>
<p style="color: #191b1f;" data-pid="FMfkO849">先通过意图分析生成多个检索条件；向量检索定位初始切片所在的高分目录；在该目录下二次检索，高分结果更新进候选集；有子目录就逐层递归；最终返回最相关的上下文，连同周边语境一起。</p>
<p style="color: #191b1f;" data-pid="JeNy67s-">一句话概括：先锁定高分目录，再向下精细探索。</p>
<p style="color: #191b1f;" data-pid="QKso_oQd">这解决的是扁平 top-k 在 Agent 场景下的一个结构性缺陷——碎片没有语境。命中一个 chunk，Agent 不知道它前后是什么、属于哪份文档的哪个章节，拿到的是信息孤岛。导航式检索的返回结果自带位置和邻居：这段内容出自 API 文档的鉴权章节，同目录下还有 endpoints 说明。对代码库问答这类强依赖结构的任务，这个差异是决定性的。</p>
<p style="color: #191b1f;" data-pid="cH_9ytDz">代价：多轮向量查询加上可能的多次判断，单次检索的绝对延迟一定高于一把梭的 ANN。前面提到的时延降低 58%–66%，我的理解是端到端口径——省下的 token 让生成阶段变快，摊平了检索阶段的开销。架构选型时要按流量形态判断：Agent 任务型场景，单次任务价值高、容忍秒级检索，划算；高 QPS 低延迟的在线检索，这套递归策略不合适。</p>
<h2 style="font-weight: 500; color: #191b1f;">全链路留痕</h2>
<p style="color: #191b1f;" data-pid="lmAUpM13">Agent 架构的可观测性讨论，通常止步于工具调用日志。OpenViking 把留痕做进了检索内部：每次查询都保留完整的目录浏览轨迹，结果不对时能看到它出自哪条路径。</p>
<p style="color: #191b1f;" data-pid="dfFSb1CA">做过 RAG 生产运维的人知道 bad case 归因有多难。用户投诉答案错了，排查下来只能看到「这几个 chunk 相似度最高所以被召回」，正确内容为什么没进 top-k，向量空间不会解释。最后退化成调 embedding、调 chunk 大小、调 k 值的炼丹循环。</p>
<p style="color: #191b1f;" data-pid="sEX8qK4H">轨迹留存把归因变成可逐步 debug 的过程：检索在哪个目录拐错了弯、哪一层的 L0 摘要误导了判断，路径上每一步可查。修复动作随之有了着力点——重写某个目录的 abstract，或者调整文件归置，都对应到具体操作。配套的 OpenViking Helper 桌面端（Beta，支持 macOS 和 Windows x64）能解析 Claude Code、Codex、Trae 的会话，展示召回、Prompt 注入、MCP 调用、捕获和提交事件，Agent 与上下文系统之间的全部交互摆在明面上。</p>
<p style="color: #191b1f;" data-pid="wMsAyqnE">这一条我建议所有做 Agent 基础设施的团队照抄，无论用不用 OpenViking：把「检索决策可回放」写进架构的非功能需求。存储和埋点的成本，第一次生产事故排查时就能收回来。</p>
<h2 style="font-weight: 500; color: #191b1f;">经验回写闭环</h2>
<p style="color: #191b1f;" data-pid="uIPUFTYq">多数 Agent 架构是开环的：任务执行完，除了对话历史什么都不留，下次遇到同类任务从零开始。OpenViking 在架构里补了一条回写路径：会话通过 <code>session.commit()</code> 显式提交后，系统异步提取两类内容写入长期记忆——用户偏好，和 Agent 经验，落到对应的 <code>/memory</code> 目录下。</p>
<p style="color: #191b1f;" data-pid="NcKzWSYU">用户偏好各家都在做。Agent 经验这条更值得看：从任务执行结果里提取操作技巧、工具使用经验，供后续同类任务复用。tau2-bench 的数据：经验记忆让任务成功率在 Retail 提升 6.87 个百分点，Airline 提升 11.87 个百分点，对比同一 LLM 无记忆基线。模型没动，纯靠架构里加一条经验沉淀回路，拿到两位数以内的成功率增量。</p>
<p style="color: #191b1f;" data-pid="8zzpDbGT">对比另一条提升路线——攒数据做 SFT 或 RL 微调，周期以周计，成本以万计。经验记忆改的是上下文而非权重，迭代周期是每次会话。两条路线不互斥，但在架构演进的排序上，外置经验回路的边际成本低得多，应该排在微调前面。</p>
<p style="color: #191b1f;" data-pid="IVvbBGO8">两处要留神。一是提取质量：异步抽取本身是 LLM 调用，抽错等于往长期记忆注入脏数据，且脏记忆会在后续任务里持续生效，危害大于一次性的错误回答。二是显式 commit 这个设计——记忆更新由开发者主动触发而非全自动，「哪些会话值得沉淀」的裁量权留在应用层。我们内部一度想做全自动沉淀，现在倾向于保留这个开关，至少在提取质量有验证机制之前。</p>
<h2 style="font-weight: 500; color: #191b1f;">接入成本</h2>
<p style="color: #191b1f;" data-pid="65NYtME-">把这套东西放进现有 Agent 架构的成本，不高。</p>
<p style="color: #191b1f;" data-pid="7MYbVe1l">Python 3.10 以上，<code>pip install openviking --upgrade</code>，<code>openviking-server init</code> 走交互式向导——支持火山引擎、OpenAI、Codex OAuth、Kimi、GLM 和本地 Ollama，选 Ollama 还能按硬件拉合适的模型。<code>openviking-server doctor</code> 启动前体检配置、Python 版本、提供商连通性和磁盘空间。有官方 Docker 镜像和 Helm 部署。</p>
<p style="color: #191b1f;" data-pid="8KfHXdrJ">集成面很宽：Claude Code、Codex、OpenClaw、Hermes、Cursor、Trae、OpenCode、pi、MCP 客户端、LangChain / LangGraph 都有官方接入，集成做的事是把召回注入 Agent 上下文并自动提交会话记忆。如果你的架构本来就走 MCP 或 LangGraph，接入成本主要在配置层。</p>
<p style="color: #191b1f;" data-pid="sC2OiHZG">许可证要过法务。主项目 AGPLv3，<code>crates/ov_cli</code> 和 examples 是 Apache 2.0。AGPLv3 自用没问题，基于它对外提供网络服务会触发传染性条款的开源义务。商业版 OpenViking Service 承诺与开源版共享同一套代码内核，差异在托管运维、基于 VikingDB 的规模（宣称万亿级向量、百亿数据毫秒级检索）、SLA 和企业级安全合规，有至多 50 个文件的免费试用和迁移工具。开源版默认本地存储加单机向量引擎，数据规模上去后的可靠性要自己扛，架构容量规划时要计入。</p>
<p style="color: #191b1f;" data-pid="e6027xiq">背后有论文支撑：VikingMem（arXiv:2605.29640），已被 VLDB 2026 接收，开源版实现了论文描述的部分核心能力。团队在按数据库系统的标准做存储和检索设计，这在 Agent 记忆类项目里少见。</p>
<h2 style="font-weight: 500; color: #191b1f;">需要注意的点</h2>
<p style="color: #191b1f;" data-pid="NtGLKL_E">三点。</p>
<p style="color: #191b1f;" data-pid="XnhJGLus">其一，整个体系的地基是写入时的自动语义处理——摘要、概览、目录归置全靠模型生成，这些产物没有质量下界。LoCoMo 和 tau2-bench 覆盖的场景有限，换到术语密集的企业知识库，L0 摘要的准确率会不会崩，要拿自己的真实数据验证，别信 benchmark 直接上生产。</p>
<p style="color: #191b1f;" data-pid="GQmCvP6C">其二，导航式检索的延迟特性划定了适用边界，架构选型时按流量形态判断，前面说过了。</p>
<p style="color: #191b1f;" data-pid="wNBh-R4r">其三，项目还早，README 自己承认「要做的事还很多」。1813 次 commit、92 个 open issue、320 个 PR，迭代活跃，反面是 API 稳定性存疑，核心链路重度依赖它要做好跟版本的准备。</p>
<p style="color: #191b1f;" data-pid="89X_UDoy">回到 Agent 架构本身。「上下文作为独立子系统」「统一文件存储模型」「按决策阶段分层供给」「检索决策可回放」「经验回写闭环」，这五个设计每一个都能脱离 OpenViking 独立存在。</p>
<p style="color: #191b1f;" data-pid="bVp_k3oJ">以上</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2026/07/agent-openviking/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RAG 的新思路：SAG 和 OpenViking</title>
		<link>https://www.phppan.com/2026/07/rag-sag-openviking/</link>
		<comments>https://www.phppan.com/2026/07/rag-sag-openviking/#comments</comments>
		<pubDate>Sat, 18 Jul 2026 01:23:09 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[架构和远方]]></category>
		<category><![CDATA[OpenViking]]></category>
		<category><![CDATA[RAG]]></category>
		<category><![CDATA[SAG]]></category>

		<guid isPermaLink="false">https://www.phppan.com/?p=2518</guid>
		<description><![CDATA[最近在看 RAG 的两个新思路，其实也不是说特别新，有点新瓶装旧酒的意思。 对于 RAG 的优化，一种线路是继 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p style="color: #191b1f;" data-first-child="" data-pid="1fXSVj0D">最近在看 RAG 的两个新思路，其实也不是说特别新，有点新瓶装旧酒的意思。</p>
<p style="color: #191b1f;" data-pid="RUmjD_UP">对于 RAG 的优化，一种线路是继续优化传统 RAG：切块更细一点，召回器多堆几层，重排再优化，最后把 prompt 拼得更精致。另一条线路是开始换问题定义：如果知识检索本身的建模方式就不对，后面那一长串补丁是不是从第一步就已经输了。</p>
<p style="color: #191b1f;" data-pid="_olrvRH0">SAG 和 OpenViking 属于第二种。</p>
<p style="color: #191b1f;" data-pid="HeY8Xerb">这两个项目看起来也不在一个层面上。SAG 讨论的是检索架构，OpenViking 讨论的是 Agent 的上下文系统。但我看下来，它们都是在解决同一类问题：RAG 之所以越来越重，往往不是因为模型不够强，而是因为我们把「知识」和「上下文」这两个对象建模得太糙。</p>
<p style="color: #191b1f;" data-pid="LjSDkiy4">过去一年，团队在 RAG 上花的钱和精力，主要耗在三个地方：</p>
<ul style="color: #191b1f;">
<li data-pid="Q_FzUCM0">文档切块以后，语义边界被打碎；</li>
<li data-pid="YMGHx5Q9">多跳关联靠 embedding 硬撞，召回经常断链；</li>
<li data-pid="g7T8fwry">想补结构化能力，就往 GraphRAG 走，结果离线构图、实体归一、增量更新把系统拖住。</li>
</ul>
<p style="color: #191b1f;" data-pid="onKtqQkj">这里的问题是这条路线会把系统带向复杂化。</p>
<h2 style="font-weight: 500; color: #191b1f;">SAG</h2>
<p style="color: #191b1f;" data-pid="y1azbgYe">SAG 的核心论文《SAG: SQL-Retrieval Augmented Generation with Query-Time Dynamic Hyperedges》提出了一种非常精妙的架构。它不是传统 RAG 与 GraphRAG 的简单拼接，而是一套用自己的数据模型和执行路径替代二者的原创检索架构。</p>
<p style="color: #191b1f;" data-pid="SVySmZQU">它的核心思想可以总结为八个字：轻量离线，动态建图。</p>
<h3 style="font-weight: 500; color: #191b1f;">1. 数据模型</h3>
<p style="color: #191b1f;" data-pid="_rlXvXFJ">传统 GraphRAG 把文本切碎，试图把所有知识都抽象成 <code>(Subject, Predicate, Object)</code> 的三元组。这种做法丢失了文本原本的上下文语义，导致最后召回出来的都是一些干瘪的关系链，LLM 很难根据这些碎片生成高质量的回答。</p>
<p style="color: #191b1f;" data-pid="Z214xO2o">SAG 重新设计了数据模型：</p>
<ul style="color: #191b1f;">
<li data-pid="_NHVfHuX">Chunk  Event（事件）：一个语义完整的文本块（Chunk）被映射为一个 Event。Event 承载该 Chunk 的完整上下文，它是最终输出和溯源的边界，不再被拆成彼此独立的三元组。</li>
<li data-pid="H7aHZdBM">Chunk  Entities（实体）：从该 Chunk 中抽取多个 Entities。这些实体只负责索引和扩展，不替代事件本身所承载的完整含义。</li>
<li data-pid="xVaNvZ__">Event  Entities：建立事件与实体之间的关联，共同定义了一条潜在的超边（Latent Hyperedge）。</li>
</ul>
<div class="highlight" style="color: #191b1f;">
<pre><code class="language-text">+-------------------------------------------------------------+
|                         Original Chunk                      |
+-------------------------------------------------------------+
                               |
                               v
+-------------------------------------------------------------+
|                         Event (完整语义)                     |
+-------------------------------------------------------------+
            /                  |                  \
           v                   v                   v
+------------------+   +------------------+   +------------------+
|     Entity A     |   |     Entity B     |   |     Entity C     |
+------------------+   +------------------+   +------------------+</code></pre>
</div>
<p style="color: #191b1f;" data-pid="eQlN2Sne">这个设计让事件和实体各司其职。实体只用来做连接的「钩子」，而事件负责保留完整的语义。</p>
<h3 style="font-weight: 500; color: #191b1f;">2. 查询时动态超边</h3>
<p style="color: #191b1f;" data-pid="54N6Zm0s">SAG 不预先构建、也不全局维护任何静态图谱。所有的关系推理，都是在检索发生的那一瞬间，通过关系型数据库的 SQL JOIN 动态计算出来的。</p>
<p style="color: #191b1f;" data-pid="ZTUpxhw-">当一个用户查询（Query）进来时，在线检索流程如下：</p>
<ol style="color: #191b1f;">
<li data-pid="pRr9Aued">种子定位：通过语义（向量）与词法（全文检索）信号，找到与查询最相关的「种子实体」和「种子事件」。</li>
<li data-pid="YnTQrQq0">SQL 动态扩展：利用关系型数据库的 SQL JOIN 查询，沿着这些种子实体，将共享相同实体的事件连接起来。</li>
<li data-pid="yBjXbXdY">局部超边实例化：在查询时，仅针对当前查询所需的局部结构实例化「超边」，不进行任何全局图遍历。</li>
<li data-pid="SWgJFUPa">证据还原：将筛选出的事件映射回原始 Chunk，去重后作为最强证据提供给 LLM 生成带引用的回答。</li>
</ol>
<p style="color: #191b1f;" data-pid="tzLR-tAW">在这个过程中，我们不需要 Neo4j，不需要复杂的图算法，底层的存储与查询完全依赖标准的数据库基础设施（如 SQLite、PostgreSQL、LanceDB 等）。</p>
<p style="color: #191b1f;" data-pid="ifTLLvmO">因为超边是查询时动态计算的，所以当有新文档导入时，不需要重算或重构全局图谱。新 Chunk 只需要并行抽取自身的 Event、Entities 并写入数据库即可。这让系统天然支持了高并发的增量写入。</p>
<p style="color: #191b1f;" data-pid="OlIwqZMy">从跑分数据来看，在相同的 <code>BGE-Large-EN-v1.5</code> Embedding 与 <code>Qwen3.6-Flash</code> LLM 配置下，SAG 在 HotpotQA、2WikiMultiHopQA 和 MuSiQue 的 9 项 Recall@1/2/5 指标中取得了 8 项最佳成绩。其平均 Recall@2/Recall@5 达到了 79.30%/88.18%，而 HippoRAG 2 仅为 68.14%/83.28%。</p>
<h3 style="font-weight: 500; color: #191b1f;">一些问题</h3>
<p style="color: #191b1f;" data-pid="EdHNLWO9">SAG 不是银弹，还存在一些问题。</p>
<p style="color: #191b1f;" data-pid="9C1pCkMN">抽取质量依然依赖 LLM。Event 的切分和 Entity 的抽取用的还是大模型，模型抽错了，后面的动态连接就是在错误的实体上做 JOIN。SAG 降低了实体的语义负担，但没消除抽取本身的不确定性。这块的鲁棒性得拿自己的语料实测。</p>
<p style="color: #191b1f;" data-pid="exFuuSpu">查询时的实体提取是另一个隐患。动态超边的起点是从 Query 里提出核心实体，如果用户的提问很口语、实体表达很模糊，种子定位偏了，后面整条链就歪了。这个环节的召回率我认为是整个系统最脆弱的地方，值得单独压测。</p>
<p style="color: #191b1f;" data-pid="ZpLngGcn">还有并发下的延迟分布。JOIN 在数据量大的时候，SQL 的执行计划、索引命中情况会直接影响尾延迟。其底层继承了数据库的并发能力，在海量数据情况下需要观察其延迟分布。</p>
<h2 style="font-weight: 500; color: #191b1f;">OpenViking</h2>
<p style="color: #191b1f;" data-pid="PtUfIrTD">聊完 SAG，看下 OpenViking。它跟 SAG 不是同一个层面的东西，我把它俩放一篇文章里，是因为它们代表了同一个方向上两种不同深度的探索。</p>
<p style="color: #191b1f;" data-pid="j76welwA">SAG 解决的是「怎么把知识检索得更准」。OpenViking 解决的是「Agent 的上下文该怎么组织」。前者是检索问题，后者是上下文工程问题。</p>
<p style="color: #191b1f;" data-pid="2IRiyc_l">火山引擎把它定位成一款面向 AI Agent 的上下文数据库，基于开源的 OpenViking 内核构建的全托管云服务。核心思想它自己概括成四句：虚拟文件系统、分层上下文、目录递归检索、可观测与自迭代。</p>
<h3 style="font-weight: 500; color: #191b1f;">万物皆文件</h3>
<p style="color: #191b1f;" data-pid="wM7uXlUR">OpenViking 把 Memory、Resource、Skill 三样东西统一抽象成文件，全部映射到 <code>viking://</code> 协议下的虚拟目录，每个条目有唯一的 URI。</p>
<p style="color: #191b1f;" data-pid="gc32jwaL">这个抽象是 Agent 发展到现在的一种沉淀，这里最早是 Manus 在实践的逻辑。Agent 领域现在最乱的就是上下文管理。你有用户的长期记忆、有外部知识资源、有工具和技能定义，这三样东西各自用各自的存储、各自的检索方式，代码里到处是特判。OpenViking 把它们收敛成同一套文件语义之后，Agent 就能用 <code>list</code>、<code>find</code> 这种统一指令去操作所有上下文。</p>
<p style="color: #191b1f;" data-pid="_3LYlKmg">从模糊的语义匹配变成确定性的文件操作，这个转变对调试很有帮助。向量检索是个黑盒，你不知道为什么这次召回了这几条、漏了那几条。文件系统是白盒，路径、目录结构摆在那，Agent 走了哪条路一目了然。</p>
<h3 style="font-weight: 500; color: #191b1f;">分层加载</h3>
<p style="color: #191b1f;" data-pid="sDzTcpAv">OpenViking 在上下文写入的时候，就自动把它处理成三层。</p>
<p style="color: #191b1f;" data-pid="F4c1zBn0">L0 是一句话摘要，用来快速判断。L1 是概述，包含核心信息和使用场景，供 Agent 在规划阶段决策。L2 是完整原始数据，Agent 确有必要时才深入读取。</p>
<p style="color: #191b1f;" data-pid="cjBxcrRk">这个设计针对的是一个很现实的成本问题。把海量上下文一次性塞进提示词，token 烧钱、容易爆窗口、还引入噪声。分层之后，Agent 在规划阶段只看 L0 和 L1 就能做大部分决策，只有真正要用某份资料的时候才去拉 L2。</p>
<p style="color: #191b1f;" data-pid="K3tDsg_L">我算过一笔账。一个复杂的多步 Agent 任务，如果每一步都把候选上下文的全文塞进去，token 消耗是指数级的。分层供给相当于给 Agent 一个「先看目录再翻正文」的能力，规划阶段的 token 成本能压下去一大截。具体压多少取决于你的任务形态，但这个方向省的钱是实打实的。</p>
<h3 style="font-weight: 500; color: #191b1f;">目录递归检索</h3>
<p style="color: #191b1f;" data-pid="WnkGa_L1">OpenViking 的检索不是单次向量召回。流程是这样：先通过意图分析生成多个检索条件，用向量检索快速定位初始切片所在的高分目录，然后在这个目录下做二次检索，把高分结果更新到候选集合；如果目录下还有子目录，就逐层递归重复二次检索；最后拿到最相关的上下文返回。</p>
<p style="color: #191b1f;" data-pid="xIoODZuX">「先锁定高分目录，再精细探索内容」，这套策略把向量检索的语义定位能力和文件系统的层次结构结合起来了。单纯的向量检索找到的是孤立的片段，它不理解片段所在的完整语境。目录递归能顺着文件的组织结构，把一个片段周围的语境一起带出来。</p>
<p style="color: #191b1f;" data-pid="RIxwplIN">这个思路和 SAG 的动态超边其实有相通之处。两者都意识到孤立的语义片段不够用，都想在检索时把「关联」这层信息补回来。SAG 用的是共享实体的 SQL JOIN，OpenViking 用的是目录层级的递归遍历。一个走关系代数，一个走树形结构。解决的底层痛点是同一个。</p>
<h3 style="font-weight: 500; color: #191b1f;">可观测与自迭代</h3>
<p style="color: #191b1f;" data-pid="WRaFPZaF">OpenViking 的检索过程，每次的目录浏览、文件定位轨迹都被完整留存，能看清问题根源、指导检索逻辑优化。</p>
<p style="color: #191b1f;" data-pid="ihfugwnx">对做过 RAG 调优的人来说，这个能力的分量不用多解释。传统向量检索出了问题，你几乎无从下手，只能瞎调 embedding、瞎调 chunk size。有了完整的检索轨迹，你能精确复盘 Agent 每一次信息获取走了哪条路径，哪一步偏了。</p>
<p style="color: #191b1f;" data-pid="j5hK7ZY_">自迭代那部分是通过 <code>session.commit()</code> 主动触发的。会话结束时，系统异步分析任务执行结果和用户反馈，自动更新到 User 和 Agent 的 <code>/memory</code> 目录下。它既更新用户偏好，也从任务执行经验里提炼操作技巧和工具使用经验。</p>
<p style="color: #191b1f;" data-pid="IedPQcM9">这个闭环我持谨慎乐观。自动提炼记忆听着很美，但提炼的质量、更新的边界、错误记忆的污染问题，都是需要长期跑才能暴露的。我不会一上来就把它当成生产依赖，会先在低风险场景里观察它更新出来的记忆到底靠不靠谱。</p>
<h2 style="font-weight: 500; color: #191b1f;">SAG 和 OpenViking</h2>
<p style="color: #191b1f;" data-pid="67yBB8an">写到这，我把 SAG 和 OpenViking 放到一起，讲讲我看到的相同点。</p>
<p style="color: #191b1f;" data-pid="pbu5OKNS">传统 RAG 的世界观是扁平的。所有知识被切成等长的 Chunk，拍平进一个向量空间，检索就是在这个空间里找最近邻。这套世界观简单、好扩展，但它主动丢弃了知识之间的结构信息。Chunk 和 Chunk 之间是什么关系，谁包含谁，谁引用谁，谁是谁的上下文，全都被拍平的过程碾掉了。</p>
<p style="color: #191b1f;" data-pid="S-ZRS-D0">SAG 和 OpenViking 从两个不同的方向，试图把这层被碾掉的结构信息找回来。</p>
<p style="color: #191b1f;" data-pid="qXo03YTa">SAG 找回的是「实体关联」这层结构。它承认知识点之间存在通过共享实体建立的隐式关联，并且用查询时的 SQL JOIN 把这层关联即时重建出来。它的贡献在于证明了这层结构不需要离线物化成一张昂贵的全局图，用关系型数据库现成的关联能力就能在查询时高效算出来。</p>
<p style="color: #191b1f;" data-pid="JiaAO3JE">OpenViking 找回的是「层次组织」这层结构。它承认知识天然有目录、有层级、有从属关系，并且用虚拟文件系统把这层组织显式地保留下来，检索的时候顺着这个层级递归下去。它的贡献在于把 Agent 的上下文从一堆散落的切片，重新组织成了一个可导航、可追溯的结构。</p>
<p style="color: #191b1f;" data-pid="HKLRQQ1F">两者都在做同一件事：扁平化的向量检索丢失了太多结构，而这些结构恰恰是复杂查询和长程任务真正需要的东西。它们的分歧只在于用什么载体去承载这层结构。SAG 选了关系表和 SQL，OpenViking 选了文件系统和目录树。</p>
<h2 style="font-weight: 500; color: #191b1f;">怎么选</h2>
<p style="color: #191b1f;" data-pid="NZfpFAuE">落到实际决策，可以分两个场景。</p>
<p style="color: #191b1f;" data-pid="cch9De1d">如果核心诉求是知识库的多跳检索精度，语料相对静态、增量频繁、又要给用户看得见的原文引用，建议评估 SAG。它的动态超边在多跳上的数据摆在那，增量友好和溯源能力恰好解决了之前方案的问题。部署门槛低，本地就能验，评估成本几乎为零。</p>
<p style="color: #191b1f;" data-pid="JVXLBY-2">如果做的是 Agent 产品，痛点在长程任务的上下文管理、记忆沉淀、多 Agent 协作，建议去评估 OpenViking。它解决的是比检索更上一层的问题，文件系统抽象和分层加载对控制 Agent 的 token 成本、提升可调试性比较有用。</p>
<p style="color: #191b1f;" data-pid="qmo6Q85T">这两个东西不冲突。理论上一个成熟的 Agent 系统，底层完全可以用 SAG 这类引擎做精准的知识检索，上层用 OpenViking 这类框架做上下文的组织和调度。一个管「检索得准」，一个管「组织得清」，各司其职。</p>
<p style="color: #191b1f;" data-pid="m6gM23j_">检索这条路走到今天，值得关注的方向已经从「怎么把向量算得更快」转到了「怎么把结构找回来」。SAG 和 OpenViking 是这个转向上两个具体的答案，一个在检索层，一个在上下文层。</p>
<p style="color: #191b1f;" data-pid="aKBEeaKX">以上。</p>
<div id="gtx-trans" style="position: absolute; left: 436px; top: 223px;"></div>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2026/07/rag-sag-openviking/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
