Bonsai-Chat-WebGPU / src /bench /prompt-matrix.ts
Valeriy Selitskiy
Release v1.2.2 interactive chat workspace
21ad36a
Raw
History Blame Contribute Delete
4.05 kB
import type { EngineChatMessage, EngineChatTool } from '../engine';
export const RELEASE_PROMPT_MATRIX_PATH = 'fixtures/release-prompts.json';
export const RELEASE_PROMPT_MATRIX_MIN_CASES = 6;
export const RELEASE_PROMPT_MATRIX_MAX_TOKENS = 64;
export interface ReleasePromptCase {
id: string;
messages: EngineChatMessage[];
tools: EngineChatTool[];
}
function record(value: unknown, field: string): Record<string, unknown> {
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
throw new Error(`${field} must be an object.`);
}
return value as Record<string, unknown>;
}
function nonEmptyString(value: unknown, field: string): string {
if (typeof value !== 'string' || value.trim() === '') throw new Error(`${field} must be a non-empty string.`);
return value;
}
function parseMessage(value: unknown, field: string): EngineChatMessage {
const message = record(value, field);
const role = nonEmptyString(message.role, `${field}.role`);
const content = nonEmptyString(message.content, `${field}.content`);
if (role !== 'system' && role !== 'user' && role !== 'assistant') {
throw new Error(`${field}.role must be system, user, or assistant.`);
}
return { role, content };
}
function parseTool(value: unknown, field: string): EngineChatTool {
const tool = record(value, field);
if (tool.type !== 'function') throw new Error(`${field}.type must be function.`);
const fn = record(tool.function, `${field}.function`);
const parameters = record(fn.parameters, `${field}.function.parameters`);
if (parameters.type !== 'object') throw new Error(`${field}.function.parameters.type must be object.`);
const properties = record(parameters.properties, `${field}.function.parameters.properties`);
return {
type: 'function',
function: {
name: nonEmptyString(fn.name, `${field}.function.name`),
...(typeof fn.description === 'string' ? { description: fn.description } : {}),
parameters: {
type: 'object',
properties: properties as EngineChatTool['function']['parameters']['properties'],
...(Array.isArray(parameters.required)
? { required: parameters.required.map((entry, index) => nonEmptyString(entry, `${field}.function.parameters.required[${index}]`)) }
: {}),
},
},
};
}
export function parseReleasePromptMatrix(value: unknown): ReleasePromptCase[] {
if (!Array.isArray(value) || value.length < RELEASE_PROMPT_MATRIX_MIN_CASES) {
throw new Error(`Release prompt matrix requires at least ${RELEASE_PROMPT_MATRIX_MIN_CASES} cases.`);
}
const ids = new Set<string>();
const cases = value.map((entry, caseIndex) => {
const item = record(entry, `cases[${caseIndex}]`);
const id = nonEmptyString(item.id, `cases[${caseIndex}].id`);
if (ids.has(id)) throw new Error(`Duplicate release prompt id: ${id}.`);
ids.add(id);
if (!Array.isArray(item.messages) || item.messages.length === 0) {
throw new Error(`cases[${caseIndex}].messages must be a non-empty array.`);
}
const messages = item.messages.map((message, messageIndex) => (
parseMessage(message, `cases[${caseIndex}].messages[${messageIndex}]`)
));
const tools = item.tools === undefined
? []
: Array.isArray(item.tools)
? item.tools.map((tool, toolIndex) => parseTool(tool, `cases[${caseIndex}].tools[${toolIndex}]`))
: (() => { throw new Error(`cases[${caseIndex}].tools must be an array.`); })();
return { id, messages, tools };
});
const multiturn = cases.find((entry) => entry.id === 'multiturn');
if (!multiturn || multiturn.messages.length < 4 || !multiturn.messages.some((message) => message.role === 'assistant')) {
throw new Error('Release prompt matrix requires the locked multi-turn assistant-history case.');
}
const toolCall = cases.find((entry) => entry.id === 'tool_call');
if (!toolCall || toolCall.tools.length === 0) {
throw new Error('Release prompt matrix requires the locked tool-call case.');
}
return cases;
}