mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-08-29 04:26:38 +00:00
Closes #2848. - dsh-llm 新增 LlmAdapter.imageRequestPricing 同步钩子与 LlmImageRequestPricing/LlmImageRequestPrice 词汇,ctx.llm 按路由解析 - llm-deepseek 用官方公布的 v4 视觉计算器逐句移植(14px patch、3:1 降采样、384 上限、最坏对齐 pad)实现该钩子,复现请求投影的最旧优先 offload 与像素预算缩放;纯几何 requestImageDimensions 上移到 dsh-attachment - token-meter 表层 fold 存储与路由无关的节点事实,measure() 按生效 envelope 的路由为图片出现处定价;锚点存快照并按同一路由重定价;TokenSurfaceNode 同时携带路由价 tokens 与固定启发式 heuristicTokens - compaction 触发、保留与选段读取同一套路由价,记录的 shadowedTokenCount 保持启发式以维持 O(1) 投影 fold 一致 - llm-replay 支持按模型的 imageRequestTokens 声明;新增 keyless 的 image-compaction ACP 快照场景端到端验证装配应用
131 lines
5.4 KiB
TypeScript
131 lines
5.4 KiB
TypeScript
/** Deterministic provider-independent image normalization. */
|
|
|
|
import sharp, { type Sharp } from 'sharp'
|
|
import { AttachmentError, requestImageDimensions } from '@deepseek-ai/dsh-attachment'
|
|
import type { ImageMediaType } from '@deepseek-ai/dsh-attachment'
|
|
import { encodeFirstWithinLimit, encodingLadder, isExhaustedEncoding } from './encoding.ts'
|
|
import { detectImage, encodedAlphaIsCompatible } from './image.ts'
|
|
import type { DetectedImage } from './image.ts'
|
|
|
|
/** Deployment-resolved policy for the persisted normalized attachment. */
|
|
export interface NormalizationPolicy {
|
|
/** Total-pixel budget; larger sources are downscaled proportionally. */
|
|
maxPixels: number
|
|
/** Long-edge cap in pixels applied after the total-pixel budget, bounding extreme aspect ratios. */
|
|
maxDimension: number
|
|
/** Encoded-byte target for the quality ladder; the smallest ladder output is kept when no quality fits. */
|
|
maxBytes: number
|
|
}
|
|
|
|
/** Normalized bytes beside the facts recorded by a durable reference. */
|
|
export interface NormalizedImage {
|
|
data: Uint8Array
|
|
mediaType: ImageMediaType
|
|
width: number
|
|
height: number
|
|
}
|
|
|
|
/**
|
|
* Whether bytes already satisfy the normalization requirements.
|
|
* @param detected - fully decoded source facts.
|
|
* @param bytes - encoded source length.
|
|
* @param policy - resolved normalization limits.
|
|
* @returns whether the source can pass through byte-identically.
|
|
*/
|
|
export function canPassThroughNormalization(
|
|
detected: DetectedImage,
|
|
bytes: number,
|
|
policy: NormalizationPolicy,
|
|
): boolean {
|
|
return detected.mediaType !== 'image/gif'
|
|
&& !detected.animated
|
|
&& !detected.carriesMetadata
|
|
&& detected.depth === 'uchar'
|
|
&& detected.space === 'srgb'
|
|
&& bytes <= policy.maxBytes
|
|
&& detected.width * detected.height <= policy.maxPixels
|
|
&& Math.max(detected.width, detected.height) <= policy.maxDimension
|
|
}
|
|
|
|
/** Assert that a normalized output is an 8-bit sRGB/sRGBA single-frame image with matching facts. */
|
|
async function verifyNormalizedImage(
|
|
image: NormalizedImage,
|
|
expectedAlpha: boolean | undefined,
|
|
): Promise<NormalizedImage> {
|
|
const detected = await detectImage(image.data)
|
|
if (detected.mediaType !== image.mediaType
|
|
|| detected.width !== image.width
|
|
|| detected.height !== image.height
|
|
|| detected.animated
|
|
|| detected.carriesMetadata
|
|
|| detected.depth !== 'uchar'
|
|
|| detected.space !== 'srgb'
|
|
|| !encodedAlphaIsCompatible(expectedAlpha, detected)) {
|
|
throw new AttachmentError(
|
|
'Image normalization did not produce a single-frame 8-bit sRGB image with matching metadata.',
|
|
'ATTACHMENT_WRITE_FAILED',
|
|
)
|
|
}
|
|
return image
|
|
}
|
|
|
|
/** Build one fixed-size, oriented, metadata-free sRGB pipeline from submitted bytes. */
|
|
function preparedPipeline(data: Uint8Array, width: number, height: number): Sharp {
|
|
return sharp(data, { failOn: 'error', limitInputPixels: false })
|
|
.rotate()
|
|
.toColourspace('srgb')
|
|
.resize({ width, height, fit: 'inside', withoutEnlargement: true })
|
|
}
|
|
|
|
/** Dimensions under the total-pixel budget, then the long-edge cap, without changing aspect ratio. */
|
|
function initialDimensions(detected: DetectedImage, policy: NormalizationPolicy): { width: number; height: number } {
|
|
const budgeted = requestImageDimensions(detected.width, detected.height, policy.maxPixels)
|
|
const longEdge = Math.max(budgeted.width, budgeted.height)
|
|
if (longEdge <= policy.maxDimension) return budgeted
|
|
const scale = policy.maxDimension / longEdge
|
|
return {
|
|
width: Math.max(1, Math.floor(budgeted.width * scale)),
|
|
height: Math.max(1, Math.floor(budgeted.height * scale)),
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Produce the persisted provider-independent normalized version of one fully decoded source.
|
|
* The source is passed through only when it is already clean, single-frame, 8-bit sRGB/sRGBA,
|
|
* and inside every normalization limit. Re-encoding never removes transparency. When every
|
|
* ladder quality exceeds the byte target, the smallest ladder output is kept; provider byte
|
|
* caps stay enforced at the route that transmits the bytes.
|
|
* @param data - complete admitted source bytes.
|
|
* @param detected - fully decoded source facts.
|
|
* @param policy - resolved independent normalization limits.
|
|
* @returns verified provider-independent normalized bytes and metadata.
|
|
*/
|
|
export async function normalizeImage(
|
|
data: Uint8Array,
|
|
detected: DetectedImage,
|
|
policy: NormalizationPolicy,
|
|
): Promise<NormalizedImage> {
|
|
if (canPassThroughNormalization(detected, data.byteLength, policy)) {
|
|
return { data, mediaType: detected.mediaType, width: detected.width, height: detected.height }
|
|
}
|
|
try {
|
|
const { width, height } = initialDimensions(detected, policy)
|
|
const encoded = await encodeFirstWithinLimit(
|
|
encodingLadder(preparedPipeline(data, width, height), detected.hasAlpha),
|
|
policy.maxBytes,
|
|
)
|
|
const chosen = isExhaustedEncoding(encoded) ? encoded.smallest : encoded
|
|
return await verifyNormalizedImage(chosen, detected.mediaType === 'image/gif' ? undefined : detected.hasAlpha)
|
|
} catch (error) {
|
|
if (error instanceof AttachmentError) throw error
|
|
const source = detected.mediaType === 'image/png' && detected.depth !== 'uchar'
|
|
? `${detected.depth === 'ushort' ? '16-bit' : detected.depth} PNG`
|
|
: `${detected.depth} ${detected.mediaType.slice('image/'.length).toUpperCase()}`
|
|
throw new AttachmentError(
|
|
`The ${source} could not be converted to the normalized 8-bit sRGB form.`,
|
|
'ATTACHMENT_WRITE_FAILED',
|
|
{ cause: error },
|
|
)
|
|
}
|
|
}
|