Alejandro Rioja.
AI Agents Operations

التخزين المؤقت للموجّهات عبر Claude API: قلّل تكاليف الإدخال دون تغيير النماذج

Alejandro Rioja
Alejandro Rioja
8 د قراءة
TL;DR

يخفّض التخزين المؤقت للموجّهات تكلفة المدخلات الكبيرة الثابتة — موجّه النظام لديك، وتعريفات الأدوات، وأمثلة few-shot — إلى ما يقارب 10% من سعر الإدخال المعتاد في الطلبات المتكررة. آلية العمل هي تطابق البادئة: ضع علامة cache_control في نهاية محتواك الثابت وأبقِ كل ما هو متغيّر بعدها. والخطأ الذي يقضي على معدلات إصابة التخزين المؤقت هو السماح بتسرّب طابع زمني أو UUID إلى داخل البادئة.

نشرة بريدية مجانية

كل أربعاء. أكثر من 28,400 مشترك. بدون حشو.

Table of contents

Open Table of contents

ما الذي يفعله التخزين المؤقت للموجّهات فعليًا

كل استدعاء لواجهة Claude API يرسل رموزًا (tokens). بدون التخزين المؤقت، كل رمز في طلبك — موجّه النظام، وتعريفات الأدوات، وأمثلة few-shot، ورسالة المستخدم — يُحتسب بسعر الإدخال المعتاد. أما مع التخزين المؤقت، فإن بادئةً من تلك الرموز تُخزَّن على خوادم Anthropic بعد الطلب الأول. وفي الطلبات اللاحقة التي تشترك في تلك البادئة بالضبط، تدفع سعر قراءة من التخزين المؤقت بدلًا من إعادة معالجتها من الصفر.

الفارق في التكلفة حقيقي:

بمجرد تجاوزك نقطة التعادل — وهو ما يحدث سريعًا في أي وكيل يعمل أكثر من بضع مرات يوميًا — تصبح كل إصابة إضافية للتخزين المؤقت خصمًا بنحو 90% على تلك الرموز.

قاعدة تطابق البادئة

هذه هي القاعدة الوحيدة التي يتبعها كل ما عداها: مفتاح التخزين المؤقت هو تطابق بادئة لموجّهك المُصيَّر (rendered).

تخزّن خوادم Anthropic المحتوى المُصيَّر من بداية موجّهك حتى علامة cache_control. ولكي تتحقق إصابة للتخزين المؤقت في الطلب التالي، يجب أن يكون كل رمز من بداية الموجّه حتى تلك العلامة مطابقًا — بايتًا ببايت.

ترتيب التصيير لتطابق البادئة هو: tools ← system ← messages. فمصفوفة الأدوات tools تُجزَّأ (hashed) أولًا، ثم كتلة system، ثم messages بالترتيب.

ما يعنيه هذا عمليًا: يجب أن يأتي المحتوى الثابت أولًا. فإذا أشار موجّه النظام لديك إلى أي شيء ديناميكي — تاريخ حالي، أو معرّف مستخدم، أو معرّف تتبّع لطلب — وظهر قبل علامة cache_control، فإن التخزين المؤقت سيخفق في كل طلب لأن البادئة تتغير باستمرار.

على ماذا تضع علامة التخزين المؤقت

أكثر الأهداف تأثيرًا هي:

1. موجّه النظام لديك

عادةً ما تكون موجّهات النظام أكبر كتلة ثابتة. شخصية وكيل مفصّلة، وقائمة بقواعد سلوكية، ومجموعة من تعليمات تنسيق المخرجات — كل هذا متطابق في كل استدعاء للوكيل نفسه. ضع علامةً عليه:

typescript
import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();

const response = await client.messages.create({
  model: "claude-opus-4-8",
  max_tokens: 1024,
  system: [
    {
      type: "text",
      text: `You are a content operations agent for alejandrorioja.com.
Your job is to draft blog posts in Alejandro's voice: direct, practitioner, 
first-person, numbered lists, honest caveats. No hedging. No filler. 
Every section must earn its place.

[... 2000 more tokens of stable instructions ...]`,
      cache_control: { type: "ephemeral" },
    },
  ],
  messages: [
    {
      role: "user",
      content: "Draft a post about prompt caching.",
    },
  ],
});

تخبر cache_control: { type: "ephemeral" } الموضوعة على كتلة system نموذج Claude بأن يخزّن مؤقتًا كل شيء حتى تلك الكتلة وبما يشملها. مصفوفة messages متغيّرة — مختلفة في كل طلب — وتبقى خارج حدود التخزين المؤقت.

2. تعريفات الأدوات

إذا كان وكيلك يستخدم أدوات، فقد تكون تلك التعريفات ضخمة. مخطّط أداة موثَّق جيدًا بوصفه وأسماء معاملاته وقيم enum الخاصة به قد يبلغ 500–1,000 رمز لكل أداة. ومع 5 أدوات، يصل ذلك إلى 5,000 رمز تدفع ثمن إعادة معالجتها في كل استدعاء:

typescript
const response = await client.messages.create({
  model: "claude-opus-4-8",
  max_tokens: 1024,
  tools: [
    {
      name: "search_airtable",
      description: "Search the Airtable content queue...",
      input_schema: { type: "object", properties: { query: { type: "string" } } },
    },
    // ... more tools ...
    {
      name: "post_to_kit",
      description: "Schedule a broadcast via the Kit API...",
      input_schema: { /* ... */ },
      // Mark the last tool to cache the entire tools array
    } as Anthropic.Tool & { cache_control: { type: "ephemeral" } },
  ],
  system: "...",
  messages: [...],
});

ضع العلامة على آخر أداة في المصفوفة. سيغطي تطابق البادئة مصفوفة الأدوات كاملةً انطلاقًا من تلك النقطة.

3. أمثلة few-shot ضمن messages

إذا مرّرت أمثلة few-shot ثابتة كرسائل مبكّرة في مصفوفة messages، فيمكن تخزينها مؤقتًا أيضًا. رتّبها كأول N رسالة وضع علامةً على آخر دور مثال:

typescript
const messages: Anthropic.MessageParam[] = [
  {
    role: "user",
    content: [
      {
        type: "text",
        text: "Here are examples of posts in my voice:\n\n[Example 1...]\n\n[Example 2...]",
        cache_control: { type: "ephemeral" },
      } as Anthropic.TextBlockParam & { cache_control: { type: "ephemeral" } },
    ],
  },
  {
    role: "assistant",
    content: "Understood. I'll follow that voice.",
  },
  // The actual user turn follows — this is volatile, no cache marker
  {
    role: "user",
    content: actualUserRequest,
  },
];

ما الذي يجب ألّا تُخزّنه مؤقتًا (العوامل الصامتة المُبطِلة)

هذه هي الأشياء التي تبدو ثابتة لكنها ليست كذلك — وستقضي على معدل إصابتك بصمت. لن تحذّرك الواجهة. بل سترى فقط cache_creation_input_tokens في كل طلب وتتساءل عن السبب.

الطوابع الزمنية في موجّه النظام. الخطأ الأكثر شيوعًا على الإطلاق:

typescript
// This invalidates the cache on every request
const system = `You are an agent. Current time: ${new Date().toISOString()}`;

انقل الطوابع الزمنية إلى رسالة المستخدم حيث ينبغي أن تكون:

typescript
// Stable system prompt — cacheable
const system = `You are an agent. Use the current time provided by the user.`;

// Volatile user message — not cached
const userMessage = `Current time: ${new Date().toISOString()}. Run the daily brief.`;

معرّفات UUID العشوائية ومعرّفات التتبّع. المشكلة ذاتها. إذا حقنت معرّف تتبّع داخل كتلة system لأغراض التسجيل، فسيحصل كل طلب على بادئة جديدة.

التسلسل غير الحتمي لـ JSON. إذا حوّلت كائنًا إلى تسلسل داخل موجّه النظام ولم يكن ترتيب المفاتيح مضمونًا، فقد تختلف السلسلة المُصيَّرة حتى عندما تكون البيانات الأساسية نفسها. حوّل إلى تسلسل بترتيب مفاتيح ثابت أو استخدم سلسلة قالب (template string).

اختيار few-shot الديناميكي. إذا كنت تختار أمثلة few-shot بناءً على الاستعلام الحالي وتضعها في البادئة المُخزَّنة مؤقتًا، فقد جعلت البادئة “الثابتة” معتمدةً على الاستعلام. إما أن تلتزم بأمثلة ثابتة لطبقة التخزين المؤقت، أو أن تنقل الأمثلة الديناميكية إلى دور الرسالة غير المُخزَّن مؤقتًا.

التحقق من معدل إصابة التخزين المؤقت لديك

تتضمن كل استجابة بيانات وصفية للاستخدام (usage metadata). تحقّق منها:

typescript
const response = await client.messages.create({ /* ... */ });

console.log({
  inputTokens: response.usage.input_tokens,
  cacheRead: response.usage.cache_read_input_tokens,
  cacheWrite: response.usage.cache_creation_input_tokens,
  outputTokens: response.usage.output_tokens,
});

في الطلب الأول: ستكون قيمة cache_creation_input_tokens غير صفرية، وقيمة cache_read_input_tokens صفرًا. هذه هي عملية الكتابة.

عند إصابة التخزين المؤقت: ستكون قيمة cache_read_input_tokens غير صفرية، وقيمة cache_creation_input_tokens صفرًا. هذه هي عملية القراءة.

إذا كنت ترى cache_creation_input_tokens في كل طلب، فإن بادئتك تتغير. أضف عبارة تسجيل تطبع أول 200 حرف من موجّه النظام المُصيَّر قبل كل استدعاء — سيقفز طابع زمني متغيّر إلى عينيك فورًا.

TTL مدته ساعة واحدة: متى يستحق تكلفة الكتابة الإضافية

قيمة TTL الافتراضية هي 5 دقائق. إذا كان وكيلك يعمل بتكرار منخفض — أقل من مرة كل 5 دقائق — فستدفع تكاليف كتابة إلى التخزين المؤقت في معظم الطلبات دون الحصول على قراءات.

typescript
// Opt into a 1-hour TTL
cache_control: { type: "ephemeral", ttl: "1h" }

تبلغ تكلفة الكتابة لمدة ساعة نحو 2× سعر الإدخال الأساسي بدلًا من 1.25×. الحساب: إذا كنت تصيب التخزين المؤقت 3 مرات أو أكثر في الساعة، فإن TTL مدته ساعة واحدة يوفّر المال. أما إذا كان وكيلك يعمل مرةً واحدة يوميًا (مثل موجزي اليومي)، فحتى TTL مدته ساعة واحدة لن ينفع — ستدفع تكاليف كتابة في كل مرة. في تلك الحالة، تكون فائدة التخزين المؤقت محدودة ما لم يكن موجّه النظام ضخمًا.

وكيل موجزي اليومي لديه موجّه نظام مؤلف من 3,000 رمز لكنه يعمل مرةً واحدة يوميًا. التخزين المؤقت لا يفيد. أما وكيل النشرة الإخبارية فيعمل عشرات المرات في الجلسة أثناء الصياغة — والتخزين المؤقت يوفّر بشكل كبير.

التسخين المسبق: جعل الطلب الأول رخيصًا

إذا كنت تعلم أن ذروة في حركة المرور قادمة — مهمة مجمّعة، أو إطلاق واجهة API — فيمكنك تسخين التخزين المؤقت مسبقًا بطلب وهمي منخفض التكلفة:

typescript
// Pre-warm: write the cache at near-zero output cost
await client.messages.create({
  model: "claude-opus-4-8",
  max_tokens: 1, // minimal output
  system: [{ type: "text", text: stableSystemPrompt, cache_control: { type: "ephemeral" } }],
  messages: [{ role: "user", content: "ping" }],
});

// Now the real requests read from cache

هذا مفيد غالبًا في المعالجة المجمّعة حيث تُطلق العديد من الطلبات المتوازية وتريد أن يصيب كل منها تخزينًا مؤقتًا ساخنًا بدلًا من التسابق على كتابته.

التخزين المؤقت للموجّهات في الحلقات الوكيلية (agentic loops)

في حلقة وكيلية متعددة الأدوار، ينمو سجل المحادثة في كل دور. والتخزين المؤقت ذكي بما يكفي للتعامل مع هذا: فهو يستخدم نافذة استرجاع (lookback window) بحجم 20 كتلة، باحثًا عن أطول بادئة مطابقة ضمن آخر 20 كتلة محتوى.

النتيجة العملية: أبقِ محتواك الثابت (موجّه النظام، تعريفات الأدوات) مثبّتًا في الأعلى. سجل المحادثة المتنامي في نهاية مصفوفة messages لن يكسر تطابق البادئة للكتل الثابتة — فهي تأتي قبل المحتوى المتغيّر، وتطابق البادئة يبدأ من الأعلى.

عمليًا، يرتّب وكلائي الأدوار هكذا:

code
System (cached) → Tools (cached) → Few-shot (cached) → Turn 1 → Turn 2 → ... → Current turn

يغطي التخزين المؤقت كل شيء حتى علامة few-shot. سجل الأدوار المتنامي بعدها يُعاد معالجته في كل مرة، لكن لا بأس بذلك — فتلك الرموز خاصة بالجلسة وصغيرة مقارنةً بالبادئة الثابتة.

كيف يبدو ذلك على الفاتورة

لنأخذ وكيلًا عالي التكرار: 100 استدعاء يوميًا، وموجّه نظام مؤلف من 4,000 رمز، وتسعير Sonnet.

بدون التخزين المؤقت:

مع التخزين المؤقت (TTL مدته 5 دقائق، بافتراض 50 استدعاءً/ساعة في الذروة):

هذا انخفاض بنحو 90% على رموز الإدخال تلك. وعلى نطاق أوسع — 1,000 استدعاء يوميًا — يتضاعف الفارق أكثر. وهذا فوق أي توفير من توجيه النموذج المستمد من حساب Haiku مقابل Sonnet: التخزين المؤقت يعمل في كل فئة.

خلاصة المشغّل

التخزين المؤقت للموجّهات هو أسهل تحسين للتكلفة في Claude API: حقل إضافي واحد على كتل المحتوى التي تكتبها أصلًا. القيد الوحيد هو الانضباط في ثبات البادئة — لا شيء ديناميكي قبل علامة التخزين المؤقت. فإذا استطعت إبقاء موجّه نظامك وأدواتك وأي أمثلة ثابتة خاليةً من المحتوى المتغيّر، فستدفع نحو 10% من تكلفة الإدخال المعتادة في كل إصابة للتخزين المؤقت. وبالنسبة للوكلاء عاليي التكرار ذوي الموجّهات الكبيرة الثابتة، يُعَدّ هذا رافعةً أكبر من تغيير فئات النماذج.


ذات صلة: حساب تكلفة وكلاء الذكاء الاصطناعي: متى يتفوّق Haiku على Sonnet · الوكلاء المُفعَّلون بالأحداث مقابل المُجدوَلين · أدوات الذكاء الاصطناعي الخمس التي أستخدمها فعليًا لإدارة عملي

تابع القراءة

احصل على دليل الذكاء الاصطناعي في صندوق بريدك

كل أربعاء. أكثر من 28,400 مشترك. بدون حشو.

↵ لعرض كل النتائج esc esc للإغلاق