prompt-caching-and-how-to-think-about-it

v2v3 · +51 −37 · View latest

⋯ 300 unchanged lines
      }
      .visual-stage {
        display: grid;
        gap: 12px;
        min-width: 0;
      }
      .visual-split {
        display: grid;
        grid-template-columns: minmax(130px, 0.8fr) minmax(0, 1.35fr);
        grid-template-columns: minmax(0, 1fr);
        gap: 10px;
        align-items: stretch;
      }
⋯ 103 unchanged lines
      .segment.write {
        background: var(--write-bg);
        color: #6f4d06;
        box-shadow: inset 0 0 0 2px rgb(217 154 33 / 38%);
      }
      .segment.read {
        background: var(--read-bg);
        color: #165d43;
        box-shadow: inset 0 0 0 2px rgb(39 132 95 / 34%);
      }
      .segment.miss {
⋯ 29 unchanged lines
      .hash-row {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: 6px;
        margin: 12px 0 8px;
        margin: 0;
      }
      .hash-row:empty {
        display: none;
      }
      .hash-pill {
        padding: 6px 8px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-height: 26px;
        padding: 4px 9px;
        border-radius: 999px;
        background: #f0eee7;
        color: #2d2b27;
        font-size: 0.68rem;
        font-weight: 700;
        line-height: 1.1;
        white-space: nowrap;
      }
      .hash-pill.write {
        background: var(--write-bg);
        color: #6f4d06;
        box-shadow: inset 0 0 0 1px rgb(217 154 33 / 30%);
      }
      .hash-pill.read {
        background: var(--read-bg);
        color: #165d43;
        box-shadow: inset 0 0 0 1px rgb(39 132 95 / 28%);
      }
      .hash-pill.miss {
        background: var(--miss-bg);
        color: #793125;
      }
      .visual-note {
        min-height: 36px;
        margin: 0 0 12px;
        margin: 0;
        color: #3f3b34;
        font-size: 0.78rem;
      }
      .controls {
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
        padding-top: 11px;
        padding-top: 12px;
        border-top: 1px solid var(--soft-line);
      }
⋯ 32 unchanged lines
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 6px 8px;
        margin-top: 11px;
        margin-top: 0;
        color: var(--muted);
        font-size: 0.66rem;
      }
⋯ 90 unchanged lines
        }
        .visual-column {
          position: static;
          position: sticky;
          top: 0;
          z-index: 20;
          order: -1;
          margin: 0 0 22px;
        }
        .visual-panel {
          position: sticky;
          top: 0;
          z-index: 10;
          max-height: 34vh;
          overflow-y: auto;
          position: static;
          border-radius: 0 0 var(--radius) var(--radius);
          margin: 0 -20px 22px;
          margin: 0 -20px;
          border-left: 0;
          border-right: 0;
        }
        .visual-split {
          grid-template-columns: minmax(120px, 0.9fr) minmax(0, 1.4fr);
          grid-template-columns: minmax(0, 1fr);
        }
        .visual-top {
⋯ 36 unchanged lines
        }
        .visual-split {
          grid-template-columns: minmax(82px, 1fr) minmax(0, 2fr);
          grid-template-columns: minmax(0, 1fr);
          gap: 8px;
        }
⋯ 7 unchanged lines
        }
        .chat-box {
          max-height: 96px;
          overflow-y: auto;
          max-height: none;
          overflow: visible;
        }
        .bubble {
⋯ 347 unchanged lines
          subtitle: "No cache yet. Just a request with a beginning.",
          note: "Prompt caching becomes easier once you look at the request as a sequence.",
          hash: [{ text: "prefix: none", tone: "" }],
          chat: [
            ["user", "Help me plan a launch."],
            ["assistant", "Sure. What are you launching?"],
          ],
          chat: [["user", "Help me plan a launch."]],
          lanes: [
            {
              label: "Request",
⋯ 59 unchanged lines
          subtitle: "Tools come before the system prompt in the prefix.",
          note: "Same system prompt, different request shape, different cache.",
          hash: [
            { text: "before: hash A", tone: "read" },
            { text: "after: hash B", tone: "miss" },
            { text: "existing shape: cache A", tone: "read" },
            { text: "changed shape: cache B", tone: "miss" },
          ],
          chat: [
            ["user", "Use the docs if you need them."],
            ["assistant", "I can search the docs first."],
          ],
          lanes: [
            {
              label: "Before tool",
              label: "Existing shape",
              marker: 55,
              segments: [
                ["system read", "system prompt", 55, "system"],
                ["message", "messages", 45, "message"],
              ],
            },
            {
              label: "After tool",
              label: "Changed shape",
              marker: 68,
              segments: [
                ["tool", "tool", 20, "tool"],
⋯ 9 unchanged lines
          subtitle: "Schemas can create a separate cache lane.",
          note: "Normal chat and JSON-shaped calls may both be correct and still use different caches.",
          hash: [
            { text: "chat: cache A", tone: "read" },
            { text: "json: cache C", tone: "write" },
            { text: "existing shape: cache A", tone: "read" },
            { text: "changed shape: cache C", tone: "write" },
          ],
          chat: [["user", "Return the plan as JSON this time."]],
          lanes: [
            {
              label: "Normal chat lane",
              label: "Existing shape",
              marker: 54,
              segments: [
                ["system read", "system prompt", 54, "system"],
                ["message", "messages", 46, "message"],
              ],
            },
            {
              label: "Structured lane",
              label: "Changed shape",
              marker: 76,
              segments: [
                ["schema", "schema", 24, "schema"],
⋯ 16 unchanged lines
          lanes: [
            {
              label: "Large app prompt",
              marker: 86,
              marker: 76,
              segments: [
                ["system read", "huge system prompt", 86, "system"],
                ["message", "messages", 14, "message"],
                ["system read", "huge system prompt", 76, "system"],
                ["message", "user", 10, "message"],
                ["message", "assistant", 14, "message"],
              ],
            },
          ],
⋯ 20 unchanged lines
          title: "Marker placement",
          subtitle: "Cache stable content. Stop before changing content.",
          note: "Toggle the marker. The good version stops before the changing task.",
          hash: [
            { text: "good: read X", tone: "read" },
            { text: "bad: write Y/Z", tone: "write" },
          ],
          hash: [],
          chat: [
            ["user", "Use the conversation so far."],
            ["assistant", "Then run a fresh task instruction."],
⋯ 312 unchanged lines
        });
        if (scene.markerToggle) {
          const result = document.createElement("span");
          result.className = `hash-pill ${goodMarker ? "read" : "write"}`;
          result.textContent = goodMarker ? "good: read X" : "bad: write Y/Z";
          hashRow.appendChild(result);
          const state = document.createElement("span");
          state.className = `hash-pill ${goodMarker ? "read" : "write"}`;
          state.textContent = goodMarker ? "stable prefix" : "moving prefix";
⋯ 61 unchanged lines
      }
      window.addEventListener("scroll", queueSceneSync, { passive: true });
      window.addEventListener("resize", queueSceneSync);
      window.addEventListener("resize", () => {
        queueSceneSync();
      });
      render(activeSceneId);
      syncSceneToHeading();
    </script>
  </body>
</html>