OpenContextEngine-skill 一个工业级的、开源 Augment Context Engine(ACE)实现

5 阅读13分钟

open-context-engine-skill

源代码: github.com/oldjs/open-…

一个工业级、开源的 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首个用户逻辑

结果对比

指标ACEOCE
所需查询次数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 CMS200+~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 成本解释
相同查询,相同代码库0100% 缓存命中
相似查询 (关键词相同)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) 在同一代码库上的表现。

测试查询

#查询难度
Q1How to modify the LLM scoring logic to support custom weights?中等 (单一模块)
Q2How does the cache system integrate with the scoring system?中等 (跨模块)
Q3How to add support for a new programming language (e.g., Elixir)?简单 (扩展点)

Q1: LLM 评分逻辑

维度AceOCE Deep
返回文件7 个片段 (context_ranker, search_context, context_expander, README, config, cache_manager)5 个块 (仅 context_ranker)
核心命中rank_chunks, build_prompt, parse_scoresrank_chunks(9), parse_scores(8), build_prompt(8), quick_score(7)
噪声包含 context_expander, config.py, README零噪声
Tokens~40001827

Q2: 缓存-评分集成

维度AceOCE Deep
返回文件5 个完整文件片段2 个块 (2 个文件)
核心命中完整的 CacheManager 类, 完整的 rank_chunksrank_chunks(9), CacheManager(8)
集成点需要阅读大段代码块直接展示缓存集成点
Tokens~45002040

Q3: 添加新语言支持

维度AceOCE 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~30001770

总体对比

维度AceOCE 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~4000182754%
Q2~4500204055%
Q3~3000177041%
平均~38331879~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_PATTERNS8添加 Elixir 正则模式
chunk_file()8处理 .ex 扩展名
EXT_TO_LANGUAGE6映射 .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 入口与初始化1110219精确命中 main() + ShanhaiApp
Q2: 状态管理模式13814239找到所有 ChangeNotifier + setState
Q3: 网络/API 调用14718489跨语言: 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 初始化
ShanhaiAppMaterialApp 配置
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 个块:

语言文件关键发现
Dart4ApiClient (Dio 封装), user_service.dart, membership_service.dart
Go3GetRechargeOrdersHandler, ExchangeMembershipHandler, syncRechargeToBackend

这展示了 OCE 理解全栈请求流的能力——从 Flutter 前端一直贯穿到 Go 后端。

与 ACE 对比

维度ACEOCE胜者
Token 效率平均 ~3500平均 ~1430OCE (节省 59%)
跨语言需分别查询自动OCE
粒度文件级片段块级OCE
噪声包含配置、README零噪声OCE

关键结论

  • 跨语言智能:单次查询同时返回 Dart 和 Go 代码
  • 模式识别:正确识别 ChangeNotifier 为 Flutter 的状态管理
  • 块级精度:返回具体函数,而非整个文件
  • 高准确度:所有核心块得分均为 8-9

归档:过往基准测试

OCE 标准模式 vs Ace (2025-01-24)

查询Ace (预估)OCE 标准模式节省
Q1~4000207448%
Q2~4500362519%
Q3~30003105-3%
平均~38332935~23%

早期结果 (早期版本)

查询AceOCE (早期)节省
Q1~4000267333%
Q2~4500320729%
Q3~300094469%
平均~38332275~40%