Phase 3.5 extraction & assembly

Bucketed 0/1 knapsack DP with numpy vectorization and greedy fallback for packing scored memories under TokenBudget.usable_budget (ADR-0069).

Milestone 3.5.C.4 — Packer v2 (Bounded DP Knapsack, Not Pure Greedy)

Status: Completed Goal: Track C — Context Assembly Engine
Phase: 3.5 — Extraction & Context Assembly
Estimated effort: 2 days
Track: Track C — Context Assembly Engine
Depends on: 3.5.C.3 (memory-side gate; packer score is interim — see ADR)
ADR: ADR-0069


Why This Milestone Exists

Greedy-by-score packing can strand usable budget when a large high-score memory leaves a remainder that no next candidate fits, while several smaller lower-score memories would collectively fill the budget better. A bounded 0/1 knapsack DP recovers that value within a packing latency budget.


Non-Goals

  • Changing the context assembly proto (MemoryUsed / AssembleContextResponse)
  • Full online/streaming repacking
  • gRPC ContextAssemblyService wiring (3.5.C.6)
  • Extending memory HTTP to return real composite_score (follow-up; interim score used instead)

File layout (as shipped)

services/context/app/packer.py     # ContextPacker, ScoredMemory, PackedMemories
services/context/app/scoring.py    # interim packer score (NOT memory composite_score)
services/context/app/pipeline.py   # pack_retrieval() thin glue
services/context/app/config.py     # IBEX_CONTEXT_PACKER_DP_CELL_CEILING, MAX_CONSECUTIVE_SKIPS

Settings / env:

  • IBEX_CONTEXT_PACKER_DP_CELL_CEILING (default 70 * 6251)
  • IBEX_CONTEXT_PACKER_MAX_CONSECUTIVE_SKIPS (default 5)

Token costs use estimate_tokens + capability-catalog family policy (ADR-0067).

Interim score: 0.85 * similarity + 0.15 * confidence. Memory’s full composite (recency / usefulness / frequency) is not on the HTTP wire yet — see ADR-0069.


Design

  • Bucket size 16; numpy DP with correct zero-weight / oversized-weight handling; exact-token repair after selection
  • Fallback to greedy when n * (buckets+1) exceeds the cell ceiling
  • Output ordered by descending interim score, then memory_id
  • PackedMemories.path is "dp" or "greedy" for metrics

Success signals

  • DP packer unit-tested against brute-force oracle (aligned bucket sizes) and the adversarial stranded-budget case (DP ≥90% util, greedy <65%)
  • P99 packing latency <5ms at n=70 (CI unit latency test)
  • Fallback-to-greedy path tested via lowered cell ceiling
  • was_budget_reached / skip counts covered; ADR-0069 accepted
  • No proto or memory HTTP schema changes in this milestone
Edit on GitHub

Last updated on