import { z } from "zod"; import { interpolateFString, FewShotPromptTemplate, } from "@langchain/core/prompts"; import { QueryTransformer } from "./parser.js"; import { Comparators, Operators, StructuredQuery, } from "./ir.js"; import { DEFAULT_EXAMPLES, DEFAULT_PREFIX, DEFAULT_SCHEMA, DEFAULT_SUFFIX, EXAMPLE_PROMPT, } from "./prompt.js"; import { AsymmetricStructuredOutputParser } from "../../output_parsers/structured.js"; /** * A simple data structure that holds information about an attribute. It * is typically used to provide metadata about attributes in other classes * or data structures within the LangChain framework. */ export class AttributeInfo { constructor(name, type, description) { Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: name }); Object.defineProperty(this, "type", { enumerable: true, configurable: true, writable: true, value: type }); Object.defineProperty(this, "description", { enumerable: true, configurable: true, writable: true, value: description }); } } export { QueryTransformer }; export { DEFAULT_EXAMPLES, DEFAULT_PREFIX, DEFAULT_SCHEMA, DEFAULT_SUFFIX, EXAMPLE_PROMPT, }; const queryInputSchema = /* #__PURE__ */ z.object({ query: /* #__PURE__ */ z .string() .describe("text string to compare to document contents"), filter: /* #__PURE__ */ z .string() .optional() .describe("logical condition statement for filtering documents"), }); /** * A class that extends AsymmetricStructuredOutputParser to parse * structured query output. */ export class StructuredQueryOutputParser extends AsymmetricStructuredOutputParser { constructor(fields) { super({ ...fields, inputSchema: queryInputSchema }); Object.defineProperty(this, "lc_namespace", { enumerable: true, configurable: true, writable: true, value: ["langchain", "chains", "query_constructor"] }); Object.defineProperty(this, "queryTransformer", { enumerable: true, configurable: true, writable: true, value: void 0 }); const { allowedComparators, allowedOperators } = fields; this.queryTransformer = new QueryTransformer(allowedComparators, allowedOperators); } /** * Processes the output of a structured query. * @param query The query string. * @param filter The filter condition. * @returns A Promise that resolves to a StructuredQuery instance. */ async outputProcessor({ query, filter, }) { let myQuery = query; if (myQuery.length === 0) { myQuery = " "; } if (filter === "NO_FILTER" || filter === undefined) { return new StructuredQuery(query); } else { const parsedFilter = await this.queryTransformer.parse(filter); return new StructuredQuery(query, parsedFilter); } } /** * Creates a new StructuredQueryOutputParser instance from the provided * components. * @param allowedComparators An array of allowed Comparator instances. * @param allowedOperators An array of allowed Operator instances. * @returns A new StructuredQueryOutputParser instance. */ static fromComponents(allowedComparators = [], allowedOperators = []) { return new StructuredQueryOutputParser({ allowedComparators, allowedOperators, }); } } export function formatAttributeInfo(info) { const infoObj = info.reduce((acc, attr) => { acc[attr.name] = { type: attr.type, description: attr.description, }; return acc; }, {}); return JSON.stringify(infoObj, null, 2) .replaceAll("{", "{{") .replaceAll("}", "}}"); } const defaultExample = DEFAULT_EXAMPLES.map((EXAMPLE) => EXAMPLE); function _getPrompt(documentContents, attributeInfo, allowedComparators, allowedOperators, examples = defaultExample) { const myAllowedComparators = allowedComparators ?? Object.values(Comparators); const myAllowedOperators = allowedOperators ?? Object.values(Operators); const attributeJSON = formatAttributeInfo(attributeInfo); const schema = interpolateFString(DEFAULT_SCHEMA, { allowed_comparators: myAllowedComparators.join(" | "), allowed_operators: myAllowedOperators.join(" | "), }); const prefix = interpolateFString(DEFAULT_PREFIX, { schema, }); const suffix = interpolateFString(DEFAULT_SUFFIX, { i: examples.length + 1, content: documentContents, attributes: attributeJSON, }); const outputParser = StructuredQueryOutputParser.fromComponents(allowedComparators, allowedOperators); return new FewShotPromptTemplate({ examples, examplePrompt: EXAMPLE_PROMPT, inputVariables: ["query"], suffix, prefix, outputParser, }); } export function loadQueryConstructorRunnable(opts) { const prompt = _getPrompt(opts.documentContents, opts.attributeInfo, opts.allowedComparators, opts.allowedOperators, opts.examples); const outputParser = StructuredQueryOutputParser.fromComponents(opts.allowedComparators, opts.allowedOperators); return prompt.pipe(opts.llm).pipe(outputParser); }