feat(llm): cache hint TTL, breakpoint cap, and tool placement (#26779)
This commit is contained in:
parent
fed716ada5
commit
77e6c0d329
12 changed files with 555 additions and 39 deletions
|
|
@ -1,20 +1,37 @@
|
|||
import { Schema } from "effect"
|
||||
import type { CacheHint } from "../../schema"
|
||||
import { newBreakpoints, ttlBucket, type Breakpoints } from "./cache"
|
||||
|
||||
// Bedrock cache markers are positional: emit a `cachePoint` block immediately
|
||||
// after the content the caller wants treated as a cacheable prefix.
|
||||
// after the content the caller wants treated as a cacheable prefix. Bedrock
|
||||
// accepts optional `ttl: "5m" | "1h"` on cachePoint, mirroring Anthropic.
|
||||
export const CachePointBlock = Schema.Struct({
|
||||
cachePoint: Schema.Struct({ type: Schema.tag("default") }),
|
||||
cachePoint: Schema.Struct({
|
||||
type: Schema.tag("default"),
|
||||
ttl: Schema.optional(Schema.Literals(["5m", "1h"])),
|
||||
}),
|
||||
})
|
||||
export type CachePointBlock = Schema.Schema.Type<typeof CachePointBlock>
|
||||
|
||||
// Bedrock recently added optional `ttl: "5m" | "1h"` on cachePoint. Map
|
||||
// `CacheHint.ttlSeconds` here once a recorded cassette validates the wire shape.
|
||||
const DEFAULT: CachePointBlock = { cachePoint: { type: "default" } }
|
||||
// Bedrock-Claude enforces the same 4-breakpoint cap as the Anthropic Messages
|
||||
// API. Callers pass a shared counter through every `block()` call site so the
|
||||
// budget is respected across `system`, `messages`, and `tools`.
|
||||
export const BEDROCK_BREAKPOINT_CAP = 4
|
||||
|
||||
export const block = (cache: CacheHint | undefined): CachePointBlock | undefined => {
|
||||
export type { Breakpoints } from "./cache"
|
||||
export const breakpoints = () => newBreakpoints(BEDROCK_BREAKPOINT_CAP)
|
||||
|
||||
const DEFAULT_5M: CachePointBlock = { cachePoint: { type: "default" } }
|
||||
const DEFAULT_1H: CachePointBlock = { cachePoint: { type: "default", ttl: "1h" } }
|
||||
|
||||
export const block = (breakpoints: Breakpoints, cache: CacheHint | undefined): CachePointBlock | undefined => {
|
||||
if (cache?.type !== "ephemeral" && cache?.type !== "persistent") return undefined
|
||||
return DEFAULT
|
||||
if (breakpoints.remaining <= 0) {
|
||||
breakpoints.dropped += 1
|
||||
return undefined
|
||||
}
|
||||
breakpoints.remaining -= 1
|
||||
return ttlBucket(cache.ttlSeconds) === "1h" ? DEFAULT_1H : DEFAULT_5M
|
||||
}
|
||||
|
||||
export * as BedrockCache from "./bedrock-cache"
|
||||
|
|
|
|||
16
packages/llm/src/protocols/utils/cache.ts
Normal file
16
packages/llm/src/protocols/utils/cache.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// Shared helpers for provider cache-marker lowering. Anthropic and Bedrock
|
||||
// both enforce a 4-breakpoint cap per request and accept the same `5m`/`1h`
|
||||
// TTL buckets, so the counter and TTL mapping live here.
|
||||
|
||||
export interface Breakpoints {
|
||||
remaining: number
|
||||
dropped: number
|
||||
}
|
||||
|
||||
export const newBreakpoints = (cap: number): Breakpoints => ({ remaining: cap, dropped: 0 })
|
||||
|
||||
// Returns `"1h"` for any `ttlSeconds >= 3600`, otherwise `undefined` (the
|
||||
// provider default 5m). Anthropic & Bedrock both treat anything shorter than
|
||||
// an hour as 5m.
|
||||
export const ttlBucket = (ttlSeconds: number | undefined): "1h" | undefined =>
|
||||
ttlSeconds !== undefined && ttlSeconds >= 3600 ? "1h" : undefined
|
||||
Loading…
Add table
Add a link
Reference in a new issue