open-context-engine-skill
一个工业级、开源的 Augment Context Engine (ACE) 实现方案。
open-context-engine-skill 是一个高性能的语义代码搜索和上下文收集引擎,旨在弥合海量代码库与 LLM(大语言模型)有限上下文窗口之间的鸿沟。它使 AI Agent(如 Claude Code)能够实时导航、理解并综合复杂的项目结构。
核心特性
- 零依赖核心 (Zero-Dependency Core):完全使用 Python 3 标准库编写。无需
pip install,在任何环境中均具有最大的可移植性。 - 双层增量缓存 (Two-Layer Incremental Caching):
- AST/模式缓存:利用内容哈希,跳过对未变更文件的重复解析。
- 语义评分缓存:基于 SQLite 的持久化存储(
.oce_cache),针对相似查询复用 LLM 的排序结果,将延迟从数秒降至 <500ms。
- 并行 LLM 排序 (Parallel LLM Ranking):通过多线程 LLM 客户端实现高吞吐量评分,可同时快速评估数百个代码块。
- 多语言智能 (Multi-Language Intelligence):
- Python:基于深度的 AST(抽象语法树)提取。
- 通用语言:基于模式(Pattern-based)提取,支持 TS/JS, Go, Rust, Java, C++ 等 10 多种语言。
- Git 感知过滤 (Git-Aware Filtering):自动遵循
.gitignore规则,并忽略二进制文件、供应商目录(vendor)和构建产物。 - 上下文打包 (Context Packing):智能组装最相关的代码片段,生成经 Token 优化的“上下文包 (Context Pack)”,供 LLM 直接使用。
Claude 的实战手记:一次真实的搜索对比
大家好,我是 Claude。让我分享一个今天发生的真实调试故事。
挑战
用户让我查找一个 Next.js 全栈项目中的“管理员生成逻辑 (admin generation logic)”——这是一个包含 OAuth、支付和基于角色权限的 CMS 平台。
这是一个典型的意图模糊查询 (ambiguous intent query)。“管理员生成”可能意味着:
- 数据库种子脚本 (Seed script)
- 初始化例程
- 注册流程的一部分
- 一个隐藏的管理员面板功能
代码库有 200 多个文件,手动搜索将耗费大量时间。
尝试 1:ACE (Augment Context Engine)
我首先尝试了 ACE,使用了包含大量关键词的查询:
查询 1: "Find where admin user is created or generated, administrator
account initialization logic. Keywords: admin, create, generate,
init, seed"
查询 2: "Find user registration, account creation, or seed script that
creates the first admin user. Keywords: register, signup, role"
2 次查询后的结果:
| 返回的文件 | 内容 |
|---|---|
actions/cms.ts | 权限检查:user?.role === "admin" |
actions/admin-*.ts | 管理员面板的 CRUD 操作 |
db/schema.ts | 包含 role 字段的用户表定义 |
ACE 找到了使用管理员权限的代码,但没有找到创建权限的代码。关键词 "admin" 在权限检查中出现了 50 多次,淹没了真正的创建逻辑。
尝试 2:OCE (Open Context Engine)
切换到 OCE,使用自然语言查询:
python scripts/search_context.py \
--project "/path/to/nextjs-cms" \
--query "I want to find where admin users are created or generated
during system initialization, how the first admin account
is set up"
# (我想找到在系统初始化期间在哪里创建或生成管理员用户,以及第一个管理员账户是如何设置的)
结果:第一次查询即命中目标。
OCE 返回了 src/app/api/auth/verify-email/route.ts,评分 10/10:
// If this is the first user, promote to admin
const userCount = await db.select({ id: users.id }).from(users);
if (userCount.length === 1) {
await db.update(users)
.set({ role: "admin" })
.where(eq(users.id, user.id));
user.role = "admin";
}
发现:该项目使用“第一个注册用户自动成为管理员”的模式,嵌入在电子邮件验证流程中——而不是种子脚本。
技术分析:为什么 OCE 成功了
1. 语义理解 vs 关键词匹配
| 维度 | ACE (基于关键词) | OCE (LLM 评分) |
|---|---|---|
| 查询解读 | 字面匹配 "admin" | 理解 "creation" (创建) vs "usage" (使用) |
| 结果排序 | 频率加权 | 语义相关性 (0-10) |
| 噪声过滤 | 有限 | LLM 剔除误报 |
2. 关键词陷阱
ACE 的关键词匹配被高频模式污染了:
// 这种模式在 12 个文件中出现了 47 次
if (user?.role !== "admin") {
return { success: false, error: "No permission" };
}
每一个权限检查都包含 "admin" + "user",触发了误报。
3. OCE 的评分机制
OCE 的 LLM 评估器理解了语义上的差异:
| 代码模式 | ACE 相关性 | OCE 评分 | 原因 |
|---|---|---|---|
role !== "admin" (检查) | 高 (关键词匹配) | 2-3 | 仅是使用,非创建 |
set({ role: "admin" }) (赋值) | 中 | 10 | 实际的角色赋值 |
userCount.length === 1 (条件) | 低 | 10 | 首个用户逻辑 |
结果对比
| 指标 | ACE | OCE |
|---|---|---|
| 所需查询次数 | 2 (未完成) | 1 |
| 返回文件数 | 6 个文件 | 1 个文件 |
| 找到核心逻辑 | 否 | 是 |
| 误报率 | ~90% | 0% |
| Token 消耗 | ~4500 | ~1200 |
关键结论
-
意图模糊的查询更适合语义搜索
- “找到 X 是在哪里被创建的”需要理解“创建”与“使用”的区别。
- 关键词匹配无法区分这些语义。
-
高频模式会制造噪声
- 常见模式(权限检查、日志记录)会污染关键词搜索结果。
- LLM 评分可以识别并过滤不相关的匹配。
-
自然语言查询优于关键词列表
- 差:
"admin creation. Keywords: admin, create, generate" - 好:
"I want to find where admin users are created during initialization"
- 差:
-
Token 效率与精度正相关
- OCE 通过排除误报,减少了 73% 的 Token 返回量。
- 更少的噪声 = 更快的理解 = 更好的回答。
何时使用哪种工具
| 场景 | 推荐工具 |
|---|---|
已知模式查找 ("find all useState hooks") | ACE |
意图模糊 ("how does auth work") | OCE |
| 跨模块追踪 | OCE + --deep |
| 首次探索代码库 | OCE |
— Claude, 2025-01-24
(在为了从数百个文件中找到那 5 行像“大海捞针”一样的代码而进行海量扫描之后)
安装
-
克隆仓库:
git clone https://github.com/oldjs/open-context-engine-skill.git cd open-context-engine-skill -
配置 API 访问: 在
open-context-engine-skill/.config/open-context-engine/config.json创建配置文件:{ "api_url": "https://api.openai.com/v1", "api_key": "your-api-key", "model": "gpt-oss-120b", "max_tokens": 8000 }
使用方法
命令行接口
针对任何项目运行语义搜索:
python scripts/search_context.py \
--project "/path/to/target/project" \
--query "Find where the database connection is initialized and how retries are handled."
与 AI 工具 (Claude Code) 集成
该引擎被设计为一项 Skill (技能)。当 Agent 遇到复杂的代码库查询时,它会调用 search_context.py 来检索最相关的逻辑:
- [search-mode] (搜索模式):使用并行 Agent 和感知 AST 的工具在代码库中进行详尽搜索。
- [analyze-mode] (分析模式):在建议架构更改之前,进行深度的上下文收集和关系映射。
架构
引擎遵循严格优化的管道流程:
- File Collector (文件收集器):扫描项目,应用 Git 规则并检测二进制文件。
- Code Chunker (代码分块器):将文件拆分为逻辑单元(类、函数或块),同时保留元数据。
- Cache Manager (缓存管理器):处理 SQLite 交互和内容哈希,确保重复查询零成本。
- Context Ranker (上下文排序器):使用线程安全的 LLM 客户端执行多线程评分。
- Context Packer (上下文打包器):将结果整合为单一、结构化的 JSON 输出,且控制在 Token 限制内。
性能
| 项目规模 | 冷搜索 (首次) | 热搜索 (缓存后) |
|---|---|---|
| 小型 (<100 文件) | ~20-40ms | ~15ms |
| 中型 (~500 文件) | ~80-120ms | ~35ms |
| 大型 (>1000 文件) | ~1s+ | ~35ms |
Token 消耗:回应开发者的担忧
“这个技能会烧光我的 Token 吗?”
简短回答:不会。 以下是真实数据和技术解释。
真实世界实测
在生产级代码库(每个 200+ 文件)上测试:
| 项目 | 文件数 | 冷搜索 (无缓存) | 热搜索 (有缓存) |
|---|---|---|---|
| Flutter + Go 全栈 | 200+ | ~2000 输入 / ~50 输出 | 0 tokens |
| Next.js CMS | 200+ | ~2000 输入 / ~50 输出 | 0 tokens |
| 本项目 (OCE) | ~20 | ~800 输入 / ~30 输出 | 0 tokens |
核心洞察:在一个 200+ 文件的项目上进行冷搜索仅消耗约 2000 输入 Token。在 GPT-4o-mini 上这大约仅需 $0.0001。
为什么这么低?签名提取 + 双层缓存
优化 1:签名提取 (而非完整代码)
OCE 不会将完整代码发送给 LLM 进行评分。相反,它提取紧凑的签名:
# 原始 150 行的类
class UserService:
"""Handles user authentication and session management."""
def __init__(self, db: Database, cache: Redis):
self.db = db
self.cache = cache
def authenticate(self, username: str, password: str) -> User:
# ... 50 lines of implementation
def create_session(self, user: User) -> Session:
# ... 40 lines of implementation
# ... 50 more lines
# LLM 实际看到的 (extract_signature 的输出):
# ─────────────────────────────────────────────────
# [0] src/services/user.py (class, L1-150)
# class UserService:
# """Handles user authentication and session management."""
#
# def __init__(self, db: Database, cache: Redis):
# def authenticate(self, username: str, password: str) -> User:
# def create_session(self, user: User) -> Session:
# ... (142 more lines)
不同块类型的提取规则:
| 块类型 | 发送行数 | 包含内容 |
|---|---|---|
| function/method | 前 8 行 | 签名 + 文档字符串 |
| class/struct/interface | 最多 12 个关键行 | 声明 + 字段定义 |
| export | 前 10 行 | 导出语句 + 签名 |
| block | 前 8 行 | 起始上下文 |
Token 节省:一个 150 行的类在评分时仅占约 15 个 Token。甚至在命中缓存之前就已减少 90%。
优化 2:双层缓存架构
OCE 使用块级语义缓存,而不是查询级缓存。这是关键区别。
┌─────────────────────────────────────────────────────────────┐
│ 搜索请求 │
│ "Find where admin users are created" │
└─────────────────────┬───────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 第 1 层: 文件块缓存 (SQLite: file_cache) │
│ ───────────────────────────────────────────────────────── │
│ Key: file_path │
│ Value: { hash: MD5(file_content), chunks: [...] } │
│ │
│ 命中: 文件未变 → 跳过重新解析 │
│ 未命中: 重新分块文件 → 更新缓存 │
└─────────────────────┬───────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 第 2 层: 评分缓存 (SQLite: score_cache) │
│ ───────────────────────────────────────────────────────── │
│ Key: (query_key, chunk_hash) │
│ query_key = MD5(sorted(keywords)) │
│ chunk_hash = MD5(code_content) │
│ │
│ 命中: 相同关键词 + 相同代码 → 返回缓存分数 │
│ 未命中: 调用 LLM 评分 → 更新缓存 │
└─────────────────────┬───────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 结果: 只有【未缓存】的块才会触发 LLM 调用 │
└─────────────────────────────────────────────────────────────┘
缓存键设计 (为什么命中率高)
# 查询键: 基于【关键词】,而非确切的查询文本
query_key = MD5(",".join(sorted(["admin", "create", "user"])))
# 以下查询生成相同的 query_key:
# - "Find where admin users are created"
# - "Show me user creation for admin accounts"
# - "admin user create logic"
结果:语义相似的查询共享缓存条目。
# 块哈希: 基于【代码内容】
chunk_hash = MD5(code_block_content)
# 相同代码 = 相同哈希,无论:
# - 文件路径变更 (移动文件依然命中缓存)
# - 查询变化 (不同查询,只要代码相同且关键词组相同 = 命中)
Token 消耗公式
冷搜索 (首次):
tokens = 需评分的块数 × 平均提示大小
≈ 150 块 × 15 tokens/块
≈ 2000-2500 tokens
热搜索 (缓存命中):
tokens = 0 ← 无需 LLM 调用
部分缓存 (部分文件变更):
tokens = 新增块数 × 平均提示大小
≈ (仅变更的文件) × 15 tokens/块
实际场景
| 场景 | Token 成本 | 解释 |
|---|---|---|
| 相同查询,相同代码库 | 0 | 100% 缓存命中 |
| 相似查询 (关键词相同) | 0 | 关键词匹配 → 缓存命中 |
| 编辑 1 个文件后查询 | ~50 | 仅新块重新评分 |
git pull (10 个文件变更) 后查询 | ~300 | 仅变更文件重新评分 |
| 完全新的查询主题 | ~2000 | 全量评分,但会为下次缓存 |
为什么不是查询级缓存?
传统方法:缓存 (精确查询字符串) → 结果
问题:"Find admin creation" 和 "Where are admins created" 字符串不同,但意图相同。
OCE 方法:缓存 (关键词, 代码哈希) → 分数
优势:
- 关键词标准化提高了命中率
- 代码级粒度意味着部分更新很便宜
- 相似查询可以从彼此的缓存中受益
总结
| 担忧 | 现实 |
|---|---|
| "200 个文件 = 很贵" | 200 文件 ≈ 2000 tokens (冷), 0 tokens (热) |
| "每次搜索都花钱" | 仅每组关键词的第一次搜索花钱 |
| "缓存失效问题" | 基于内容哈希 → 变更自动失效 |
| "内存开销" | 10,000 个块的 SQLite 文件 < 1MB |
算一笔账:如果你每天在同一个项目上用不同的查询搜索 100 次,你会命中缓存 90% 以上。每日成本 ≈ $0.001。
基准测试:OCE Deep 模式 vs Ace (2025-01-24)
这是一项 A/B 测试,对比 open-context-engine-skill Deep Mode (--deep) 与 Ace (Augment's Context Engine MCP) 在同一代码库上的表现。
测试查询
| # | 查询 | 难度 |
|---|---|---|
| Q1 | How to modify the LLM scoring logic to support custom weights? | 中等 (单一模块) |
| Q2 | How does the cache system integrate with the scoring system? | 中等 (跨模块) |
| Q3 | How to add support for a new programming language (e.g., Elixir)? | 简单 (扩展点) |
Q1: LLM 评分逻辑
| 维度 | Ace | OCE Deep |
|---|---|---|
| 返回文件 | 7 个片段 (context_ranker, search_context, context_expander, README, config, cache_manager) | 5 个块 (仅 context_ranker) |
| 核心命中 | rank_chunks, build_prompt, parse_scores | rank_chunks(9), parse_scores(8), build_prompt(8), quick_score(7) |
| 噪声 | 包含 context_expander, config.py, README | 零噪声 |
| Tokens | ~4000 | 1827 |
Q2: 缓存-评分集成
| 维度 | Ace | OCE Deep |
|---|---|---|
| 返回文件 | 5 个完整文件片段 | 2 个块 (2 个文件) |
| 核心命中 | 完整的 CacheManager 类, 完整的 rank_chunks | rank_chunks(9), CacheManager(8) |
| 集成点 | 需要阅读大段代码块 | 直接展示缓存集成点 |
| Tokens | ~4500 | 2040 |
Q3: 添加新语言支持
| 维度 | Ace | OCE Deep |
|---|---|---|
| 返回文件 | 4 个文件 (code_chunker 完整版, file_collector, SKILL, README) | 3 个块 (仅 code_chunker) |
| 核心命中 | LANGUAGE_PATTERNS, EXT_TO_LANGUAGE (埋在 400+ 行代码中) | LANGUAGE_PATTERNS(8), chunk_file(8), EXT_TO_LANGUAGE(6) |
| 扩展点 | 必须搜索大文件 | 3 个精确的修改位置 |
| Tokens | ~3000 | 1770 |
总体对比
| 维度 | Ace | OCE Deep | 胜者 |
|---|---|---|---|
| 精度 | B (覆盖广,需人工过滤) | A+ (手术刀般精准) | OCE Deep |
| 噪声控制 | C (包含文档、配置) | A+ (零噪声) | OCE Deep |
| 上下文完整性 | A (完整调用链) | B+ (核心 + 智能扩展) | Ace (略胜) |
| Token 效率 | C (平均 ~3833) | A+ (平均 ~1879) | OCE Deep |
| LLM 友好度 | B (需要大量阅读) | A+ (立即可操作) | OCE Deep |
Token 效率
| 查询 | Ace (预估) | OCE Deep | 节省 |
|---|---|---|---|
| Q1 | ~4000 | 1827 | 54% |
| Q2 | ~4500 | 2040 | 55% |
| Q3 | ~3000 | 1770 | 41% |
| 平均 | ~3833 | 1879 | ~51% |
准确性分析
Deep 模式在所有测试查询中均达到 100% 准确率:
| 查询 | 核心命中率 | 噪声率 | 结论 |
|---|---|---|---|
| Q1: LLM 评分 | 100% | 0% | 所有返回的块都是实际修改点 |
| Q2: 缓存集成 | 100% | 0% | 直接展示了 rank_chunks 内部对 CacheManager 的调用 |
| Q3: 新语言 | 100% | 0% | 精确定位了 3 个需修改的位置 |
Q1 细分:
| 返回块 | 分数 | 是否核心? |
|---|---|---|
rank_chunks() | 9 | 核心 - 主评分入口 |
parse_scores() | 8 | 核心 - 解析 LLM 响应 |
build_prompt() | 8 | 核心 - 构建评分提示词 |
quick_score() | 7 | 相关 - 预评分逻辑 |
Q3 细分:
| 返回块 | 分数 | 所需操作 |
|---|---|---|
LANGUAGE_PATTERNS | 8 | 添加 Elixir 正则模式 |
chunk_file() | 8 | 处理 .ex 扩展名 |
EXT_TO_LANGUAGE | 6 | 映射 .ex → elixir |
关键发现
为什么 Deep 模式消耗更少的 Token (反直觉!)
Deep 模式不是“返回更多上下文”,而是**“返回更精准的上下文”**。
扩展逻辑的设计带有智能克制:
# 仅当前几名块的分数 >= 6 时扩展
top_chunks = [c for c in chunks if c.get("score", 0) >= 6][:5]
# LLM 决定是否需要扩展
expanded = expand_context(client, query, top_chunks, ...)
当 LLM 分析器确定“这些核心块足以回答查询”时,它会返回一个空的扩展列表。这是正确的行为——明智的克制胜过盲目的扩展。
OCE Deep 模式优势:
- 节省 51% Token:精度胜过体量
- 手术刀般精准:仅返回确切需要的代码块
- 零噪声:结果中无 README、配置或无关文件
- 高相关性评分:核心函数始终得分为 8-9
- 智能扩展:仅在真正需要时扩展,否则保持精简
Ace 优势:
- 完整的代码覆盖在对项目完全陌生时有帮助
- 完整的调用链对于非常大规模的重构更安全
建议
| 用例 | 推荐工具 |
|---|---|
| 日常开发查询 | OCE Deep |
| 快速 Bug 修复 | OCE Deep |
| 扩展点查找 | OCE Deep |
| 跨模块集成 | OCE Deep |
| 架构深度探索 (新项目) | Ace |
| 大规模重构 (100+ 文件) | Ace |
跨语言支持:Flutter + Go 全栈项目
OCE 提供无缝的跨语言搜索能力。以下是一个 Flutter + Go 全栈应用 (~200 文件, Dart 前端 + Go 后端) 的真实基准测试。
测试项目结构
my_first_app/
├── lib/ # Flutter 前端 (Dart)
│ ├── main.dart # App 入口
│ ├── core/api_client.dart # Dio HTTP 客户端
│ ├── data/auth_manager.dart # ChangeNotifier 状态
│ ├── services/*.dart # API 服务层
│ └── pages/*.dart # UI 组件
└── server/ # Go 后端
├── main.go # HTTP 服务 + 路由
├── *_handler.go # 请求处理器
├── models/*.go # GORM 模型
└── utils/*.go # 工具类
测试查询与结果
| 查询 | 块数 | 文件数 | Tokens | 最高分 | 亮点 |
|---|---|---|---|---|---|
| Q1: App 入口与初始化 | 1 | 1 | 1021 | 9 | 精确命中 main() + ShanhaiApp |
| Q2: 状态管理模式 | 13 | 8 | 1423 | 9 | 找到所有 ChangeNotifier + setState |
| Q3: 网络/API 调用 | 14 | 7 | 1848 | 9 | 跨语言: Dart 客户端 + Go 处理器 |
Q1: App 入口点
python scripts/search_context.py \
--project "/path/to/flutter_app" \
--query "Find the main entry point and app initialization flow"
结果:单个块 (1021 tokens) 包含完整的初始化链:
| 组件 | 描述 |
|---|---|
isDesktop | 平台检测 |
main() | 窗口管理器 + ApiClient 初始化 |
ShanhaiApp | MaterialApp 配置 |
build() | 主题 + 路由设置 |
Q2: 状态管理
结果:8 个文件中的 13 个块,覆盖:
| 模式 | 发现的文件 |
|---|---|
ChangeNotifier 单例 | auth_manager.dart, record_manager.dart |
setState() 使用 | login_page.dart, voice_feed_page.dart, 等 |
| 监听器模式 | _onAuthChanged(), _onRecordsChanged() |
Q3: 网络请求 (跨语言)
结果:来自 Dart 和 Go 代码的 14 个块:
| 语言 | 文件 | 关键发现 |
|---|---|---|
| Dart | 4 | ApiClient (Dio 封装), user_service.dart, membership_service.dart |
| Go | 3 | GetRechargeOrdersHandler, ExchangeMembershipHandler, syncRechargeToBackend |
这展示了 OCE 理解全栈请求流的能力——从 Flutter 前端一直贯穿到 Go 后端。
与 ACE 对比
| 维度 | ACE | OCE | 胜者 |
|---|---|---|---|
| Token 效率 | 平均 ~3500 | 平均 ~1430 | OCE (节省 59%) |
| 跨语言 | 需分别查询 | 自动 | OCE |
| 粒度 | 文件级片段 | 块级 | OCE |
| 噪声 | 包含配置、README | 零噪声 | OCE |
关键结论
- 跨语言智能:单次查询同时返回 Dart 和 Go 代码
- 模式识别:正确识别
ChangeNotifier为 Flutter 的状态管理 - 块级精度:返回具体函数,而非整个文件
- 高准确度:所有核心块得分均为 8-9
归档:过往基准测试
OCE 标准模式 vs Ace (2025-01-24)
| 查询 | Ace (预估) | OCE 标准模式 | 节省 |
|---|---|---|---|
| Q1 | ~4000 | 2074 | 48% |
| Q2 | ~4500 | 3625 | 19% |
| Q3 | ~3000 | 3105 | -3% |
| 平均 | ~3833 | 2935 | ~23% |
早期结果 (早期版本)
| 查询 | Ace | OCE (早期) | 节省 |
|---|---|---|---|
| Q1 | ~4000 | 2673 | 33% |
| Q2 | ~4500 | 3207 | 29% |
| Q3 | ~3000 | 944 | 69% |
| 平均 | ~3833 | 2275 | ~40% |