mcpField
P
prompt-caching

prompt-caching

github.com/sickn33開発48.7k869 回インストール今日更新
リポジトリ

prompt-caching について

prompt-cachingは、LLMシステムを開発する人向けのスキルです。プロンプトやレスポンスのキャッシュ、Cache Augmented Generationを扱い、実装パターン、無効化の指針、よくある問題の確認項目を示します。

主な機能

  1. 01Anthropicのプロンプトキャッシュパターン
  2. 02LLMレスポンスのキャッシュ
  3. 03Cache Augmented Generation
  4. 04キャッシュ無効化の戦略
  5. 05キャッシュ指標と検証項目

活用シーン

  1. 01安定したClaude APIのプロンプト接頭辞の再利用
  2. 02繰り返されるLLMクエリのキャッシュ
  3. 03安定した文書コンテキストのキャッシュ提供

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/sickn33/agentic-awesome-skills --skill prompt-caching

インストール後、Claude Code で/prompt-cachingを入力して読み込まれたか確認します。

詳細

翻訳後に原文が更新されています。最新の内容は原文をご確認ください。

プロンプトキャッシュ

Anthropic のプロンプトキャッシュ、レスポンスキャッシュ、CAG(Cache Augmented Generation)など、LLM プロンプト向けのキャッシュ戦略

機能

  • prompt-cache
  • response-cache
  • kv-cache
  • cag-patterns
  • cache-invalidation

前提条件

  • 知識: キャッシュの基礎、LLM API の使用法、ハッシュ関数
  • 推奨スキル: context-window-management

スコープ

  • 対象外: CDN キャッシュ、データベースクエリキャッシュ、静的アセットキャッシュ
  • 境界: LLM 固有のキャッシュに焦点を当て、プロンプトキャッシュとレスポンスキャッシュを扱います

エコシステム

主要ツール
  • Anthropic Prompt Caching - Claude API のネイティブプロンプトキャッシュ
  • Redis - レスポンス用のインメモリキャッシュ(サーバーでは ioredis、サーバーレスでは HTTP 経由の @upstash/redis。upstash-redis を参照)
  • OpenAI Caching - OpenAI API の自動キャッシュ

パターン

Anthropic プロンプトキャッシュ

繰り返されるプレフィックスには Claude のネイティブプロンプトキャッシュを使用します

使用する場面: 安定したシステムプロンプトやコンテキストで Claude API を使用する場合

import Anthropic from '@anthropic-ai/sdk';

const client = new Anthropic();

// プロンプトの安定した部分をキャッシュします async function queryWithCaching(userQuery: string) { const response = await client.messages.create({ model: "claude-sonnet-4-20250514", max_tokens: 1024, system: [ { type: "text", text: LONG_SYSTEM_PROMPT, // 詳細な指示 cache_control: { type: "ephemeral" } // これをキャッシュします! }, { type: "text", text: KNOWLEDGE_BASE, // 大きな静的なコンテキスト cache_control: { type: "ephemeral" } } ], messages: [ { role: "user", content: userQuery } // 動的な部分 ] });

// キャッシュの使用状況を確認します
console.log(`Cache read: ${response.usage.cache_read_input_tokens}`);
console.log(`Cache write: ${response.usage.cache_creation_input_tokens}`);

return response;

}

// コスト削減: キャッシュされたトークンで 90% 削減 // レイテンシ削減: 最大 2 倍高速化

レスポンスキャッシュ

同一または類似のクエリに対して LLM のレスポンス全体をキャッシュします

使用する場面: 同じクエリが繰り返し実行される場合

import { createHash } from 'crypto'; import Redis from 'ioredis';

const redis = new Redis(process.env.REDIS_URL); // 永続的な接続を必要としないサーバーレス/エッジ向けの代替手段: // import { Redis } from '@upstash/redis'; const redis = Redis.fromEnv(); // その後 redis.set(key, value, { ex: ttl }) を使用します

class ResponseCache { private ttl = 3600; // デフォルトは 1 時間

// 完全一致キャッシュ
async getCached(prompt: string): Promise<string | null> {
    const key = this.hashPrompt(prompt);
    return await redis.get(`response:${key}`);
}

async setCached(prompt: string, response: string): Promise<void> {
    const key = this.hashPrompt(prompt);
    await redis.set(`response:${key}`, response, 'EX', this.ttl);
}

private hashPrompt(prompt: string): string {
    return createHash('sha256').update(prompt).digest('hex');
}

// 意味的類似性キャッシュ
async getSemanticallySimilar(
    prompt: string,
    threshold: number = 0.95
): Promise<string | null> {
    const embedding = await embed(prompt);
    const similar = await this.vectorCache.search(embedding, 1);

    if (similar.length && similar[0].similarity > threshold) {
        return await redis.get(`response:${similar[0].id}`);
    }
    return null;
}

// temperature を考慮したキャッシュ
async getCachedWithParams(
    prompt: string,
    params: { temperature: number; model: string }
): Promise<string | null> {
    // 低い temperature のレスポンスのみをキャッシュします
    if (params.temperature > 0.5) return null;

    const key = this.hashPrompt(
        `${prompt}|${params.model}|${params.temperature}`
    );
    return await redis.get(`response:${key}`);
}

}

Cache Augmented Generation (CAG)

RAG 検索の代わりに、プロンプト内にドキュメントを事前キャッシュします

使用する場面: ドキュメントのコーパスが安定しており、コンテキストに収まる場合

// CAG: ドキュメントコンテキストを事前計算し、プロンプトにキャッシュ // 次の場合に RAG より優れています: // - ドキュメントが安定している // - 全体がコンテキストウィンドウに収まる // - レイテンシが重要である

class CAGSystem { private cachedContext: string | null = null; private lastUpdate: number = 0;

async buildCachedContext(documents: Document[]): Promise<void> {
    // ドキュメントを前処理してフォーマット
    const formatted = documents.map(d =>
        `## ${d.title}\n${d.content}`
    ).join('\n\n');

    // タイムスタンプとともに保存
    this.cachedContext = formatted;
    this.lastUpdate = Date.now();
}

async query(userQuery: string): Promise<string> {
    // キャッシュされたコンテキストをプロンプトで直接使用
    const response = await client.messages.create({
        model: "claude-sonnet-4-20250514",
        max_tokens: 1024,
        system: [
            {
                type: "text",
                text: "You are a helpful assistant with access to the following documentation.",
                cache_control: { type: "ephemeral" }
            },
            {
                type: "text",
                text: this.cachedContext!,  // 事前キャッシュされたドキュメント
                cache_control: { type: "ephemeral" }
            }
        ],
        messages: [{ role: "user", content: userQuery }]
    });

    return response.content[0].text;
}

// 定期的な更新
async refreshIfNeeded(documents: Document[]): Promise<void> {
    const stale = Date.now() - this.lastUpdate > 3600000;  // 1 時間
    if (stale) {
        await this.buildCachedContext(documents);
    }
}

}

// CAG と RAG の判断マトリクス: // | 要因 | CAG が優位 | RAG が優位 | // |------------------|------------|------------| // | コーパスサイズ | 100K トークン未満 | 100K トークン超 | // | 更新頻度 | 低 | 高 | // | レイテンシ要件 | 重要 | 柔軟 | // | クエリの特異性 | 一般的 | 特異的 |

注意すべき点

キャッシュミスが追加のオーバーヘッドを伴うレイテンシスパイクを引き起こす

重大度: HIGH

状況: キャッシュミス時に応答が遅く、キャッシュなしよりも遅い

症状:

  • キャッシュミス時に応答が遅い
  • キャッシュヒット率が 50% を下回る
  • キャッシュなしよりもレイテンシが高い

これが問題となる理由: キャッシュチェックがレイテンシを追加します。 キャッシュ書き込みがさらにレイテンシを追加します。 ミス + オーバーヘッド > キャッシュなし。

推奨される修正:

// Optimize for cache misses, not just hits

class OptimizedCache { async queryWithCache(prompt: string): Promise { const cacheKey = this.hash(prompt);

    // Non-blocking cache check
    const cachedPromise = this.cache.get(cacheKey);
    const llmPromise = this.queryLLM(prompt);

    // Race: use cache if available before LLM returns
    const cached = await Promise.race([
        cachedPromise,
        sleep(50).then(() => null)  // 50ms cache timeout
    ]);

    if (cached) {
        // Cancel LLM request if possible
        return cached;
    }

    // Cache miss: continue with LLM
    const response = await llmPromise;

    // Async cache write (don't block response)
    this.cache.set(cacheKey, response).catch(console.error);

    return response;
}

}

// Alternative: Probabilistic caching // Only cache if query matches known high-frequency patterns class SelectiveCache { private patterns: Map<string, number> = new Map();

shouldCache(prompt: string): boolean {
    const pattern = this.extractPattern(prompt);
    const frequency = this.patterns.get(pattern) || 0;

    // Only cache high-frequency patterns
    return frequency > 10;
}

recordQuery(prompt: string): void {
    const pattern = this.extractPattern(prompt);
    this.patterns.set(pattern, (this.patterns.get(pattern) || 0) + 1);
}

}

キャッシュされた応答が時間の経過とともに不正確になる

重大度: HIGH

状況: ユーザーがキャッシュから古い情報や誤った情報を取得する

症状:

  • ユーザーが誤った情報を報告する
  • 回答が現在のデータと一致しない
  • 古い応答に関する苦情

これが問題となる理由: ソースデータが変更されました。 キャッシュの無効化がありません。 動的データに対して TTL が長すぎます。

推奨される修正:

// Implement proper cache invalidation

class InvalidatingCache { // Version-based invalidation private cacheVersion = 1;

getCacheKey(prompt: string): string {
    return `v${this.cacheVersion}:${this.hash(prompt)}`;
}

invalidateAll(): void {
    this.cacheVersion++;
    // Old keys automatically become orphaned
}

// Content-hash invalidation
async setWithContentHash(
    key: string,
    response: string,
    sourceContent: string
): Promise<void> {
    const contentHash = this.hash(sourceContent);
    await this.cache.set(key, {
        response,
        contentHash,
        timestamp: Date.now()
    });
}

async getIfValid(
    key: string,
    currentSourceContent: string
): Promise<string | null> {
    const cached = await this.cache.get(key);
    if (!cached) return null;

    // Check if source content changed
    const currentHash = this.hash(currentSourceContent);
    if (cached.contentHash !== currentHash) {
        await this.cache.delete(key);
        return null;
    }

    return cached.response;
}

// Event-based invalidation
onSourceUpdate(sourceId: string): void {
    // Invalidate all caches that used this source
    this.invalidateByTag(`source:${sourceId}`);
}

}

プレフィックスの変更によりプロンプトキャッシュが機能しない

重要度: MEDIUM

状況: 類似したプロンプトにもかかわらずキャッシュミスが発生する

症状:

  • キャッシュヒット率が期待より低い
  • キャッシュ作成トークンが多く、読み取りが少ない
  • 類似したプロンプトがキャッシュにヒットしない

これが問題となる理由: Anthropic のキャッシュは完全なプレフィックス一致を必要とします。 プレフィックス内のタイムスタンプや動的コンテンツ。 異なるメッセージ順序。

推奨される修正:

// 最適なキャッシュのためにプロンプトを構造化する

class CacheOptimizedPrompts { // 間違い: キャッシュされるプレフィックス内の動的コンテンツ buildPromptBad(query: string): SystemMessage[] { return [ { type: "text", text: You are helpful. Current time: ${new Date()}, // キャッシュを壊す! cache_control: { type: "ephemeral" } } ]; }

// 正しい: 静的なプレフィックス、動的コンテンツは末尾に
buildPromptGood(query: string): SystemMessage[] {
    return [
        {
            type: "text",
            text: STATIC_SYSTEM_PROMPT,  // 決して変化しない
            cache_control: { type: "ephemeral" }
        },
        {
            type: "text",
            text: STATIC_KNOWLEDGE_BASE,  // ほとんど変化しない
            cache_control: { type: "ephemeral" }
        }
        // 動的コンテンツは messages に入れ、system には入れない
    ];
}

// プレフィックスの順序が重要
buildWithConsistentOrder(components: string[]): SystemMessage[] {
    // 一貫した順序にするためにコンポーネントをソートする
    const sorted = [...components].sort();
    return sorted.map((c, i) => ({
        type: "text",
        text: c,
        cache_control: i === sorted.length - 1
            ? { type: "ephemeral" }
            : undefined  // 完全なプレフィックスのみをキャッシュする
    }));
}

}

検証チェック

高温度のレスポンスのキャッシュ

重要度: WARNING

メッセージ: 高温度でのキャッシュ。レスポンスは非決定論的です。

修正アクション: temperature <= 0.5 のレスポンスのみをキャッシュしてください

TTL なしのキャッシュ

重要度: WARNING

メッセージ: TTL なしのキャッシュ。古いデータを無期限に提供する可能性があります。

修正アクション: データの鮮度要件に基づいて適切な TTL を設定してください

キャッシュされるプレフィックス内の動的コンテンツ

重要度: WARNING

メッセージ: キャッシュされるプレフィックス内の動的コンテンツ。キャッシュミスを引き起こします。

修正アクション: 動的コンテンツを cache_control ブロックの外に移動してください

キャッシュメトリクスなし

重要度: INFO

メッセージ: ヒット/ミスの追跡なしのキャッシュ。有効性を測定できません。

修正アクション: キャッシュのヒット/ミスメトリクスとログを追加してください

コラボレーション

委譲トリガー
  • context window|token -> context-window-management (コンテキストの最適化が必要)
  • rag|retrieval -> rag-implementation (取得システムが必要)
  • memory -> conversation-memory (メモリの永続化が必要)
高性能 LLM システム

スキル: prompt-caching、context-window-management、rag-implementation

ワークフロー:

1. Analyze query patterns
2. Implement prompt caching for stable prefixes
3. Add response caching for frequent queries
4. Consider CAG for stable document sets
5. Monitor and optimize hit rates

関連スキル

相性が良い: context-window-management、rag-implementation、conversation-memory

使用する場面

  • ユーザーが言及または示唆する: プロンプトキャッシュ
  • ユーザーが言及または示唆する: プロンプトのキャッシュ
  • ユーザーが言及または示唆する: レスポンスキャッシュ
  • ユーザーが言及または示唆する: cag
  • ユーザーが言及または示唆する: cache augmented

制限事項

  • このスキルは、タスクが上記で説明した範囲に明確に一致する場合にのみ使用してください。
  • 出力を環境固有の検証、テスト、専門家によるレビューの代替として扱わないでください。
  • 必要な入力、権限、安全境界、成功基準が欠けている場合は、停止して確認を求めてください。

コメント