Files
wehub-resource-sync 0d3cb498a3
CI / Shell Format Check (push) Has been cancelled
CI / Check Ruby (3.4) (push) Has been cancelled
CI / CI Config (push) Has been cancelled
CI / Test on Node ${{ matrix.node }} and ${{ matrix.os }}${{ matrix.shard && format(' (shard {0}/3)', matrix.shard) || '' }} (push) Has been cancelled
CI / Build on Node ${{ matrix.node }} (push) Has been cancelled
CI / Style Check (push) Has been cancelled
CI / Generate Assets (push) Has been cancelled
CI / Check Python (3.14) (push) Has been cancelled
CI / Check Python (3.9) (push) Has been cancelled
CI / Build Docs (push) Has been cancelled
CI / Code Scan Action (push) Has been cancelled
CI / Site tests (push) Has been cancelled
CI / webui tests (push) Has been cancelled
CI / Run Integration Tests (push) Has been cancelled
CI / Run Smoke Tests (push) Has been cancelled
CI / Go Tests (push) Has been cancelled
CI / Share Test (push) Has been cancelled
CI / Redteam (Production API) (push) Has been cancelled
CI / Redteam (Staging API) (push) Has been cancelled
CI / GitHub Actions Lint (push) Has been cancelled
CI / Check Ruby (3.0) (push) Has been cancelled
release-please / release-please (push) Has been cancelled
release-please / build (push) Has been cancelled
release-please / publish-npm (push) Has been cancelled
release-please / publish-npm-backfill (push) Has been cancelled
release-please / docker (push) Has been cancelled
release-please / publish-code-scan-action (push) Has been cancelled
release-please / attest-code-scan-action (push) Has been cancelled
Deploy local.promptfoo.app / Deploy to Cloudflare Pages (push) Has been cancelled
Test and Publish Multi-arch Docker Image / test (push) Has been cancelled
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-amd64 platform:linux/amd64 runner:ubuntu-latest]) (push) Has been cancelled
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-arm64 platform:linux/arm64 runner:ubuntu-24.04-arm]) (push) Has been cancelled
Test and Publish Multi-arch Docker Image / merge-docker-digests (push) Has been cancelled
Test and Publish Multi-arch Docker Image / Attest Multi-arch Image (push) Has been cancelled
Validate Renovate Config / Validate Renovate Configuration (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:24:08 +08:00

146 lines
4.7 KiB
TypeScript

import { zodResponseFormat } from 'openai/helpers/zod.mjs';
import { TranslationResponseSchema } from './src/schemas/translation-response';
import type { UnifiedConfig } from 'promptfoo';
// Generate the response format for OpenAI
const responseFormat = zodResponseFormat(TranslationResponseSchema, 'translation_response');
// Helper to adapt schema for Gemini (removes OpenAI-specific fields)
function cleanSchemaForGemini(schema: any): any {
if (typeof schema !== 'object' || schema === null) {
return schema;
}
const cleaned = { ...schema };
// Remove properties that Gemini doesn't support
delete cleaned.additionalProperties;
delete cleaned.$schema;
// Recursively clean nested objects
if (cleaned.properties) {
cleaned.properties = Object.fromEntries(
Object.entries(cleaned.properties).map(([key, value]) => [key, cleanSchemaForGemini(value)]),
);
}
if (cleaned.items) {
cleaned.items = cleanSchemaForGemini(cleaned.items);
}
return cleaned;
}
const config: UnifiedConfig = {
description: 'Fun translation tests with structured outputs',
prompts: [
`You are a creative translator who adds personality to translations.
Translate this to {{language}}: "{{text}}"
Return a JSON response with your translation, confidence level, and any fun cultural notes.`,
],
providers: [
{
id: 'openai:chat:gpt-5.5',
label: 'GPT-5.5 (structured)',
config: {
response_format: responseFormat,
},
},
{
id: 'google:gemini-2.5-flash',
label: 'Gemini 2.5 Flash (structured)',
config: {
generationConfig: {
response_mime_type: 'application/json',
response_schema: cleanSchemaForGemini(responseFormat.json_schema.schema),
},
},
},
],
tests: [
{
vars: {
language: 'Pirate speak',
text: "I can't find my coffee",
},
assert: [
{
type: 'javascript',
value: `
// Handle both object and string outputs
const parsed = typeof output === 'object' ? output :
JSON.parse(output.replace(/^\`\`\`json\\s*|\\s*\`\`\`$/g, ''));
// Check for valid pirate speak patterns
const text = parsed.translation.toLowerCase();
const hasPirateSpeak = text.includes('arr') || text.includes('matey') ||
text.includes('ye') || text.includes("me ") ||
text.includes("'t ") || text.match(/\bt'\b/) ||
text.includes('brew');
return parsed.translation &&
parsed.language.toLowerCase().includes('pirate') &&
hasPirateSpeak;
`,
},
],
},
{
vars: {
language: 'Shakespeare English',
text: 'This app is broken',
},
assert: [
{
type: 'javascript',
value: `
const parsed = typeof output === 'object' ? output :
JSON.parse(output.replace(/^\`\`\`json\\s*|\\s*\`\`\`$/g, ''));
const text = parsed.translation.toLowerCase();
return parsed.translation &&
(text.includes('thou') || text.includes('thee') ||
text.includes('doth') || text.includes('hath') ||
text.includes('alas') || text.includes('lieth') ||
text.includes('woeful') || text.includes('undone') ||
text.includes('forsooth') || text.includes('prithee') ||
text.includes('verily') || text.match(/eth\\b/));
`,
},
],
},
{
vars: {
language: 'Gen Z slang',
text: "That's really impressive",
},
assert: [
{
type: 'javascript',
value: `
const parsed = typeof output === 'object' ? output :
JSON.parse(output.replace(/^\`\`\`json\\s*|\\s*\`\`\`$/g, ''));
const translation = parsed.translation.toLowerCase();
return parsed.translation &&
parsed.confidence > 0 &&
(translation.includes('slay') ||
translation.includes('fire') ||
translation.includes('bussin') ||
translation.includes('lit') ||
translation.includes('goat') ||
translation.includes('lowkey') ||
translation.includes('low-key') ||
translation.includes('no cap') ||
translation.includes(' fr') ||
translation.includes('insane'));
`,
},
],
},
],
};
export default config;