prompt-manners
Version:
A prompt injection mitigation library
119 lines (114 loc) • 2.99 kB
JavaScript
;
// 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,
};
}
exports.Optional = Optional;
exports.PromptSymbol = PromptSymbol;
exports.dataPrompt = dataPrompt;
exports.instructionPrompt = instructionPrompt;
exports.promptCompiler = promptCompiler;