UNPKG

@langchain/community

Version:
1 lines • 32.9 kB
{"version":3,"file":"prisma.cjs","names":["VectorStore","embeddings: EmbeddingsInterface","config: {\n db: PrismaClient;\n prisma: PrismaNamespace;\n tableName: TModelName;\n vectorColumnName: string;\n columns: TSelectModel;\n filter?: TFilterModel;\n columnTypes?: ColumnTypeConfig;\n /**\n * When true, addDocuments uses INSERT statements to create new records.\n * When false (default), addDocuments uses UPDATE statements to update existing records by ID.\n * Set to true when using with ParentDocumentRetriever or when documents don't pre-exist in the database.\n */\n useInsert?: boolean;\n }","db: PrismaClient","config: {\n prisma: TPrisma;\n tableName: keyof TPrisma[\"ModelName\"] & string;\n vectorColumnName: string;\n columns: TColumns;\n filter?: TFilters;\n columnTypes?: ColumnTypeConfig;\n useInsert?: boolean;\n }","texts: string[]","metadatas: TModel[]","dbConfig: {\n prisma: TPrisma;\n tableName: keyof TPrisma[\"ModelName\"] & string;\n vectorColumnName: string;\n columns: TColumns;\n columnTypes?: ColumnTypeConfig;\n useInsert?: boolean;\n }","docs: Document[]","Document","docs: Document<TModel>[]","models: TModel[]","documents: Document<TModel>[]","vectors: number[][]","query: string","filter: this[\"FilterType\"] | undefined","k?: number","filter?: this[\"FilterType\"]","query: number[]","k: number","results: [Document<SimilarityModel<TModel, TSelectModel>>, number][]","metadatas: object[]","dbConfig: {\n db: PrismaClient;\n prisma: PrismaNamespace;\n tableName: string;\n vectorColumnName: string;\n columns: ModelColumns<Record<string, unknown>>;\n columnTypes?: ColumnTypeConfig;\n useInsert?: boolean;\n }"],"sources":["../../src/vectorstores/prisma.ts"],"sourcesContent":["import { Document } from \"@langchain/core/documents\";\nimport type { EmbeddingsInterface } from \"@langchain/core/embeddings\";\nimport type { DocumentInterface } from \"@langchain/core/documents\";\nimport { VectorStore } from \"@langchain/core/vectorstores\";\n\nconst IdColumnSymbol = Symbol(\"id\");\nconst ContentColumnSymbol = Symbol(\"content\");\n\ntype ColumnSymbol = typeof IdColumnSymbol | typeof ContentColumnSymbol;\n\ndeclare type Value = unknown;\ndeclare type RawValue = Value | Sql;\n\ndeclare class Sql {\n strings: string[];\n\n constructor(\n rawStrings: ReadonlyArray<string>,\n rawValues: ReadonlyArray<RawValue>\n );\n}\n\ntype PrismaNamespace = {\n ModelName: Record<string, string>;\n Sql: typeof Sql;\n raw: (sql: string) => Sql;\n join: (\n values: RawValue[],\n separator?: string,\n prefix?: string,\n suffix?: string\n ) => Sql;\n sql: (strings: ReadonlyArray<string>, ...values: RawValue[]) => Sql;\n};\n\ntype PrismaClient = {\n $queryRaw<T = unknown>(\n query: TemplateStringsArray | Sql,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ...values: any[]\n ): Promise<T>;\n $executeRaw(\n query: TemplateStringsArray | Sql,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ...values: any[]\n ): // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Promise<any>;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n $transaction<P extends Promise<any>[]>(arg: [...P]): Promise<any>;\n};\n\ntype ObjectIntersect<A, B> = {\n [P in keyof A & keyof B]: A[P] | B[P];\n};\n\ntype ModelColumns<TModel extends Record<string, unknown>> = {\n [K in keyof TModel]?: true | ColumnSymbol;\n};\n\nexport type PrismaSqlFilter<TModel extends Record<string, unknown>> = {\n [K in keyof TModel]?: {\n equals?: TModel[K];\n in?: TModel[K][];\n notIn?: TModel[K][];\n isNull?: TModel[K];\n isNotNull?: TModel[K];\n like?: TModel[K];\n lt?: TModel[K];\n lte?: TModel[K];\n gt?: TModel[K];\n gte?: TModel[K];\n not?: TModel[K];\n };\n};\n\nconst OpMap = {\n equals: \"=\",\n in: \"IN\",\n notIn: \"NOT IN\",\n isNull: \"IS NULL\",\n isNotNull: \"IS NOT NULL\",\n like: \"LIKE\",\n lt: \"<\",\n lte: \"<=\",\n gt: \">\",\n gte: \">=\",\n not: \"<>\",\n};\n\ntype SimilarityModel<\n TModel extends Record<string, unknown> = Record<string, unknown>,\n TColumns extends ModelColumns<TModel> = ModelColumns<TModel>,\n> = Pick<TModel, keyof ObjectIntersect<TModel, TColumns>> & {\n _distance: number | null;\n};\n\ntype DefaultPrismaVectorStore = PrismaVectorStore<\n Record<string, unknown>,\n string,\n ModelColumns<Record<string, unknown>>,\n PrismaSqlFilter<Record<string, unknown>>\n>;\n\n/**\n * Configuration for column types to enable proper type casting in SQL queries.\n * This is particularly important for columns that require explicit casting,\n * such as UUID columns in PostgreSQL.\n */\nexport interface ColumnTypeConfig {\n [key: string]: \"uuid\" | \"text\" | \"integer\" | \"bigint\" | \"jsonb\";\n}\n\n/**\n * A specific implementation of the VectorStore class that is designed to\n * work with Prisma. It provides methods for adding models, documents, and\n * vectors, as well as for performing similarity searches.\n */\nexport class PrismaVectorStore<\n TModel extends Record<string, unknown>,\n TModelName extends string,\n TSelectModel extends ModelColumns<TModel>,\n TFilterModel extends PrismaSqlFilter<TModel>,\n> extends VectorStore {\n declare FilterType: TFilterModel;\n\n protected tableName: string;\n\n protected vectorColumnName: string;\n\n protected selectColumns: string[];\n\n filter?: TFilterModel;\n\n idColumn: keyof TModel & string;\n\n contentColumn: keyof TModel & string;\n\n protected columnTypes?: ColumnTypeConfig;\n\n /**\n * When true, addDocuments uses INSERT statements to create new records.\n * When false (default), addDocuments uses UPDATE statements to update existing records by ID.\n * Set to true when using with ParentDocumentRetriever or when documents don't pre-exist in the database.\n */\n protected useInsert: boolean;\n\n static IdColumn: typeof IdColumnSymbol = IdColumnSymbol;\n\n static ContentColumn: typeof ContentColumnSymbol = ContentColumnSymbol;\n\n protected db: PrismaClient;\n\n protected Prisma: PrismaNamespace;\n\n _vectorstoreType(): string {\n return \"prisma\";\n }\n\n constructor(\n embeddings: EmbeddingsInterface,\n config: {\n db: PrismaClient;\n prisma: PrismaNamespace;\n tableName: TModelName;\n vectorColumnName: string;\n columns: TSelectModel;\n filter?: TFilterModel;\n columnTypes?: ColumnTypeConfig;\n /**\n * When true, addDocuments uses INSERT statements to create new records.\n * When false (default), addDocuments uses UPDATE statements to update existing records by ID.\n * Set to true when using with ParentDocumentRetriever or when documents don't pre-exist in the database.\n */\n useInsert?: boolean;\n }\n ) {\n super(embeddings, {});\n\n this.Prisma = config.prisma;\n this.db = config.db;\n\n const entries = Object.entries(config.columns);\n const idColumn = entries.find((i) => i[1] === IdColumnSymbol)?.[0];\n const contentColumn = entries.find(\n (i) => i[1] === ContentColumnSymbol\n )?.[0];\n\n if (idColumn == null) throw new Error(\"Missing ID column\");\n if (contentColumn == null) throw new Error(\"Missing content column\");\n\n this.idColumn = idColumn;\n this.contentColumn = contentColumn;\n\n this.tableName = config.tableName;\n this.vectorColumnName = config.vectorColumnName;\n this.columnTypes = config.columnTypes;\n this.useInsert = config.useInsert ?? false;\n\n this.selectColumns = entries\n .map(([key, alias]) => (alias && key) || null)\n .filter((x): x is string => !!x);\n\n if (config.filter) {\n this.filter = config.filter;\n }\n }\n\n /**\n * Creates a new PrismaVectorStore with the specified model.\n * @param db The PrismaClient instance.\n * @returns An object with create, fromTexts, and fromDocuments methods.\n */\n static withModel<TModel extends Record<string, unknown>>(db: PrismaClient) {\n function create<\n TPrisma extends PrismaNamespace,\n TColumns extends ModelColumns<TModel>,\n TFilters extends PrismaSqlFilter<TModel>,\n >(\n embeddings: EmbeddingsInterface,\n config: {\n prisma: TPrisma;\n tableName: keyof TPrisma[\"ModelName\"] & string;\n vectorColumnName: string;\n columns: TColumns;\n filter?: TFilters;\n columnTypes?: ColumnTypeConfig;\n useInsert?: boolean;\n }\n ) {\n type ModelName = keyof TPrisma[\"ModelName\"] & string;\n return new PrismaVectorStore<TModel, ModelName, TColumns, TFilters>(\n embeddings,\n { ...config, db }\n );\n }\n\n async function fromTexts<\n TPrisma extends PrismaNamespace,\n TColumns extends ModelColumns<TModel>,\n >(\n texts: string[],\n metadatas: TModel[],\n embeddings: EmbeddingsInterface,\n dbConfig: {\n prisma: TPrisma;\n tableName: keyof TPrisma[\"ModelName\"] & string;\n vectorColumnName: string;\n columns: TColumns;\n columnTypes?: ColumnTypeConfig;\n useInsert?: boolean;\n }\n ) {\n const docs: Document[] = [];\n for (let i = 0; i < texts.length; i += 1) {\n const metadata = Array.isArray(metadatas) ? metadatas[i] : metadatas;\n const newDoc = new Document({\n pageContent: texts[i],\n metadata,\n });\n docs.push(newDoc);\n }\n\n return PrismaVectorStore.fromDocuments(docs, embeddings, {\n ...dbConfig,\n db,\n });\n }\n\n async function fromDocuments<\n TPrisma extends PrismaNamespace,\n TColumns extends ModelColumns<TModel>,\n TFilters extends PrismaSqlFilter<TModel>,\n >(\n docs: Document<TModel>[],\n embeddings: EmbeddingsInterface,\n dbConfig: {\n prisma: TPrisma;\n tableName: keyof TPrisma[\"ModelName\"] & string;\n vectorColumnName: string;\n columns: TColumns;\n columnTypes?: ColumnTypeConfig;\n useInsert?: boolean;\n }\n ) {\n type ModelName = keyof TPrisma[\"ModelName\"] & string;\n const instance = new PrismaVectorStore<\n TModel,\n ModelName,\n TColumns,\n TFilters\n >(embeddings, { ...dbConfig, db });\n await instance.addDocuments(docs);\n return instance;\n }\n\n return { create, fromTexts, fromDocuments };\n }\n\n /**\n * Adds the specified models to the store.\n * @param models The models to add.\n * @returns A promise that resolves when the models have been added.\n */\n async addModels(models: TModel[]) {\n return this.addDocuments(\n models.map((metadata) => {\n const pageContent = metadata[this.contentColumn];\n if (typeof pageContent !== \"string\")\n throw new Error(\"Content column must be a string\");\n return new Document({ pageContent, metadata });\n })\n );\n }\n\n /**\n * Adds the specified documents to the store.\n * @param documents The documents to add.\n * @returns A promise that resolves when the documents have been added.\n */\n async addDocuments(documents: Document<TModel>[]) {\n const texts = documents.map(({ pageContent }) => pageContent);\n const vectors = await this.embeddings.embedDocuments(texts);\n\n if (this.useInsert) {\n return this.addDocumentsWithVectors(vectors, documents);\n }\n return this.addVectors(vectors, documents);\n }\n\n /**\n * Adds the specified vectors to the store.\n * @param vectors The vectors to add.\n * @param documents The documents associated with the vectors.\n * @returns A promise that resolves when the vectors have been added.\n */\n async addVectors(vectors: number[][], documents: Document<TModel>[]) {\n // table name, column name cannot be parametrised\n // these fields are thus not escaped by Prisma and can be dangerous if user input is used\n const idColumnRaw = this.Prisma.raw(`\"${this.idColumn}\"`);\n const tableNameRaw = this.Prisma.raw(`\"${this.tableName}\"`);\n const vectorColumnRaw = this.Prisma.raw(`\"${this.vectorColumnName}\"`);\n\n await this.db.$transaction(\n vectors.map((vector, idx) => {\n const idValue = documents[idx].metadata[this.idColumn];\n const columnType = this.columnTypes?.[this.idColumn];\n\n // Apply type casting based on configured column type\n let whereClause;\n if (columnType === \"uuid\") {\n whereClause = this.Prisma.sql`${idColumnRaw} = ${idValue}::uuid`;\n } else if (columnType === \"integer\") {\n whereClause = this.Prisma.sql`${idColumnRaw} = ${idValue}::integer`;\n } else if (columnType === \"bigint\") {\n whereClause = this.Prisma.sql`${idColumnRaw} = ${idValue}::bigint`;\n } else {\n // Default behavior for backward compatibility\n whereClause = this.Prisma.sql`${idColumnRaw} = ${idValue}`;\n }\n\n return this.db.$executeRaw(\n this.Prisma.sql`UPDATE ${tableNameRaw}\n SET ${vectorColumnRaw} = ${`[${vector.join(\",\")}]`}::vector\n WHERE ${whereClause}\n `\n );\n })\n );\n }\n\n /**\n * Adds documents with their corresponding vectors to the store using INSERT statements.\n * This method ensures documents are created if they don't exist, making it compatible\n * with ParentDocumentRetriever which creates new child documents.\n * @param vectors The vectors to add.\n * @param documents The documents associated with the vectors.\n * @returns A promise that resolves when the documents have been added.\n */\n async addDocumentsWithVectors(\n vectors: number[][],\n documents: Document<TModel>[]\n ) {\n // table name, column name cannot be parametrised\n // these fields are thus not escaped by Prisma and can be dangerous if user input is used\n const tableNameRaw = this.Prisma.raw(`\"${this.tableName}\"`);\n const vectorColumnRaw = this.Prisma.raw(`\"${this.vectorColumnName}\"`);\n\n // Build column names for INSERT statement\n const columnNames = this.selectColumns.map((col) =>\n this.Prisma.raw(`\"${col}\"`)\n );\n const allColumns = [...columnNames, vectorColumnRaw];\n\n await this.db.$transaction(\n vectors.map((vector, idx) => {\n const document = documents[idx];\n const vectorString = `[${vector.join(\",\")}]`;\n\n // Build values for each column\n const columnValues = this.selectColumns.map((col) => {\n if (col === this.contentColumn) {\n return document.pageContent;\n }\n return document.metadata[col];\n });\n\n // Add vector as the last value\n const allValues = [\n ...columnValues,\n this.Prisma.sql`${vectorString}::vector`,\n ];\n\n return this.db.$executeRaw(\n this.Prisma.sql`\n INSERT INTO ${tableNameRaw} (${this.Prisma.join(allColumns, \", \")})\n VALUES (${this.Prisma.join(allValues, \", \")})\n `\n );\n })\n );\n }\n\n /**\n * Performs a similarity search with the specified query.\n * @param query The query to use for the similarity search.\n * @param k The number of results to return.\n * @param _filter The filter to apply to the results.\n * @param _callbacks The callbacks to use during the search.\n * @returns A promise that resolves with the search results.\n */\n async similaritySearch(\n query: string,\n k = 4,\n filter: this[\"FilterType\"] | undefined = undefined\n ): Promise<Document<SimilarityModel<TModel, TSelectModel>>[]> {\n const results = await this.similaritySearchVectorWithScore(\n await this.embeddings.embedQuery(query),\n k,\n filter\n );\n\n return results.map((result) => result[0]);\n }\n\n /**\n * Performs a similarity search with the specified query and returns the\n * results along with their scores.\n * @param query The query to use for the similarity search.\n * @param k The number of results to return.\n * @param filter The filter to apply to the results.\n * @param _callbacks The callbacks to use during the search.\n * @returns A promise that resolves with the search results and their scores.\n */\n async similaritySearchWithScore(\n query: string,\n k?: number,\n filter?: this[\"FilterType\"]\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ): Promise<[DocumentInterface<Record<string, any>>, number][]> {\n return super.similaritySearchWithScore(query, k, filter);\n }\n\n /**\n * Performs a similarity search with the specified vector and returns the\n * results along with their scores.\n * @param query The vector to use for the similarity search.\n * @param k The number of results to return.\n * @param filter The filter to apply to the results.\n * @returns A promise that resolves with the search results and their scores.\n */\n async similaritySearchVectorWithScore(\n query: number[],\n k: number,\n filter?: this[\"FilterType\"]\n ): Promise<[Document<SimilarityModel<TModel, TSelectModel>>, number][]> {\n // table name, column names cannot be parametrised\n // these fields are thus not escaped by Prisma and can be dangerous if user input is used\n const vectorColumnRaw = this.Prisma.raw(`\"${this.vectorColumnName}\"`);\n const tableNameRaw = this.Prisma.raw(`\"${this.tableName}\"`);\n const selectRaw = this.Prisma.raw(\n this.selectColumns.map((x) => `\"${x}\"`).join(\", \")\n );\n\n const vector = `[${query.join(\",\")}]`;\n const articles = await this.db.$queryRaw<\n Array<SimilarityModel<TModel, TSelectModel>>\n >(\n this.Prisma.join(\n [\n this.Prisma.sql`\n SELECT ${selectRaw}, ${vectorColumnRaw} <=> ${vector}::vector as \"_distance\"\n FROM ${tableNameRaw}\n `,\n this.buildSqlFilterStr(filter ?? this.filter),\n this.Prisma.sql`\n ORDER BY \"_distance\" ASC\n LIMIT ${k};\n `,\n ].filter((x) => x != null),\n \"\"\n )\n );\n\n const results: [Document<SimilarityModel<TModel, TSelectModel>>, number][] =\n [];\n for (const article of articles) {\n if (article._distance != null && article[this.contentColumn] != null) {\n results.push([\n new Document({\n pageContent: article[this.contentColumn] as string,\n metadata: article,\n }),\n article._distance,\n ]);\n }\n }\n\n return results;\n }\n\n buildSqlFilterStr(filter?: this[\"FilterType\"]) {\n if (filter == null) return null;\n return this.Prisma.join(\n Object.entries(filter).flatMap(([key, ops]) =>\n Object.entries(ops).map(([opName, value]) => {\n // column name, operators cannot be parametrised\n // these fields are thus not escaped by Prisma and can be dangerous if user input is used\n const opNameKey = opName as keyof typeof OpMap;\n const colRaw = this.Prisma.raw(`\"${key}\"`);\n const opRaw = this.Prisma.raw(OpMap[opNameKey]);\n const columnType = this.columnTypes?.[key];\n\n switch (OpMap[opNameKey]) {\n case OpMap.notIn:\n case OpMap.in: {\n if (!Array.isArray(value)) {\n throw new Error(\n `Invalid filter: IN operator requires an array. Received: ${JSON.stringify(\n value,\n null,\n 2\n )}`\n );\n }\n\n if (value.length === 0) {\n const isInOperator = OpMap[opNameKey] === OpMap.in;\n\n // For empty arrays:\n // - IN () should return FALSE (nothing can be in an empty set)\n // - NOT IN () should return TRUE (everything is not in an empty set)\n return this.Prisma.sql`${!isInOperator}`;\n }\n\n // Apply type casting for IN/NOT IN operators based on column type\n if (columnType === \"uuid\") {\n const castedValues = value.map(\n (v) => this.Prisma.sql`${v}::uuid`\n );\n return this.Prisma.sql`${colRaw} ${opRaw} (${this.Prisma.join(\n castedValues\n )})`;\n } else if (columnType === \"integer\") {\n const castedValues = value.map(\n (v) => this.Prisma.sql`${v}::integer`\n );\n return this.Prisma.sql`${colRaw} ${opRaw} (${this.Prisma.join(\n castedValues\n )})`;\n } else if (columnType === \"bigint\") {\n const castedValues = value.map(\n (v) => this.Prisma.sql`${v}::bigint`\n );\n return this.Prisma.sql`${colRaw} ${opRaw} (${this.Prisma.join(\n castedValues\n )})`;\n } else if (columnType === \"jsonb\") {\n const castedValues = value.map((v) => {\n const jsonValue =\n typeof v === \"object\" ? JSON.stringify(v) : v;\n return this.Prisma.sql`${jsonValue}::jsonb`;\n });\n return this.Prisma.sql`${colRaw} ${opRaw} (${this.Prisma.join(\n castedValues\n )})`;\n }\n\n return this.Prisma.sql`${colRaw} ${opRaw} (${this.Prisma.join(\n value\n )})`;\n }\n case OpMap.isNull:\n case OpMap.isNotNull:\n return this.Prisma.sql`${colRaw} ${opRaw}`;\n default:\n // Apply proper type casting based on column type\n if (columnType === \"uuid\") {\n return this.Prisma.sql`${colRaw} ${opRaw} ${value}::uuid`;\n } else if (columnType === \"integer\") {\n return this.Prisma.sql`${colRaw} ${opRaw} ${value}::integer`;\n } else if (columnType === \"bigint\") {\n return this.Prisma.sql`${colRaw} ${opRaw} ${value}::bigint`;\n } else if (columnType === \"jsonb\") {\n // For JSONB, cast the value to JSON string then to jsonb\n const jsonValue =\n typeof value === \"object\" ? JSON.stringify(value) : value;\n return this.Prisma.sql`${colRaw} ${opRaw} ${jsonValue}::jsonb`;\n } else if (columnType) {\n // For other specified types, apply the cast\n return this.Prisma\n .sql`${colRaw} ${opRaw} ${value}::${this.Prisma.raw(\n columnType\n )}`;\n } else {\n // Default behavior for backward compatibility - cast column to text\n return this.Prisma.sql`${colRaw}::text ${opRaw} ${value}`;\n }\n }\n })\n ),\n \" AND \",\n \" WHERE \"\n );\n }\n\n /**\n * Creates a new PrismaVectorStore from the specified texts.\n * @param texts The texts to use to create the store.\n * @param metadatas The metadata for the texts.\n * @param embeddings The embeddings to use.\n * @param dbConfig The database configuration.\n * @returns A promise that resolves with the new PrismaVectorStore.\n */\n static async fromTexts(\n texts: string[],\n metadatas: object[],\n embeddings: EmbeddingsInterface,\n dbConfig: {\n db: PrismaClient;\n prisma: PrismaNamespace;\n tableName: string;\n vectorColumnName: string;\n columns: ModelColumns<Record<string, unknown>>;\n columnTypes?: ColumnTypeConfig;\n useInsert?: boolean;\n }\n ): Promise<DefaultPrismaVectorStore> {\n const docs: Document[] = [];\n for (let i = 0; i < texts.length; i += 1) {\n const metadata = Array.isArray(metadatas) ? metadatas[i] : metadatas;\n const newDoc = new Document({\n pageContent: texts[i],\n metadata,\n });\n docs.push(newDoc);\n }\n\n return PrismaVectorStore.fromDocuments(docs, embeddings, dbConfig);\n }\n\n /**\n * Creates a new PrismaVectorStore from the specified documents.\n * @param docs The documents to use to create the store.\n * @param embeddings The embeddings to use.\n * @param dbConfig The database configuration.\n * @returns A promise that resolves with the new PrismaVectorStore.\n */\n static async fromDocuments(\n docs: Document[],\n embeddings: EmbeddingsInterface,\n dbConfig: {\n db: PrismaClient;\n prisma: PrismaNamespace;\n tableName: string;\n vectorColumnName: string;\n columns: ModelColumns<Record<string, unknown>>;\n columnTypes?: ColumnTypeConfig;\n useInsert?: boolean;\n }\n ): Promise<DefaultPrismaVectorStore> {\n const instance = new PrismaVectorStore(embeddings, dbConfig);\n await instance.addDocuments(docs);\n return instance;\n }\n}\n"],"mappings":"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"}