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 采用"目录导航 + 语义检索"的组合策略:

  1. 全局向量搜索:用 L0 摘要在全库范围内找出 Top-3 相关目录作为种子
  2. 目录递归检索:在种子目录内二次检索,递归进入子目录
  3. 分数传播final_score = α × child_score + (1-α) × parent_score(α 默认 0.5)
  4. 收敛检测: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 最佳实践

  1. URI 规范设计:按业务域组织目录,保持 3-4 层深度。使用有意义的目录名(如 auth/database/deploy/),避免过深嵌套。
  2. 分层策略选择:大多数 Agent 决策场景使用 L1 概述即可满足需求;仅对确需精确执行的操作加载 L2 详情。
  3. 队列监控:生产环境必须监控 EmbeddingQueue 的 pending 和 error_count,防止摄入速度超过处理速度。
  4. 定期审计记忆:长期运行后,agent/memories/ 和 agent/skills/ 可能积累过时或噪声记忆,建议定期清理。
  5. 配置配套模型:使用同一厂商的 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()

代码解析

  1. DocumentManager 运用了知识点 1(viking:// 文件系统范式):将技术文档按 viking://resources/docs/{project}/{doc_name} 的 URI 规范组织到虚拟文件系统中。使用 add_resource() 添加文档,tree() 验证目录结构。

  2. SmartRetriever 运用了知识点 2(L0/L1/L2 分层上下文加载):先通过 find() 语义搜索获取候选 URI 列表,然后优先加载 L1 概述(overview()),仅在 Token 预算允许时对最相关的一条加载 L2 详情(read())。这实现了 Token 预算管理。

  3. SessionManager 运用了知识点 3(会话管理与记忆提炼):通过 create_session() 创建会话,add_message() 记录对话历史,commit() 异步提炼记忆,wait_processed() 等待提炼完成。提炼后的记忆自动存储到 viking://user/memories/viking://agent/memories/

扩展挑战

  1. 接入真实 LLM:将 chat() 方法中的简化回答替换为真实的 OpenAI/Claude API 调用,将检索到的上下文注入到 prompt 中。
  2. 添加 Rerank 策略:在 SmartRetriever.retrieve() 中添加 Rerank 步骤,对 L0 摘要进行重排序后再加载 L1。
  3. 多用户支持:为不同用户维护独立的会话和记忆空间,实现个性化文档助手。

第五部分:常见问题与排查指南

常见错误及解决方案

错误信息 原因 解决方案
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

调试技巧

  1. 使用 ov status 检查系统状态:Rust CLI 工具 ov status 可以快速检查服务器状态、队列积压情况、存储使用量等关键指标。

  2. 查看 L0/L1 文件验证分层生成:使用 client.abstract(uri)client.overview(uri) 检查自动生成的分层文件是否正确。如果摘要或概述内容不准确,可能是 VLM 模型质量问题——尝试切换更强的模型(如从 gpt-4o-mini 升级到 gpt-4o)。

  3. 监控 QueueObserver 追踪异步处理:生产环境中,关注 QueueObserver 的 pending(待处理数)、error_count(错误数)和处理时延指标。当 pending 持续增长时,说明摄入速度需要限流。


第六部分:学习路线推荐

官方文档推荐阅读顺序

  1. About OpenViking (docs/en/about/01-about-us.md) — 理解项目定位和设计理念
  2. Context Types (docs/en/concepts/01-context-types.md) — 理解三种上下文类型(记忆、资源、技能)
  3. Viking URI (docs/en/concepts/02-viking-uri.md) — 掌握 URI 规范和寻址方式
  4. Context Layers (docs/en/concepts/03-context-layers.md) — 深入理解 L0/L1/L2 分层机制
  5. Retrieval Mechanism (docs/en/concepts/retrieval.md) — 目录递归检索算法详解
  6. VikingBot (docs/en/guides/vikingbot.md) — 使用内置 Agent 框架构建应用

推荐进阶资源