feat: preserve pages and compress context
This commit is contained in:
@@ -147,6 +147,14 @@ export const conversationMessageSchema = z
|
||||
createdAt: z.number().int().nonnegative(),
|
||||
state: z.enum(['streaming', 'complete', 'error']),
|
||||
status: z.string().max(4_000).optional(),
|
||||
contextCompression: z
|
||||
.object({
|
||||
state: z.enum(['compressing', 'completed', 'failed']),
|
||||
estimatedBeforeTokens: z.number().int().nonnegative(),
|
||||
estimatedAfterTokens: z.number().int().nonnegative().optional()
|
||||
})
|
||||
.strict()
|
||||
.optional(),
|
||||
tools: z.array(conversationToolActivitySchema).max(100).optional(),
|
||||
sources: z.array(z.string().max(8_192)).max(100).optional(),
|
||||
sourceReferences: z
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
export const minimumModelContextWindowTokens = 32_000
|
||||
export const maximumModelContextWindowTokens = 10_000_000
|
||||
export const contextOutputAndSafetyTokens = 12_000
|
||||
export const estimatedContextRequestOverheadTokens = 4_000
|
||||
|
||||
export type ContextWindowMessage = {
|
||||
role: 'user' | 'assistant'
|
||||
content: string
|
||||
}
|
||||
|
||||
export function estimateTextTokens(value: string): number {
|
||||
let asciiCharacters = 0
|
||||
let nonAsciiCharacters = 0
|
||||
for (const character of value) {
|
||||
if (character.codePointAt(0)! <= 0x7f) {
|
||||
asciiCharacters += 1
|
||||
} else {
|
||||
nonAsciiCharacters += 1
|
||||
}
|
||||
}
|
||||
return Math.max(
|
||||
1,
|
||||
Math.ceil(asciiCharacters / 4 + nonAsciiCharacters)
|
||||
)
|
||||
}
|
||||
|
||||
export function estimateMessagesTokens(
|
||||
messages: readonly ContextWindowMessage[]
|
||||
): number {
|
||||
return messages.reduce(
|
||||
(total, message) => total + estimateTextTokens(message.content) + 4,
|
||||
0
|
||||
)
|
||||
}
|
||||
|
||||
export function estimateContextInputTokens(input: {
|
||||
history: readonly ContextWindowMessage[]
|
||||
prompt: string
|
||||
summaryTokens?: number
|
||||
}): number {
|
||||
return (
|
||||
estimateMessagesTokens(input.history) +
|
||||
estimateTextTokens(input.prompt) +
|
||||
(input.summaryTokens ?? 0) +
|
||||
estimatedContextRequestOverheadTokens
|
||||
)
|
||||
}
|
||||
|
||||
export function getEffectiveContextTriggerTokens(input: {
|
||||
triggerTokens: number
|
||||
contextWindowTokens?: number
|
||||
}): number {
|
||||
if (input.contextWindowTokens === undefined) {
|
||||
return input.triggerTokens
|
||||
}
|
||||
return Math.min(
|
||||
input.triggerTokens,
|
||||
Math.max(
|
||||
input.contextWindowTokens,
|
||||
minimumModelContextWindowTokens
|
||||
) - contextOutputAndSafetyTokens
|
||||
)
|
||||
}
|
||||
+34
-2
@@ -1,4 +1,8 @@
|
||||
import { z } from 'zod'
|
||||
import {
|
||||
maximumModelContextWindowTokens,
|
||||
minimumModelContextWindowTokens
|
||||
} from './context-window'
|
||||
import type {
|
||||
BrowserProfileCreateInput,
|
||||
BrowserProfileRenameInput,
|
||||
@@ -416,6 +420,11 @@ const modelApiKeyUpdateSchema = z.discriminatedUnion('action', [
|
||||
z.object({ action: z.literal('clear') }).strict()
|
||||
])
|
||||
|
||||
export {
|
||||
maximumModelContextWindowTokens,
|
||||
minimumModelContextWindowTokens
|
||||
} from './context-window'
|
||||
|
||||
const modelProfileInputSchema = z
|
||||
.object({
|
||||
id: modelProfileIdSchema,
|
||||
@@ -433,8 +442,8 @@ const modelProfileInputSchema = z
|
||||
contextWindowTokens: z
|
||||
.number()
|
||||
.int()
|
||||
.min(8_000)
|
||||
.max(10_000_000)
|
||||
.min(minimumModelContextWindowTokens)
|
||||
.max(maximumModelContextWindowTokens)
|
||||
.optional(),
|
||||
imageGenerationQuality: imageGenerationQualitySchema,
|
||||
apiKey: modelApiKeyUpdateSchema
|
||||
@@ -907,6 +916,29 @@ export type AgentEvent =
|
||||
type: 'reasoning'
|
||||
delta: string
|
||||
}
|
||||
| {
|
||||
requestId: string
|
||||
type: 'context-metrics'
|
||||
estimatedInputTokens: number
|
||||
effectiveTriggerTokens: number
|
||||
contextWindowTokens?: number
|
||||
compressionEnabled: boolean
|
||||
recentRawTokens: number
|
||||
coveredMessageCount: number
|
||||
summaryTokens: number
|
||||
}
|
||||
| {
|
||||
requestId: string
|
||||
type: 'context-compression'
|
||||
state: 'started' | 'completed'
|
||||
estimatedBeforeTokens: number
|
||||
estimatedAfterTokens?: number
|
||||
effectiveTriggerTokens: number
|
||||
contextWindowTokens?: number
|
||||
recentRawTokens: number
|
||||
coveredMessageCount: number
|
||||
summaryTokens?: number
|
||||
}
|
||||
| {
|
||||
requestId: string
|
||||
type: 'tool'
|
||||
|
||||
Reference in New Issue
Block a user