Skip to content

渐进式披露机制 (Progressive Disclosure) 🎯

"从元数据到完整内容 —— Claude Code 如何通过分层加载实现上下文优化"


1. 什么是渐进式披露

1.1 核心概念

渐进式披露 是一种上下文管理策略,按需分层加载内容:

传统方式: 启动时加载所有内容 → 53,000 tokens

渐进式披露:
  Layer 1 (启动): 元数据 → ~2,000 tokens
  Layer 2 (触发): 摘要 → ~5,000 tokens
  Layer 3 (使用): 完整内容 → 按需加载

1.2 收益对比

指标传统方式渐进式披露改进
启动 tokens100,0005,00095% ↓
首次响应5-10s<1s90% ↓
平均 tokens/对话120,00015,00087% ↓
成本/1000 对话$360$4587% ↓

2. 三层架构

2.1 Layer 1: 元数据层

目标: 让 Agent 知道"有什么可用"

typescript
interface ToolMetadata {
  name: string;
  description: string;  // 1 句话描述
  category?: string;
}

// 示例
const toolsMetadata = [
  { name: "Read", description: "读取文件内容" },
  { name: "Edit", description: "编辑文件" },
  { name: "Bash", description: "执行 shell 命令" }
];

Skills 元数据:

typescript
interface SkillMetadata {
  name: string;
  trigger: string;      // 触发条件
  description: string;  // 简短描述
}

const skillsMetadata = [
  {
    name: "commit",
    trigger: "用户输入 /commit",
    description: "创建 git commit"
  },
  {
    name: "code-review",
    trigger: "用户输入 /code-review",
    description: "代码审查"
  }
];

2.2 Layer 2: 摘要层

触发时机: Agent 决定使用某个工具/Skill

typescript
interface ToolSummary extends ToolMetadata {
  parameters: {
    name: string;
    type: string;
    required: boolean;
    description: string;
  }[];
  examples?: string[];  // 简短示例
}

// 示例
const readToolSummary = {
  name: "Read",
  description: "读取文件内容",
  parameters: [
    { name: "file_path", type: "string", required: true, description: "文件路径" },
    { name: "offset", type: "number", required: false, description: "起始行" },
    { name: "limit", type: "number", required: false, description: "读取行数" }
  ],
  examples: ["Read('src/App.tsx')", "Read('README.md', 100, 50)"]
};

Skills 摘要:

typescript
interface SkillSummary extends SkillMetadata {
  instructions: string;  // 核心指令(200-300 tokens)
  tools: string[];       // 可用工具列表
}

2.3 Layer 3: 完整内容层

触发时机: 需要详细文档或复杂逻辑

typescript
interface ToolFull extends ToolSummary {
  implementation?: string;  // 实现细节
  edgeCases?: string[];     // 边界情况
  bestPractices?: string[]; // 最佳实践
}

interface SkillFull extends SkillSummary {
  fullInstructions: string;  // 完整指令
  references?: string[];     // 引用文档
  examples?: string[];       // 详细示例
}

3. 实现机制

3.1 工具懒加载

typescript
class ToolRegistry {
  private metadata: Map<string, ToolMetadata> = new Map();
  private summaries: Map<string, ToolSummary> = new Map();
  private full: Map<string, ToolFull> = new Map();

  // 启动时加载元数据
  async initialize() {
    const tools = await loadToolsMetadata();
    tools.forEach(t => this.metadata.set(t.name, t));
  }

  // 按需加载摘要
  async getSummary(name: string): Promise<ToolSummary> {
    if (!this.summaries.has(name)) {
      this.summaries.set(name, await loadToolSummary(name));
    }
    return this.summaries.get(name)!;
  }

  // 按需加载完整内容
  async getFull(name: string): Promise<ToolFull> {
    if (!this.full.has(name)) {
      this.full.set(name, await loadToolFull(name));
    }
    return this.full.get(name)!;
  }
}

3.2 Skills 懒加载

typescript
class SkillRegistry {
  private metadata: SkillMetadata[] = [];
  private loaded: Map<string, SkillFull> = new Map();

  async initialize() {
    this.metadata = await loadSkillsMetadata();
  }

  // 检测触发
  detectTrigger(userInput: string): string | null {
    for (const skill of this.metadata) {
      if (this.matchesTrigger(userInput, skill.trigger)) {
        return skill.name;
      }
    }
    return null;
  }

  // 加载完整 Skill
  async load(name: string): Promise<SkillFull> {
    if (!this.loaded.has(name)) {
      this.loaded.set(name, await loadSkillFull(name));
    }
    return this.loaded.get(name)!;
  }

  private matchesTrigger(input: string, trigger: string): boolean {
    // 简化的触发匹配逻辑
    return input.includes(trigger) || input.startsWith(`/${trigger}`);
  }
}

3.3 记忆懒加载

typescript
class MemorySystem {
  private metadata: { id: string; summary: string; timestamp: Date }[] = [];

  async initialize() {
    this.metadata = await loadMemoryMetadata();
  }

  // 语义搜索相关记忆
  async search(query: string, limit: number = 5) {
    const embedding = await getEmbedding(query);
    const relevant = await vectorSearch(embedding, this.metadata, limit);

    // 加载完整记忆内容
    return Promise.all(relevant.map(m => loadMemoryFull(m.id)));
  }
}

4. 系统提示词注入

4.1 启动时注入(Layer 1)

typescript
function buildInitialPrompt() {
  return `
You are Claude Code, an AI coding assistant.

Available tools (${tools.length}):
${tools.map(t => `- ${t.name}: ${t.description}`).join('\n')}

Available skills (${skills.length}):
${skills.map(s => `- /${s.name}: ${s.description}`).join('\n')}

Use tools by calling them with parameters.
Skills are triggered when user types /${skillName}.
  `.trim();
}

4.2 触发时注入(Layer 2)

typescript
async function injectToolSummary(toolName: string) {
  const summary = await toolRegistry.getSummary(toolName);

  return `
Tool: ${summary.name}
${summary.description}

Parameters:
${summary.parameters.map(p =>
  `- ${p.name} (${p.type}${p.required ? ', required' : ''}): ${p.description}`
).join('\n')}

Examples:
${summary.examples?.join('\n') || 'N/A'}
  `.trim();
}

4.3 使用时注入(Layer 3)

typescript
async function injectSkillFull(skillName: string) {
  const skill = await skillRegistry.load(skillName);

  return `
# Skill: ${skill.name}

${skill.fullInstructions}

Available tools: ${skill.tools.join(', ')}

${skill.references ? `\nReferences:\n${skill.references.join('\n')}` : ''}
  `.trim();
}

5. 实战案例

5.1 场景:用户请求 /commit

typescript
async function handleUserInput(input: string) {
  // 1. 检测 Skill 触发
  const skillName = skillRegistry.detectTrigger(input);

  if (skillName) {
    // 2. 加载 Skill 完整内容
    const skill = await skillRegistry.load(skillName);

    // 3. 注入到上下文
    const prompt = buildPromptWithSkill(skill);

    // 4. 调用 LLM
    return await llm.chat({ messages: [{ role: 'system', content: prompt }] });
  }
}

// Token 消耗:
// - 启动: 5,000 tokens (元数据)
// - 触发 /commit: +3,000 tokens (Skill 完整内容)
// - 总计: 8,000 tokens (vs 传统方式的 100,000 tokens)

5.2 场景:使用 Read 工具

typescript
async function handleToolCall(toolName: string, args: any) {
  // 1. 首次使用时加载摘要
  if (!toolRegistry.hasSummary(toolName)) {
    const summary = await toolRegistry.getSummary(toolName);
    injectToContext(summary);
  }

  // 2. 执行工具
  return await executeTool(toolName, args);
}

// Token 消耗:
// - 启动: 5,000 tokens
// - 首次使用 Read: +500 tokens (摘要)
// - 后续使用: 0 tokens (已缓存)

6. 优化策略

6.1 预加载热门内容

typescript
class SmartRegistry {
  private hotSkills = ['commit', 'code-review', 'feature-dev'];

  async initialize() {
    await this.loadMetadata();

    // 预加载热门 Skills 的摘要
    await Promise.all(
      this.hotSkills.map(name => this.loadSummary(name))
    );
  }
}

6.2 缓存策略

typescript
class CachedRegistry {
  private cache = new LRUCache<string, any>({ max: 50 });

  async load(id: string) {
    if (this.cache.has(id)) {
      return this.cache.get(id);
    }

    const content = await loadFromDisk(id);
    this.cache.set(id, content);
    return content;
  }
}

6.3 压缩元数据

typescript
// 优化前
const metadata = {
  name: "Read",
  description: "Reads a file from the local filesystem. You can access any file directly by using this tool.",
  category: "filesystem"
};

// 优化后
const metadata = {
  name: "Read",
  description: "读取文件",
  category: "fs"
};

7. 性能监控

typescript
class PerformanceMonitor {
  trackLoading(layer: string, name: string, tokens: number) {
    console.log(`[${layer}] Loaded ${name}: ${tokens} tokens`);
  }

  getStats() {
    return {
      totalTokens: this.totalTokens,
      layerBreakdown: {
        metadata: this.metadataTokens,
        summary: this.summaryTokens,
        full: this.fullTokens
      }
    };
  }
}

8. 最佳实践

  1. 元数据极简: 每个工具/Skill 描述控制在 10 词以内
  2. 摘要精准: 包含核心参数和 1-2 个示例
  3. 按需加载: 只在真正需要时加载完整内容
  4. 预加载热门: 对高频使用的内容提前加载摘要
  5. 缓存复用: 使用 LRU 缓存避免重复加载
  6. 监控优化: 持续跟踪 token 消耗,优化加载策略

9. 与其他机制的协同

9.1 与自动压缩协同

typescript
class HybridSystem {
  async handleConversation(messages: Message[]) {
    // 1. 渐进式披露控制初始上下文
    const initialContext = await this.buildMinimalContext();

    // 2. 对话过程中按需加载
    const additionalContext = await this.loadOnDemand(messages);

    // 3. 接近上下文限制时自动压缩
    if (this.contextSize > this.threshold) {
      await this.compressHistory(messages);
    }
  }
}

9.2 与语义检索协同

typescript
class SemanticDisclosure {
  async loadRelevant(query: string) {
    // 1. 语义搜索相关 Skills
    const relevantSkills = await this.semanticSearch(query, this.skillsMetadata);

    // 2. 加载摘要
    return Promise.all(relevantSkills.map(s => this.loadSummary(s.name)));
  }
}

参考资源


本文基于 Claude Code 2026 年最新实现。

前端面试知识库