Files
makelore/shared/imported-model-profile.ts

180 lines
5.1 KiB
TypeScript

export type ImportedModelModality = 'text' | 'audio' | 'image' | 'pdf';
export type ImportedVisionTokenEstimator = 'qwen-32px-grid';
export type ImportedThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'max';
export const IMPORTED_REASONING_EFFORTS = ['low', 'high', 'max'] as const;
export type ImportedReasoningEffort = (typeof IMPORTED_REASONING_EFFORTS)[number];
export type ImportedModelWebSearchCapability = Readonly<{
schemaVersion: 1;
adapter: 'openai-responses' | 'bailian-responses' | 'bailian-chat-completions';
supportsForcedSearch: true;
sourceMode: 'structured' | 'inline-or-structured';
billingAuthority: 'model-request';
}>;
export interface ImportedModelCapability {
reasoningEfforts: ImportedReasoningEffort[];
reasoningCanDisable: boolean;
webSearch?: ImportedModelWebSearchCapability;
}
export type ImportedModelCapabilities = Record<string, ImportedModelCapability>;
export function thinkingLevelMapForImportedModelCapability(
capability: ImportedModelCapability,
): Partial<Record<ImportedThinkingLevel, string | null>> {
return {
...(capability.reasoningCanDisable ? {} : { off: null }),
minimal: null,
low: capability.reasoningEfforts.includes('low') ? 'low' : null,
medium: null,
high: capability.reasoningEfforts.includes('high') ? 'high' : null,
max: capability.reasoningEfforts.includes('max') ? 'max' : null,
};
}
export interface ImportedPiModelProfile {
reasoning: boolean;
thinkingLevelMap?: Partial<Record<ImportedThinkingLevel, string | null>>;
compat?: {
thinkingFormat?: 'deepseek' | 'openrouter' | 'qwen';
supportsDeveloperRole?: boolean;
supportsReasoningEffort?: boolean;
supportsStore?: boolean;
requiresReasoningContentOnAssistantMessages?: boolean;
};
}
export interface ImportedModelProfile {
modalities: {
input: ImportedModelModality[];
output: ImportedModelModality[];
};
limit?: {
context: number;
output: number;
};
visionTokenEstimator?: ImportedVisionTokenEstimator;
pi?: ImportedPiModelProfile;
}
const VERIFIED_QWEN_36_PLUS_MODEL_IDS = new Set([
'qwen3.6-plus',
'qwen3.6-plus-2026-04-02',
]);
const VERIFIED_QWEN_PLUS_MODEL_IDS = new Set([
...VERIFIED_QWEN_36_PLUS_MODEL_IDS,
'qwen3.7-plus',
'qwen3.7-plus-2026-05-26',
]);
const QWEN_VL_PATTERN = /^qwen(?:\d+(?:\.\d+)?)?-vl(?:[-\w.]+)?$/i;
const QWEN_OMNI_PATTERN = /^qwen-omni(?:[-\w.]+)?$/i;
function imageModalities(): ImportedModelProfile['modalities'] {
return {
input: ['text', 'image'],
output: ['text'],
};
}
export function getImportedModelProfile(rawModelId: string): ImportedModelProfile | null {
const modelId = rawModelId.trim();
const normalizedModelId = modelId.toLowerCase();
if (normalizedModelId === 'deepseek-v4-pro') {
return {
modalities: {
input: ['text'],
output: ['text'],
},
limit: {
context: 1_000_000,
output: 384_000,
},
pi: {
reasoning: true,
thinkingLevelMap: {
minimal: null,
low: 'low',
medium: null,
high: 'high',
max: 'max',
},
compat: {
thinkingFormat: 'deepseek',
supportsReasoningEffort: true,
requiresReasoningContentOnAssistantMessages: true,
},
},
};
}
if (normalizedModelId === 'qwen3.8-max') {
return {
modalities: imageModalities(),
limit: {
context: 1_000_000,
output: 131_072,
},
pi: {
reasoning: true,
thinkingLevelMap: {
minimal: null,
low: 'low',
medium: 'medium',
high: 'xhigh',
},
compat: {
thinkingFormat: 'qwen',
supportsDeveloperRole: false,
supportsReasoningEffort: true,
supportsStore: false,
},
},
};
}
if (VERIFIED_QWEN_PLUS_MODEL_IDS.has(normalizedModelId)) {
return {
modalities: imageModalities(),
limit: {
context: 1_000_000,
output: 65_536,
},
visionTokenEstimator: 'qwen-32px-grid',
...(VERIFIED_QWEN_36_PLUS_MODEL_IDS.has(normalizedModelId)
? {
pi: {
reasoning: true,
thinkingLevelMap: {
minimal: null,
low: null,
medium: null,
high: 'high',
},
compat: {
thinkingFormat: 'qwen' as const,
supportsDeveloperRole: false,
supportsReasoningEffort: false,
supportsStore: false,
},
},
}
: {}),
};
}
if (QWEN_VL_PATTERN.test(modelId) || QWEN_OMNI_PATTERN.test(modelId)) {
return {
modalities: imageModalities(),
};
}
return null;
}
export function estimateImportedModelVisionTokens(
modelId: string,
width: number,
height: number,
): number | null {
if (getImportedModelProfile(modelId)?.visionTokenEstimator !== 'qwen-32px-grid') return null;
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return null;
return Math.ceil((width * height) / (32 * 32)) + 2;
}