Files
doczyai-pipelines/documentation/PROMPT_CACHING_SYSTEM_PROPOSAL.md
T
Venkatakrishna Reddy Avula 2da639e59b Merged in feature/DAIP2-2314-DAIP2-1687-hybrid (pull request #993)
Feature/DAIP2-2314 DAIP2 1687 hybrid

* remove -files from s3 prefix requirements

* Resolve input paths

* fix: VendorProcessor.process_file returns (df, None) tuple

runner.safe_process_file unpacks the result as (cc_df, dashboard_df), so
returning a single DataFrame caused every vendor/generic file to fail with
"too many values to unpack (expected 2)" — Python iterates DataFrame columns
during unpacking. Vendor pipelines have no dashboard variant; second slot is
None and the existing `dashboard_result is not None` guard in runner.py
already handles it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* DAIP2-2314 + DAIP2-1687: pad DYNAMIC_PRIMARY + DYNAMIC_PRIMARY_ENTITY_CLASSIFICATION over 1024-token cache floor

- Pad DYNAMIC_PRIMARY_INSTRUCTION with three new sections: [SCOPE BOUNDARIES], [SOURCE TEXT INTERPRETATION], [REASONING DISCIPLINE], plus a [WORKED EXAMPLES] block. Estimated tokens: 447 -> 1117 (Sonnet 4.5 1024-min, +93 margin). All additions reinforce existing rules (sibling-field separation, alias mapping, pricing-vs-LOB distinction, contrastive-clause exclusion, exhibit-header binding) — no new directives that could bias extraction.
- Pad DYNAMIC_PRIMARY_ENTITY_CLASSIFICATION_INSTRUCTION with a [FINAL CHECKLIST BEFORE OUTPUT] block. Estimated tokens: 956 -> 1101 (Sonnet 4.5 1024-min, +77 margin). Reinforces the existing 4-step anti-duplication protocol and JSON shape requirements.
- Register both new entries in cache_registry: DYNAMIC_PRIMARY_ENTITY_CLASSIFICATION as INSTRUCTION_PLUS_CONTEXT (caches at warm-up), DYNAMIC_PRIMARY_ENTITIES as CONTEXT (instruction is intentionally short; CONTEXT c…
* black format fix

* Merged dev into feature/DAIP2-2314-DAIP2-1687-hybrid

* fixed raw lob values in base lob field mapping and composite entities fix

* black format fix

* fixed LOB Program output issues

* issue fixes

* remove debugging code

* Updated prompts

* updated additional instructions

* Update Program-->LOB

* LLM-based AD-Program/Product mapping to LOB even when there is a crosswalk

* black format fix

* Merged dev into feature/DAIP2-2314-DAIP2-1687-hybrid

* added logging in prompt call tracking

* added updated logging in prompt call tracking

* aaded min cache token per usage label

* added cache registry for dynamic primary mapping prompt calls

* reolved mapping prompts ambiguities

* black format fix

* Phase 2 modifications added

* reverted phase 2 modifications


Approved-by: Katon Minhas
2026-05-08 15:52:32 +00:00

7.9 KiB

Prompt Caching System Proposal

Branch: feature/DAIP2-2314-expand-caching-for-short-prompts

Goal

Ensure every stable instruction prompt that is intended to be cached is actually cacheable, warmed on the same model used at runtime, and observable in runtime logs.

  1. Introduce a central prompt cache registry.

    Each cacheable prompt should be declared once with:

    • usage_label
    • instruction function
    • model family used at runtime
    • minimum cache token policy
    • runtime call sites
    • whether the prompt also uses context_for_caching

    This avoids the current split where cache warming is in prompt_templates.get_cacheable_instructions() but runtime model choice is scattered through prompt call sites.

  2. Enforce the 1024-token minimum before runtime.

    Prompt caching should not be treated as enabled just because cache=True is passed. At startup, the registry should validate every cached instruction with the same tokenizer/estimate used by reporting. If a prompt is below the minimum, it should either:

    • fail fast in a cache audit mode, or
    • automatically append approved static cache padding/instruction context until it crosses the threshold.

    The padding must be stable and domain-relevant, not dynamic request data.

  3. Warm caches per model, not globally.

    Cache entries are model-specific. The runner currently warms all instructions with sonnet_latest, but SPLIT_SERVICE_TERM runs with haiku_latest. The cache warming layer should warm (usage_label, resolved_model_id) pairs derived from the registry.

  4. Only mark supported models as cacheable.

    _supports_prompt_cache() currently excludes Haiku. If Haiku prompt caching is not supported in this Bedrock setup, Haiku prompts should not be registered as cached. Either move those prompt calls to sonnet_latest when caching matters, or keep them uncached and report them as intentionally uncached.

  5. Keep static instruction caching separate from dynamic context caching.

    Instruction prompts can be cached predictably. context_for_caching is different because it changes by contract, exhibit, or page. It should be tracked as a separate cache class:

    • instruction_cache: expected to read after warm-up
    • context_cache: expected to create/read per repeated context

    This prevents context variability from making instruction caching look broken.

  6. Add a cache contract test.

    A local test should inspect the built request body for every registered prompt and assert:

    • the instruction block has cache_control
    • the resolved model supports caching
    • the static instruction token estimate is at least 1024
    • warm-up model equals runtime model
  7. Upgrade runtime reporting.

    Add these fields to prompt-call logs:

    • resolved_model_id
    • cache_policy: instruction, context, instruction+context, none
    • instruction_cache_eligible
    • context_cache_eligible
    • cache_miss_reason

    This makes root cause visible without manual investigation.

Prompt Application Report

Apply Instruction Caching, Already Over 1024 Tokens

These should remain registered and warmed. They are good candidates for strict cache contract tests.

Prompt Estimated Instruction Tokens Action
OUTLIER_BREAKOUT 2483 Keep cached
METHODOLOGY_BREAKOUT 1927 Keep cached
SPLIT_SERVICE_TERM 1600 Cache only if runtime model supports caching; currently runs on Haiku
DYNAMIC_ASSIGNMENT 1578 Keep cached
CARVEOUT_CHECK 1498 Keep cached
SERVICE_ENRICHMENT 1459 Keep cached
REIMBURSEMENT_PRIMARY 1390 Keep cached
EXHIBIT_LEVEL 1108 Keep cached

Apply Instruction Caching After Padding/Expansion

These are wired or partially wired but below the 1024-token minimum. They should be padded or expanded with stable domain guidance before being considered cached.

Prompt Estimated Instruction Tokens Tokens Needed Action
fill_bill_type 968 56 Add small static guidance
DYNAMIC_CODE_ASSIGNMENT 966 58 Add small static guidance
CHECK_PROVIDER_NAME_MATCH 957 67 Add small static guidance
GROUPER_BREAKOUT 939 85 Add small static guidance
EXHIBIT_HEADER 922 102 Add static header examples/rules
LESSER_OF_DISTRIBUTION 914 110 Add static decision examples
LESSER_OF_CHECK 900 124 Add static classification examples
CODE_EXPLICIT 871 153 Add static code-system rules
REIMB_DATES_ASSIGNMENT 803 221 Add date extraction examples
DYNAMIC_PRIMARY 441 583 Expand instruction substantially
SPLIT_REIMB_DATES 410 614 Expand instruction substantially
prompt_lob_relationship 408 616 Move field prompt into instruction or add static LOB rules
code_implicit_arbitration 391 633 Expand arbitration rules
AARETE_DERIVED_PAYER_NAME 372 652 Expand payer naming rules
FEE_SCHEDULE_BREAKOUT 352 672 Expand fee schedule rules
code_implicit_special 329 695 Expand special code rules
DATE_FIX 322 702 Expand date normalization rules
SPECIAL_CASE_ASSIGNMENT 251 773 Expand special case rules
DERIVED_TERM_DATE 247 777 Expand term date rules
code_last_check 179 845 Expand or leave uncached if low value
EXTRACT_AMENDMENT_NUM_FROM_FILENAME 152 872 Expand or leave uncached if low value
EXHIBIT_HEADER_DEDUP 35 989 Do not cache unless redesigned

Wire for Caching or Mark Intentionally Uncached

These showed runtime volume but no instruction function match in the audit. They need explicit registry decisions.

Prompt Runtime Finding Action
prompt_hsc_single_field 109 calls, cache_enabled=False, large dynamic prompt Split stable HSC instructions from dynamic chunk and cache the instruction
SPECIAL_CASE_BREAKOUT 6 calls, no instruction cache Wire only if repeated volume justifies expansion
code_implicit_rag Cached in API, audit alias missing Add registry alias to the actual instruction function
prompt_provider_info Cached in API, audit alias missing Add registry alias to TIN_NPI_TEMPLATE_INSTRUCTION or rename usage label
validate_reimbursements_for_llm Cached in API, audit alias missing Add registry alias to VALIDATE_REIMBURSEMENTS_INSTRUCTION

Immediate Fixes

  1. Change SPLIT_SERVICE_TERM to use a cache-supported model or mark it intentionally uncached. Current behavior is misleading: cache=True is passed, but no Bedrock cache tokens are recorded.

  2. Add a registry alias map for usage labels that do not match instruction names:

    • code_implicit_rag -> CODE_IMPLICIT
    • prompt_provider_info -> TIN_NPI_TEMPLATE
    • validate_reimbursements_for_llm -> VALIDATE_REIMBURSEMENTS
    • prompt_lob_relationship -> its real instruction function
  3. Expand the near-threshold instructions first because they need the least work and have current evidence of API cache reads:

    • fill_bill_type
    • DYNAMIC_CODE_ASSIGNMENT
    • CHECK_PROVIDER_NAME_MATCH
    • GROUPER_BREAKOUT
    • EXHIBIT_HEADER
    • LESSER_OF_DISTRIBUTION
    • LESSER_OF_CHECK
    • CODE_EXPLICIT
  4. Redesign prompt_hsc_single_field into (instruction, prompt) form. It is high-volume and currently sends all prompt text dynamically.

Expected Behavior After Fix

For instruction-only prompts, after warm-up the API should report cache reads on normal calls. The cached percentage will still not be 100% of total billed input because the dynamic user prompt remains uncached. The correct target is:

  • cache_creation_tokens only during warm-up or first uncached use
  • cache_read_tokens > 0 on every eligible runtime call
  • cache_miss_reason empty for registered instruction cache prompts

For context-cached prompts, 100% cache reads should not be expected unless the same context block repeats. The report should evaluate those separately.