open-context-engine-skill

源代码: https://github.com/oldjs/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

关键结论

  1. 意图模糊的查询更适合语义搜索

    • “找到 X 是在哪里被创建的”需要理解“创建”与“使用”的区别。
    • 关键词匹配无法区分这些语义。
  2. 高频模式会制造噪声

    • 常见模式(权限检查、日志记录)会污染关键词搜索结果。
    • LLM 评分可以识别并过滤不相关的匹配。
  3. 自然语言查询优于关键词列表

    • 差:"admin creation. Keywords: admin, create, generate"
    • 好:"I want to find where admin users are created during initialization"
  4. Token 效率与精度正相关

    • OCE 通过排除误报,减少了 73% 的 Token 返回量。
    • 更少的噪声 = 更快的理解 = 更好的回答。

何时使用哪种工具

场景 推荐工具
已知模式查找 ("find all useState hooks") ACE
意图模糊 ("how does auth work") OCE
跨模块追踪 OCE + --deep
首次探索代码库 OCE

— Claude, 2025-01-24
(在为了从数百个文件中找到那 5 行像“大海捞针”一样的代码而进行海量扫描之后)


安装

  1. 克隆仓库

    git clone https://github.com/oldjs/open-context-engine-skill.git
    cd open-context-engine-skill
    
  2. 配置 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 来检索最相关的逻辑:

  1. [search-mode] (搜索模式):使用并行 Agent 和感知 AST 的工具在代码库中进行详尽搜索。
  2. [analyze-mode] (分析模式):在建议架构更改之前,进行深度的上下文收集和关系映射。

架构

引擎遵循严格优化的管道流程:

  1. File Collector (文件收集器):扫描项目,应用 Git 规则并检测二进制文件。
  2. Code Chunker (代码分块器):将文件拆分为逻辑单元(类、函数或块),同时保留元数据。
  3. Cache Manager (缓存管理器):处理 SQLite 交互和内容哈希,确保重复查询零成本。
  4. Context Ranker (上下文排序器):使用线程安全的 LLM 客户端执行多线程评分。
  5. 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 映射 .exelixir

关键发现

为什么 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%
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐