UNPKG

@llumiverse/core

Version:

Provide an universal API to LLMs. Support for existing LLMs can be added by writing a driver.

88 lines 2.93 kB
import { Ajv } from 'ajv'; import addFormats from 'ajv-formats'; import { extractAndParseJSON } from "./json.js"; import { resolveField } from './resolver.js'; const ajv = new Ajv({ coerceTypes: 'array', allowDate: true, strict: false, useDefaults: true, removeAdditional: "failing" }); //use ts ignore to avoid error with ESM and ajv-formats // @ts-ignore This expression is not callable addFormats(ajv); export class ValidationError extends Error { code; constructor(code, message) { super(message); this.code = code; this.name = 'ValidationError'; } } function parseCompletionAsJson(data) { let lastError; for (const part of data) { if (part.type === "text") { const text = part.value.trim(); try { return extractAndParseJSON(text); } catch (error) { lastError = new ValidationError("json_error", error.message); } } } if (!lastError) { lastError = new ValidationError("json_error", "No JSON compatible response found in completion result"); } throw lastError; } export function validateResult(data, schema) { let json; if (Array.isArray(data)) { const jsonResults = data.filter(r => r.type === "json"); if (jsonResults.length > 0) { json = jsonResults[0].value; } else { try { json = parseCompletionAsJson(data); } catch (error) { throw new ValidationError("json_error", error.message); } } } else { throw new Error("Data to validate must be an array"); } const validate = ajv.compile(schema); const valid = validate(json); if (!valid && validate.errors) { let errors = []; for (const e of validate.errors) { const path = e.instancePath.split("/").slice(1); const value = resolveField(json, path); const schemaPath = e.schemaPath.split("/").slice(1); const schemaFieldFormat = resolveField(schema, schemaPath); const schemaField = resolveField(schema, schemaPath.slice(0, -3)); //ignore date if empty or null if (!value && ["date", "date-time"].includes(schemaFieldFormat) && !schemaField?.required?.includes(path[path.length - 1])) { continue; } else { errors.push(e); } } //console.log("Errors", errors) if (errors.length > 0) { const errorsMessage = errors.map(e => `${e.instancePath}: ${e.message}\n${JSON.stringify(e.params)}`).join(",\n\n"); throw new ValidationError("validation_error", errorsMessage); } } return [{ type: "json", value: json }]; } //# sourceMappingURL=validation.js.map