UNPKG

prompt-manners

Version:

A prompt injection mitigation library

113 lines (109 loc) 2.87 kB
// export interface Logger { // log(...args: unknown[]): void; // warn(...args: unknown[]): void; // error(...args: unknown[]): void; // } // export function defaultLogger(): Logger { // return { // log: console.log, // warn: console.warn, // error: console.error, // }; // } class Optional { value; constructor(value) { this.value = value; } get isPresent() { return this.value !== undefined && this.value !== null; } static of(value) { return new Optional(value); } static empty() { return new Optional(null); } } /** * * @param value * @returns */ function isNullish(value) { return value === null || value === undefined; } /** * https://developer.mozilla.org/en-US/docs/Glossary/Falsy * @param value * @returns */ function isFalsy(value) { if (isNullish(value)) { return true; } return value === false; } const PromptSymbol = Symbol.for("prompt-tag"); function dataPrompt( // eslint-disable-next-line @typescript-eslint/no-unused-vars _literals, // eslint-disable-next-line @typescript-eslint/no-unused-vars ..._args) { return { data: "", // TODO: handle hard coded inputs for the data prompt format: (input) => input, [PromptSymbol]: "data", }; } function instructionPrompt(literals, ...args) { const rawPrompt = literals .map((literal, idx) => { let result = literal; if (idx < args.length) { result += args[idx]; } return result; }) .join("") .trim(); return { instruction: rawPrompt, [PromptSymbol]: "instruction", }; } function promptCompiler(_literals, ...args) { // The question is how do zip them // Since this could start as an arg and continue? // for this tag the args might be more important // This ordering might not matter because we are just using this to compile all the prompts to one const prompts = new Map(); for (const arg of args) { if (Object.hasOwn(arg, PromptSymbol)) { prompts.set(arg[PromptSymbol], arg); } } /** * This will always render in this order * 1. instruction prompt * 2. data prompt */ const renderPrompt = (input) => { if (!prompts.has("instruction")) { return Optional.empty(); } let result = ""; const instruction = prompts.get("instruction"); result += instruction.instruction; if (!isFalsy(input) && prompts.has("data")) { result += "\n\n"; const data = prompts.get("data"); result += data.format(input); } return Optional.of(result); }; return { renderPrompt, }; } export { Optional, PromptSymbol, dataPrompt, instructionPrompt, promptCompiler };