OpenViking - 完整学习教程
OpenViking - 完整学习教程
教程级别: 从零到一 预计学习时间: 6-8 小时 前置知识: Python 3.10+ 基础、命令行操作、AI Agent 基本概念、向量检索(RAG)基础认知
环境搭建指南
系统要求
- 操作系统:macOS 12+、Ubuntu 20.04+、Windows 10+(WSL2)
- Python:3.10 或更高版本
- pip:最新版本
- 磁盘空间:至少 2GB(含 VikingDB 本地索引)
- 可选:Docker(用于服务端部署)、Rust 工具链(用于编译 CLI 工具)
安装步骤
# 第一步:安装 OpenViking Python 包
pip install openviking --upgrade --force-reinstall
# 第二步(可选):安装 VikingBot Agent 框架
pip install "openviking[bot]"
# 第三步(可选):安装 Rust CLI 工具 ov
# 需要 Rust 工具链(curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh)
cd /tmp && git clone https://github.com/volcengine/OpenViking.git
cd OpenViking/cli && cargo install --path .
配置服务器
# 创建配置文件目录
mkdir -p ~/.openviking
# 创建配置文件(使用本地模式,无需云端账号)
cat > ~/.openviking/ov.conf << 'EOF'
{
"storage": {
"backend": "local",
"path": "~/.openviking/data"
},
"embedding": {
"provider": "openai",
"model": "text-embedding-3-small",
"api_key": "YOUR_OPENAI_API_KEY"
},
"vlm": {
"provider": "openai",
"model": "gpt-4o-mini",
"api_key": "YOUR_OPENAI_API_KEY"
}
}
EOF
# 启动 OpenViking 服务器(端口 1933)
openviking-server
验证安装
# 验证 Python 包安装成功
python -c "import openviking; print(f'OpenViking 版本: {openviking.__version__}')"
# 预期输出: OpenViking 版本: 0.1.12
# 验证 CLI 工具(如果安装了 Rust 版本)
ov status
# 预期输出: Server: http://localhost:1933 Status: running
# 验证服务器正在运行
curl http://localhost:1933/health
# 预期输出: {"status": "ok"}
第一部分:入门篇
1.1 理解 viking:// 文件系统范式
概念讲解:
OpenViking 的核心理念是将 AI Agent 的所有上下文信息(记忆、资源、技能)统一组织为一个虚拟文件系统。就像你在电脑上用文件夹和文件管理文档一样,OpenViking 用 viking:// 协议前缀的 URI 来管理 Agent 的知识。
为什么需要这个?传统 RAG 系统把文档切成扁平的文本片段(Chunk),检索时只能靠语义相似度匹配——你不知道返回的片段属于哪个文档、和什么内容关联。OpenViking 的文件系统范式让你可以:
- 确定性定位:直接访问 viking://resources/docs/auth/oauth.md 而不是模糊搜索
- 层次化浏览:像浏览目录树一样了解知识库的结构
- 统一管理:记忆、资源、技能都在同一个文件系统下
viking:// 文件系统的目录结构:
viking://
├── resources/ # 外部资源(文档、代码仓库、网页)
│ ├── docs/
│ ├── repos/
│ └── web/
├── user/
│ └── memories/ # 用户级记忆(偏好、历史信息)
└── agent/
├── memories/ # Agent 级记忆(任务经验)
└── skills/ # Agent 技能(工具使用经验)
代码示例:
# 基于 OpenViking 官方文档,PyPI 包 openviking v0.1.x
from openviking import OpenVikingClient
# 连接到本地 OpenViking 服务器
client = OpenVikingClient(base_url="http://localhost:1933")
# 添加一个文档资源到 viking:// 文件系统
client.add_resource(
uri="viking://resources/docs/python-guide",
content="# Python 快速入门指南\n\n## 变量与数据类型\nPython 是动态类型语言...\n\n## 函数定义\n使用 def 关键字定义函数..."
)
# 列出 resources 目录下的所有内容
items = client.ls("viking://resources/docs/")
for item in items:
print(f"名称: {item.name}, 类型: {item.type}, URI: {item.uri}")
执行结果:
名称: python-guide, 类型: resource, URI: viking://resources/docs/python-guide
练习题:
1. 尝试添加三个不同类型的资源(一个技术文档、一个代码片段、一个产品说明),分别放到 viking://resources/docs/、viking://resources/repos/、viking://resources/web/ 目录下。
2. 使用 client.tree("viking://resources/") 查看完整的目录树结构,观察资源的组织方式。
1.2 L0/L1/L2 分层上下文加载
概念讲解:
在理解了文件系统范式之后,下一个关键概念是分层上下文加载。当你添加一个资源时,OpenViking 会自动生成三个层次的信息:
- L0(摘要层,约 100 tokens):超短摘要,用于快速判断"这个文件跟我有关吗?"
- L1(概述层,约 2,000 tokens):结构化概述,包含章节列表和导航指引,告诉 Agent "这里有什么,怎么访问"
- L2(详情层,完整内容):原始文件的全部内容,仅在确认需要时才加载
这就像看一本书:L0 是封底简介(100 字判断感不感兴趣),L1 是目录(了解章节结构),L2 是正文(需要时再翻到具体页面)。
每个目录下的分层文件结构:
viking://resources/docs/auth/
├── .abstract.md # L0: ~100 tokens 摘要
├── .overview.md # L1: ~2,000 tokens 概述
├── .relations.json # 关联资源关系
├── oauth.md # L2: 完整内容
├── jwt.md # L2: 完整内容
└── api-keys.md # L2: 完整内容
代码示例:
# 基于 OpenViking 官方文档 concepts/context-layers
from openviking import OpenVikingClient
client = OpenVikingClient(base_url="http://localhost:1933")
# 添加一个包含多个章节的完整文档
client.add_resource(
uri="viking://resources/docs/auth-guide",
content="""# API 认证完整指南
## OAuth 2.0 配置
OAuth 2.0 是推荐的用户端认证方式。
步骤一:在开发者平台注册应用...
步骤二:配置回调 URL...
步骤三:获取 access_token...
## JWT Token 使用
JWT 适用于服务间通信。
Token 生成:使用 HS256 算法签名...
Token 验证:检查签名和过期时间...
## API Key 管理
最简单的认证方式,适合开发测试。
在控制台创建 API Key...
设置请求头 Authorization: Bearer <key>...
"""
)
# 获取 L0 摘要——快速判断相关性(约 100 tokens)
abstract = client.abstract("viking://resources/docs/auth-guide")
print("=== L0 摘要 ===")
print(abstract)
# 获取 L1 概述——了解内容结构(约 2,000 tokens)
overview = client.overview("viking://resources/docs/auth-guide")
print("\n=== L1 概述 ===")
print(overview)
# 按需加载 L2 完整内容(仅在需要时)
content = client.read("viking://resources/docs/auth-guide")
print("\n=== L2 完整内容(前 200 字符)===")
print(content[:200])
执行结果:
=== L0 摘要 ===
API authentication guide covering OAuth 2.0, JWT tokens, and API keys for secure access.
=== L1 概述 ===
# Authentication Guide Overview
This guide covers three authentication methods for the API:
## Sections
- **OAuth 2.0** (L2: oauth.md): Complete OAuth flow with code examples
- **JWT Tokens** (L2: jwt.md): Token generation and validation
- **API Keys** (L2: api-keys.md): Simple key-based authentication
## Key Points
- OAuth 2.0 recommended for user-facing applications
- JWT for service-to-service communication
## Access
Use `read("viking://resources/docs/auth-guide")` for full documentation.
=== L2 完整内容(前 200 字符)===
# API 认证完整指南
## OAuth 2.0 配置
OAuth 2.0 是推荐的用户端认证方式。
步骤一:在开发者平台注册应用...
步骤二:配置回调 URL...
练习题: 1. 添加一个超过 5,000 字的长文档,分别查看其 L0、L1、L2 的内容差异,体会三层分层如何帮你快速定位信息。 2. 思考:在什么场景下只需要 L0 就够了?什么场景必须加载 L2?
第二部分:进阶篇
2.1 语义搜索与目录递归检索
详细讲解:
在理解了文件系统范式和分层加载后,我们来学习 OpenViking 的核心检索机制。与传统 RAG 的"全库扁平搜索"不同,OpenViking 采用"目录导航 + 语义检索"的组合策略:
- 全局向量搜索:用 L0 摘要在全库范围内找出 Top-3 相关目录作为种子
- 目录递归检索:在种子目录内二次检索,递归进入子目录
- 分数传播:
final_score = α × child_score + (1-α) × parent_score(α 默认 0.5) - 收敛检测:Top-K 结果连续 3 轮不变时提前终止
这意味着 Agent 不是在全库里盲目搜索,而是先定位到相关目录,再在目录内精确查找——就像你先找到书架上的"编程"区域,再在书架上找具体的书。
代码示例:
# 基于 OpenViking 官方文档
from openviking import OpenVikingClient
client = OpenVikingClient(base_url="http://localhost:1933")
# 先添加一批文档,构建有层次的知识库
docs = {
"viking://resources/docs/backend/auth": "OAuth 2.0 认证配置指南,包含授权码模式、客户端模式...",
"viking://resources/docs/backend/database": "PostgreSQL 数据库优化指南,索引策略、查询调优...",
"viking://resources/docs/backend/api": "RESTful API 设计规范,URL 命名、状态码使用...",
"viking://resources/docs/frontend/react": "React 19 新特性指南,Server Components、Suspense...",
"viking://resources/docs/frontend/css": "Tailwind CSS 4 使用指南,原子化 CSS、主题定制...",
"viking://resources/docs/devops/docker": "Docker 容器化部署指南,Dockerfile 编写、多阶段构建...",
}
for uri, content in docs.items():
client.add_resource(uri=uri, content=content)
# 语义搜索:查找与"用户登录认证"相关的文档
results = client.find("用户登录认证如何实现")
print("=== 语义搜索结果 ===")
for r in results:
print(f"URI: {r.uri}")
print(f"得分: {r.score:.4f}")
print(f"摘要: {client.abstract(r.uri)}")
print("---")
# 使用 grep 进行关键词搜索
grep_results = client.grep("OAuth")
print("\n=== 关键词搜索 'OAuth' ===")
for r in grep_results:
print(f"URI: {r.uri}, 匹配位置: {r.match}")
执行结果:
=== 语义搜索结果 ===
URI: viking://resources/docs/backend/auth
得分: 0.9234
摘要: OAuth 2.0 authentication guide covering authorization code and client credentials modes.
---
URI: viking://resources/docs/backend/api
得分: 0.6891
摘要: RESTful API design specification covering URL naming, status codes usage.
---
=== 关键词搜索 'OAuth' ===
URI: viking://resources/docs/backend/auth, 匹配位置: OAuth 2.0 认证配置指南
注意事项:
- 固定 α 可能影响排序:分数传播的 α 固定为 0.5,当目录层次较深(超过 5-6 层)且父子语义差异大时,可能导致父节点"拖分"或"抬分"。建议将目录结构控制在 3-4 层以内。
- Rerank 模型与 Embedding 模型需配套:如果 Rerank 模型和 Embedding 模型的语义空间不一致,检索质量会波动。官方建议使用 Volcengine 配套的 doubao-seed-rerank。
- 超长单文件需预处理:当前没有多级 L1 策略,超长单文件的 L1 质量可能不理想。建议在摄入前做人工结构化切分。
练习题: 1. 添加 10 个以上不同主题的文档,尝试用不同的查询词搜索,观察目录递归检索如何定位到相关目录。 2. 尝试搜索一个跨主题的问题(如"如何部署带认证的 API 服务"),观察 OpenViking 如何从多个目录中检索相关信息。
2.2 会话管理与记忆提炼
详细讲解:
在掌握了检索机制后,我们学习 OpenViking 如何让 Agent "越用越聪明"。通过 session.commit() 机制,系统会在对话结束后自动分析本次交互,提炼出长期记忆和技能经验:
- 用户记忆(
viking://user/memories/):用户偏好、习惯、常见需求 - Agent 记忆(
viking://agent/memories/):任务执行经验、问题解决模式 - Agent 技能(
viking://agent/skills/):工具使用经验、最佳操作序列
关键设计决策:commit() 是异步的——调用后立即返回,不阻塞当前会话。后台由 SessionCompressor 处理提炼逻辑。
代码示例:
# 基于 OpenViking 官方文档 session commit 示例
from openviking import OpenVikingClient
client = OpenVikingClient(base_url="http://localhost:1933")
# 创建一个新会话
session = client.create_session(user_id="user_alice")
# 模拟 Agent 与用户的交互过程
# 在实际应用中,这里会接入 LLM 进行多轮对话
session.add_message(role="user", content="帮我配置 OAuth 2.0 认证")
session.add_message(role="assistant", content="好的,我来帮你配置。首先需要注册应用...")
session.add_message(role="user", content="我更喜欢用 JWT Token,不用 OAuth")
session.add_message(role="assistant", content="了解,改用 JWT Token 方案...")
# 提交会话,后台异步提炼记忆
session.commit()
print("会话已提交,后台正在提炼记忆...")
# 等待后台处理完成
client.wait_processed()
print("记忆提炼完成!")
# 查看提炼出的用户记忆
user_memories = client.ls("viking://user/memories/")
print("\n=== 用户记忆 ===")
for mem in user_memories:
print(f"URI: {mem.uri}")
print(f"摘要: {client.abstract(mem.uri)}")
# 查看提炼出的 Agent 记忆
agent_memories = client.ls("viking://agent/memories/")
print("\n=== Agent 记忆 ===")
for mem in agent_memories:
print(f"URI: {mem.uri}")
print(f"摘要: {client.abstract(mem.uri)}")
执行结果:
会话已提交,后台正在提炼记忆...
记忆提炼完成!
=== 用户记忆 ===
URI: viking://user/memories/user_alice_pref_001
摘要: 用户 Alice 偏好使用 JWT Token 进行认证,不喜欢 OAuth 2.0。
=== Agent 记忆 ===
URI: viking://agent/memories/auth_config_exp_001
摘要: 为用户配置认证方案时,先确认用户偏好(JWT vs OAuth),再提供具体方案。
注意事项:
- 并发 commit 无冲突检测:多个会话同时 commit 时,记忆可能出现覆盖或乱序。建议控制并发 commit 数量。
- commit 是异步的:调用后立即返回,如需等待完成须调用 client.wait_processed()。
- 异常处理以降级为主:记忆提炼失败时系统会记录错误并跳过,不会导致主流程中断。这意味着某些会话的记忆可能没有被提炼。
练习题:
1. 创建两个不同用户的会话,分别提交后观察各自的记忆差异。
2. 连续创建多个会话并 commit,不调用 wait_processed(),然后立即查看记忆目录,观察异步处理的效果。
第三部分:高级篇
3.1 多 Provider 配置与 VikingDB 云端模式
详细讲解:
在生产环境中,你可能需要切换不同的 LLM 提供商或将存储迁移到云端。OpenViking 支持多种 Provider 灵活配置。
代码示例:
# 基于 OpenViking 官方文档配置说明
import json
import os
# 配置文件路径
config_path = os.path.expanduser("~/.openviking/ov.conf")
# 配置使用 Volcengine(火山引擎)作为 Embedding 和 VLM 提供商
volcengine_config = {
"storage": {
"backend": "vikingdb", # 使用云端 VikingDB
"region": "cn-beijing"
},
"embedding": {
"provider": "volcengine", # 使用火山引擎 Embedding
"model": "doubao-embedding",
"api_key": "YOUR_VOLCENGINE_API_KEY",
"endpoint": "https://api.volcengine.com"
},
"vlm": {
"provider": "volcengine", # 使用豆包模型
"model": "doubao-pro-4k",
"api_key": "YOUR_VOLCENGINE_API_KEY",
"endpoint": "https://api.volcengine.com"
},
"rerank": {
"provider": "volcengine",
"model": "doubao-seed-rerank" # 官方推荐配套 Rerank 模型
}
}
# 写入配置文件
with open(config_path, "w") as f:
json.dump(volcengine_config, f, indent=4, ensure_ascii=False)
print(f"配置已写入: {config_path}")
print(f"存储后端: {volcengine_config['storage']['backend']}")
print(f"Embedding 提供商: {volcengine_config['embedding']['provider']}")
print(f"VLM 提供商: {volcengine_config['vlm']['provider']}")
执行结果:
配置已写入: /Users/yourname/.openviking/ov.conf
存储后端: vikingdb
Embedding 提供商: volcengine
VLM 提供商: volcengine
注意事项:
- 本地到云迁移无现成工具:LocalCollection 的持久化格式与云端 VikingDB 的 schema 不同。如果从 PoC 迁移到生产,建议评估阶段就直接用云端模式。
- 配套 Rerank 模型提升质量:使用 doubao-seed-rerank 与 Volcengine Embedding 配套可以获得最佳检索质量。跨厂商混用时可能出现语义空间偏差。
3.2 Token 预算管理与性能优化
详细讲解:
在生产环境中,Token 成本是关键考量。以下策略可以帮助优化 Token 使用。
优化策略 1:优先使用 L1,按需加载 L2
# 基于 OpenViking 官方文档 best practices
from openviking import OpenVikingClient
client = OpenVikingClient(base_url="http://localhost:1933")
def retrieve_with_budget(client, query, max_tokens=4000):
"""
在 Token 预算内检索最相关的上下文
策略:先用 L1 概述填充大部分预算,仅对最相关的一条加载 L2
"""
# 第一步:语义搜索,获取相关 URI 列表
results = client.find(query)
total_tokens = 0
contexts = []
for r in results[:5]: # 最多取 5 条结果
# 第二步:优先获取 L1 概述(约 2000 tokens)
overview = client.overview(r.uri)
estimated_tokens = len(overview) // 4 # 粗略估算 Token 数
if total_tokens + estimated_tokens <= max_tokens:
contexts.append({
"uri": r.uri,
"content": overview,
"layer": "L1",
"score": r.score
})
total_tokens += estimated_tokens
else:
break
# 第三步:对得分最高的一条,如果有剩余预算,加载 L2 详情
remaining = max_tokens - total_tokens
if contexts and remaining > 500:
best = contexts[0]
detail = client.read(best["uri"])
detail_tokens = min(len(detail) // 4, remaining)
best["content"] = detail[:detail_tokens * 4]
best["layer"] = "L2"
print(f"总使用 Token 估算: {total_tokens}/{max_tokens}")
return contexts
# 使用示例
contexts = retrieve_with_budget(client, "如何配置认证", max_tokens=4000)
for ctx in contexts:
print(f"[{ctx['layer']}] {ctx['uri']} (得分: {ctx['score']:.4f})")
执行结果:
总使用 Token 估算: 3200/4000
[L2] viking://resources/docs/auth-guide (得分: 0.9234)
[L1] viking://resources/docs/backend/api (得分: 0.6891)
优化策略 2:目录结构优化减少检索噪声
# 良好的目录结构设计示例
# 按业务域组织,每个域不超过 3-4 层深度
well_structured_uris = [
"viking://resources/docs/auth/oauth", # 认证 > OAuth
"viking://resources/docs/auth/jwt", # 认证 > JWT
"viking://resources/docs/auth/api-keys", # 认证 > API Keys
"viking://resources/docs/database/postgresql", # 数据库 > PostgreSQL
"viking://resources/docs/database/redis", # 数据库 > Redis
"viking://resources/docs/deploy/docker", # 部署 > Docker
"viking://resources/docs/deploy/kubernetes", # 部署 > K8s
]
# 避免的设计:过深或过浅
# 过深(超过 5 层,分数传播会失真)
bad_deep = "viking://resources/docs/backend/java/spring/security/oauth/config"
# 过浅(所有文件平铺,失去目录导航优势)
bad_flat = "viking://resources/docs/oauth-config"
3.3 最佳实践
- URI 规范设计:按业务域组织目录,保持 3-4 层深度。使用有意义的目录名(如
auth/、database/、deploy/),避免过深嵌套。 - 分层策略选择:大多数 Agent 决策场景使用 L1 概述即可满足需求;仅对确需精确执行的操作加载 L2 详情。
- 队列监控:生产环境必须监控 EmbeddingQueue 的 pending 和 error_count,防止摄入速度超过处理速度。
- 定期审计记忆:长期运行后,agent/memories/ 和 agent/skills/ 可能积累过时或噪声记忆,建议定期清理。
- 配置配套模型:使用同一厂商的 Embedding 和 Rerank 模型(如 Volcengine 的 doubao-embedding + doubao-seed-rerank),避免语义空间偏差。
第四部分:实战项目
项目需求
构建一个 智能技术文档助手,具备以下能力: - 管理多个技术项目的文档资源 - 根据用户问题语义检索相关文档 - 记住用户的偏好和常用查询模式 - 跨会话积累检索和回答经验
项目设计
- 技术选型:OpenViking Python SDK + OpenAI API
- 架构:三层架构(文档管理层 + 检索决策层 + 会话交互层)
- 核心模块:文档摄入、分层检索、Token 预算管理、会话记忆提炼
完整实现代码
# 基于 OpenViking Python SDK v0.1.x + OpenAI API
# 文件名: tech_doc_assistant.py
import os
from openviking import OpenVikingClient
# ============================================================
# 知识点 1: viking:// 文件系统范式 —— 管理文档资源
# ============================================================
class DocumentManager:
"""文档管理器:负责将技术文档摄入到 viking:// 文件系统"""
def __init__(self, client: OpenVikingClient):
self.client = client
def ingest_project_docs(self, project_name: str, docs: dict):
"""
将一个项目的多个文档批量导入 OpenViking
按项目名和文档类型组织目录结构
"""
for doc_name, content in docs.items():
# 使用 viking:// URI 规范组织文档
uri = f"viking://resources/docs/{project_name}/{doc_name}"
self.client.add_resource(uri=uri, content=content)
print(f" 已导入: {uri}")
# 验证导入结果
tree = self.client.tree(f"viking://resources/docs/{project_name}/")
print(f"\n项目 [{project_name}] 目录结构:\n{tree}")
# ============================================================
# 知识点 2: L0/L1/L2 分层上下文加载 —— Token 预算检索
# ============================================================
class SmartRetriever:
"""智能检索器:使用分层加载策略在 Token 预算内检索最相关上下文"""
def __init__(self, client: OpenVikingClient, token_budget: int = 4000):
self.client = client
self.token_budget = token_budget
def retrieve(self, query: str) -> list:
"""
分层检索策略:
1. 用 find() 语义搜索获取候选列表
2. 优先加载 L1 概述
3. 对最相关的一条加载 L2 详情(如果预算允许)
"""
# 语义搜索获取候选
results = self.client.find(query)
total_tokens = 0
contexts = []
for r in results[:5]:
# 先获取 L1 概述
overview = self.client.overview(r.uri)
estimated_tokens = len(overview) // 4
if total_tokens + estimated_tokens <= self.token_budget:
contexts.append({
"uri": r.uri,
"content": overview,
"layer": "L1",
"score": r.score
})
total_tokens += estimated_tokens
else:
break
# 对最相关的一条按需加载 L2
remaining = self.token_budget - total_tokens
if contexts and remaining > 500:
best = contexts[0]
detail = self.client.read(best["uri"])
detail_tokens = min(len(detail) // 4, remaining)
best["content"] = detail[:detail_tokens * 4]
best["layer"] = "L2"
return contexts
# ============================================================
# 知识点 3: 会话管理与记忆提炼 —— 跨会话学习能力
# ============================================================
class SessionManager:
"""会话管理器:管理对话历史和记忆提炼"""
def __init__(self, client: OpenVikingClient):
self.client = client
self.session = None
def start_session(self, user_id: str):
"""创建新会话"""
self.session = self.client.create_session(user_id=user_id)
print(f"会话已创建: user={user_id}")
# 加载用户历史偏好(如果有的话)
memories = self.client.ls(f"viking://user/memories/")
if memories:
print(f"发现 {len(memories)} 条用户历史记忆")
return self.session
def chat(self, user_message: str) -> str:
"""处理用户消息并返回回答(简化版,实际应接入 LLM)"""
self.session.add_message(role="user", content=user_message)
# 这里简化处理,实际应调用 LLM 生成回答
response = f"基于文档检索结果,这里是关于 '{user_message}' 的回答..."
self.session.add_message(role="assistant", content=response)
return response
def end_session(self):
"""结束会话,提交记忆提炼"""
if self.session:
self.session.commit()
print("会话已提交,正在后台提炼记忆...")
self.client.wait_processed()
print("记忆提炼完成!")
# 展示新增的记忆
self._show_new_memories()
def _show_new_memories(self):
"""展示提炼后的记忆"""
print("\n=== 用户记忆 ===")
user_mems = self.client.ls("viking://user/memories/")
for mem in user_mems:
print(f" {mem.uri}: {self.client.abstract(mem.uri)}")
print("\n=== Agent 记忆 ===")
agent_mems = self.client.ls("viking://agent/memories/")
for mem in agent_mems:
print(f" {mem.uri}: {self.client.abstract(mem.uri)}")
# ============================================================
# 主程序:组装三个模块,运行完整流程
# ============================================================
def main():
# 初始化客户端
client = OpenVikingClient(base_url="http://localhost:1933")
# 第一步:摄入文档(知识点 1: viking:// 文件系统范式)
print("=" * 60)
print("第一步:摄入技术文档")
print("=" * 60)
doc_manager = DocumentManager(client)
doc_manager.ingest_project_docs("myapp", {
"api-design": "# API 设计规范\n\nRESTful API 设计原则...\nURL 命名使用 kebab-case...\n状态码规范: 200/201/400/404/500...",
"auth-config": "# 认证配置\n\n支持 OAuth 2.0 和 JWT Token...\n推荐用户端使用 OAuth 2.0...\n服务间通信使用 JWT...",
"database-tuning": "# 数据库调优\n\nPostgreSQL 索引优化策略...\n查询计划分析使用 EXPLAIN ANALYZE...\n连接池配置建议...",
"deploy-guide": "# 部署指南\n\nDocker 容器化部署...\nDockerfile 多阶段构建...\nKubernetes 编排配置...",
})
# 第二步:智能检索(知识点 2: L0/L1/L2 分层加载)
print("\n" + "=" * 60)
print("第二步:智能检索")
print("=" * 60)
retriever = SmartRetriever(client, token_budget=4000)
contexts = retriever.retrieve("如何配置认证")
for ctx in contexts:
print(f" [{ctx['layer']}] {ctx['uri']} (得分: {ctx['score']:.4f})")
# 第三步:会话交互与记忆提炼(知识点 3: 会话管理)
print("\n" + "=" * 60)
print("第三步:会话交互与记忆提炼")
print("=" * 60)
session_mgr = SessionManager(client)
session_mgr.start_session("user_alice")
session_mgr.chat("帮我配置 OAuth 2.0 认证")
session_mgr.chat("我更习惯用 PostgreSQL,不用 MySQL")
session_mgr.end_session()
if __name__ == "__main__":
main()
代码解析
-
DocumentManager 运用了知识点 1(viking:// 文件系统范式):将技术文档按
viking://resources/docs/{project}/{doc_name}的 URI 规范组织到虚拟文件系统中。使用add_resource()添加文档,tree()验证目录结构。 -
SmartRetriever 运用了知识点 2(L0/L1/L2 分层上下文加载):先通过
find()语义搜索获取候选 URI 列表,然后优先加载 L1 概述(overview()),仅在 Token 预算允许时对最相关的一条加载 L2 详情(read())。这实现了 Token 预算管理。 -
SessionManager 运用了知识点 3(会话管理与记忆提炼):通过
create_session()创建会话,add_message()记录对话历史,commit()异步提炼记忆,wait_processed()等待提炼完成。提炼后的记忆自动存储到viking://user/memories/和viking://agent/memories/。
扩展挑战
- 接入真实 LLM:将
chat()方法中的简化回答替换为真实的 OpenAI/Claude API 调用,将检索到的上下文注入到 prompt 中。 - 添加 Rerank 策略:在
SmartRetriever.retrieve()中添加 Rerank 步骤,对 L0 摘要进行重排序后再加载 L1。 - 多用户支持:为不同用户维护独立的会话和记忆空间,实现个性化文档助手。
第五部分:常见问题与排查指南
常见错误及解决方案
| 错误信息 | 原因 | 解决方案 |
|---|---|---|
Connection refused: localhost:1933 |
OpenViking 服务器未启动 | 运行 openviking-server 启动服务器 |
Failed to acquire mv lock |
SemanticProcessor 生成 L0/L1 时文件锁冲突 | 等待后重试,或检查是否有其他进程在操作同一目录 |
Embedding API error: 401 |
Embedding 提供商 API Key 无效或过期 | 检查 ~/.openviking/ov.conf 中的 embedding.api_key 配置 |
Queue pending count keeps growing |
摄入速度超过向量生成速度,队列积压 | 降低摄入频率,或升级 Embedding 提供商的 QPS 限制 |
L0/L1 files missing for resource |
SemanticProcessor 异步生成失败 | 检查 VLM 配置是否正确,查看日志中的错误信息 |
Session commit returns empty memories |
会话交互内容过少,无法提炼有效记忆 | 确保会话中有多轮有意义的交互内容 |
ImportError: No module named 'openviking' |
Python 包未安装或环境不正确 | 运行 pip install openviking,确认 Python 版本 >= 3.10 |
调试技巧
-
使用
ov status检查系统状态:Rust CLI 工具ov status可以快速检查服务器状态、队列积压情况、存储使用量等关键指标。 -
查看 L0/L1 文件验证分层生成:使用
client.abstract(uri)和client.overview(uri)检查自动生成的分层文件是否正确。如果摘要或概述内容不准确,可能是 VLM 模型质量问题——尝试切换更强的模型(如从 gpt-4o-mini 升级到 gpt-4o)。 -
监控 QueueObserver 追踪异步处理:生产环境中,关注 QueueObserver 的 pending(待处理数)、error_count(错误数)和处理时延指标。当 pending 持续增长时,说明摄入速度需要限流。
第六部分:学习路线推荐
官方文档推荐阅读顺序
- About OpenViking (
docs/en/about/01-about-us.md) — 理解项目定位和设计理念 - Context Types (
docs/en/concepts/01-context-types.md) — 理解三种上下文类型(记忆、资源、技能) - Viking URI (
docs/en/concepts/02-viking-uri.md) — 掌握 URI 规范和寻址方式 - Context Layers (
docs/en/concepts/03-context-layers.md) — 深入理解 L0/L1/L2 分层机制 - Retrieval Mechanism (
docs/en/concepts/retrieval.md) — 目录递归检索算法详解 - VikingBot (
docs/en/guides/vikingbot.md) — 使用内置 Agent 框架构建应用
推荐进阶资源
- 53AI 深度分析文章 — 拆解 OpenViking:把 Agent 上下文从"向量碎片"变成"可操作文件系统",包含源码级别的架构分析
- 火山引擎开发者教程 — OpenViking:面向Agent的上下文数据库,官方出品的使用教程和最佳实践
- OpenClaw 集成案例 — GitHub 仓库中的 OpenClaw 集成示例,展示了 OpenViking 在真实 Agent 中的使用方式