UNPKG

@langchain/community

Version:
1 lines • 20.8 kB
{"version":3,"file":"chroma.cjs","names":["VectorStore","embeddings: EmbeddingsInterface","args: ChromaLibArgs","documents: Document[]","options?: { ids?: string[] }","vectors: number[][]","newMetadata: Document[\"metadata\"]","params: ChromaDeleteParams<this[\"FilterType\"]>","query: number[]","k: number","filter?: this[\"FilterType\"]","results: [Document, number][]","metadata: Document[\"metadata\"]","Document","texts: string[]","metadatas: object[] | object","dbConfig: ChromaLibArgs","docs: Document[]","collectionName?: string"],"sources":["../../src/vectorstores/chroma.ts"],"sourcesContent":["import * as uuid from \"uuid\";\nimport type {\n ChromaClient as ChromaClientT,\n ChromaClientArgs,\n Collection,\n CollectionConfiguration,\n CollectionMetadata,\n Where,\n} from \"chromadb\";\n\nimport type { EmbeddingsInterface } from \"@langchain/core/embeddings\";\nimport { VectorStore } from \"@langchain/core/vectorstores\";\nimport { Document } from \"@langchain/core/documents\";\n\ntype SharedChromaLibArgs = {\n numDimensions?: number;\n collectionName?: string;\n filter?: object;\n collectionMetadata?: CollectionMetadata;\n collectionConfiguration?: CollectionConfiguration;\n chromaCloudAPIKey?: string;\n clientParams?: Omit<ChromaClientArgs, \"path\">;\n};\n\n/**\n * Defines the arguments that can be passed to the `Chroma` class\n * constructor. It can either contain a `url` for the Chroma database, the\n * number of dimensions for the vectors (`numDimensions`), a\n * `collectionName` for the collection to be used in the database, and a\n * `filter` object; or it can contain an `index` which is an instance of\n * `ChromaClientT`, along with the `numDimensions`, `collectionName`, and\n * `filter`.\n */\nexport type ChromaLibArgs =\n | ({\n url?: string;\n } & SharedChromaLibArgs)\n | ({\n index?: ChromaClientT;\n } & SharedChromaLibArgs);\n\n/**\n * Defines the parameters for the `delete` method in the `Chroma` class.\n * It can either contain an array of `ids` of the documents to be deleted\n * or a `filter` object to specify the documents to be deleted.\n */\nexport interface ChromaDeleteParams<T> {\n ids?: string[];\n filter?: T;\n}\n\n/**\n * Chroma vector store integration.\n *\n * Setup:\n * Install `@langchain/community` and `chromadb`.\n *\n * ```bash\n * npm install @langchain/community chromadb\n * ```\n *\n * ## [Constructor args](https://api.js.langchain.com/classes/langchain_community_vectorstores_chroma.Chroma.html#constructor)\n *\n * <details open>\n * <summary><strong>Instantiate</strong></summary>\n *\n * ```typescript\n * import { Chroma } from '@langchain/community/vectorstores/chroma';\n * // Or other embeddings\n * import { OpenAIEmbeddings } from '@langchain/openai';\n *\n * const embeddings = new OpenAIEmbeddings({\n * model: \"text-embedding-3-small\",\n * })\n *\n * const vectorStore = new Chroma(\n * embeddings,\n * {\n * collectionName: \"foo\",\n * host: \"localhost\",\n * }\n * );\n * ```\n * </details>\n *\n * <br />\n *\n * <details>\n * <summary><strong>Add documents</strong></summary>\n *\n * ```typescript\n * import type { Document } from '@langchain/core/documents';\n *\n * const document1 = { pageContent: \"foo\", metadata: { baz: \"bar\" } };\n * const document2 = { pageContent: \"thud\", metadata: { bar: \"baz\" } };\n * const document3 = { pageContent: \"I will be deleted :(\", metadata: {} };\n *\n * const documents: Document[] = [document1, document2, document3];\n * const ids = [\"1\", \"2\", \"3\"];\n * await vectorStore.addDocuments(documents, { ids });\n * ```\n * </details>\n *\n * <br />\n *\n * <details>\n * <summary><strong>Delete documents</strong></summary>\n *\n * ```typescript\n * await vectorStore.delete({ ids: [\"3\"] });\n * ```\n * </details>\n *\n * <br />\n *\n * <details>\n * <summary><strong>Similarity search</strong></summary>\n *\n * ```typescript\n * const results = await vectorStore.similaritySearch(\"thud\", 1);\n * for (const doc of results) {\n * console.log(`* ${doc.pageContent} [${JSON.stringify(doc.metadata, null)}]`);\n * }\n * // Output: * thud [{\"baz\":\"bar\"}]\n * ```\n * </details>\n *\n * <br />\n *\n *\n * <details>\n * <summary><strong>Similarity search with filter</strong></summary>\n *\n * ```typescript\n * const resultsWithFilter = await vectorStore.similaritySearch(\"thud\", 1, { baz: \"bar\" });\n *\n * for (const doc of resultsWithFilter) {\n * console.log(`* ${doc.pageContent} [${JSON.stringify(doc.metadata, null)}]`);\n * }\n * // Output: * foo [{\"baz\":\"bar\"}]\n * ```\n * </details>\n *\n * <br />\n *\n *\n * <details>\n * <summary><strong>Similarity search with score</strong></summary>\n *\n * ```typescript\n * const resultsWithScore = await vectorStore.similaritySearchWithScore(\"qux\", 1);\n * for (const [doc, score] of resultsWithScore) {\n * console.log(`* [SIM=${score.toFixed(6)}] ${doc.pageContent} [${JSON.stringify(doc.metadata, null)}]`);\n * }\n * // Output: * [SIM=0.000000] qux [{\"bar\":\"baz\",\"baz\":\"bar\"}]\n * ```\n * </details>\n *\n * <br />\n *\n * <details>\n * <summary><strong>As a retriever</strong></summary>\n *\n * ```typescript\n * const retriever = vectorStore.asRetriever({\n * searchType: \"mmr\", // Leave blank for standard similarity search\n * k: 1,\n * });\n * const resultAsRetriever = await retriever.invoke(\"thud\");\n * console.log(resultAsRetriever);\n *\n * // Output: [Document({ metadata: { \"baz\":\"bar\" }, pageContent: \"thud\" })]\n * ```\n * </details>\n *\n * <br />\n */\nexport class Chroma extends VectorStore {\n declare FilterType: Where;\n\n index?: ChromaClientT;\n\n collection?: Collection;\n\n collectionName: string;\n\n collectionMetadata?: CollectionMetadata;\n\n numDimensions?: number;\n\n clientParams?: Omit<ChromaClientArgs, \"path\">;\n\n url: string;\n\n filter?: object;\n\n _vectorstoreType(): string {\n return \"chroma\";\n }\n\n constructor(embeddings: EmbeddingsInterface, args: ChromaLibArgs) {\n super(embeddings, args);\n this.numDimensions = args.numDimensions;\n this.embeddings = embeddings;\n this.collectionName = ensureCollectionName(args.collectionName);\n this.collectionMetadata = args.collectionMetadata;\n this.clientParams = args.clientParams || {};\n if (\"index\" in args) {\n this.index = args.index;\n } else if (\"url\" in args) {\n this.url = args.url || \"http://localhost:8000\";\n }\n\n if (args.chromaCloudAPIKey) {\n this.clientParams.headers = {\n ...(this.clientParams?.headers || {}),\n \"x-chroma-token\": args.chromaCloudAPIKey,\n };\n }\n\n this.filter = args.filter;\n }\n\n /**\n * Adds documents to the Chroma database. The documents are first\n * converted to vectors using the `embeddings` instance, and then added to\n * the database.\n * @param documents An array of `Document` instances to be added to the database.\n * @param options Optional. An object containing an array of `ids` for the documents.\n * @returns A promise that resolves when the documents have been added to the database.\n */\n async addDocuments(documents: Document[], options?: { ids?: string[] }) {\n const texts = documents.map(({ pageContent }) => pageContent);\n return this.addVectors(\n await this.embeddings.embedDocuments(texts),\n documents,\n options\n );\n }\n\n /**\n * Ensures that a collection exists in the Chroma database. If the\n * collection does not exist, it is created.\n * @returns A promise that resolves with the `Collection` instance.\n */\n async ensureCollection(): Promise<Collection> {\n if (!this.collection) {\n if (!this.index) {\n this.index = new (await Chroma.imports()).ChromaClient({\n path: this.url,\n ...(this.clientParams ?? {}),\n });\n }\n try {\n this.collection = await this.index.getOrCreateCollection({\n name: this.collectionName,\n embeddingFunction: null,\n ...(this.collectionMetadata && { metadata: this.collectionMetadata }),\n });\n } catch (err) {\n throw new Error(`Chroma getOrCreateCollection error: ${err}`);\n }\n }\n\n return this.collection;\n }\n\n /**\n * Adds vectors to the Chroma database. The vectors are associated with\n * the provided documents.\n * @param vectors An array of vectors to be added to the database.\n * @param documents An array of `Document` instances associated with the vectors.\n * @param options Optional. An object containing an array of `ids` for the vectors.\n * @returns A promise that resolves with an array of document IDs when the vectors have been added to the database.\n */\n async addVectors(\n vectors: number[][],\n documents: Document[],\n options?: { ids?: string[] }\n ) {\n if (vectors.length === 0) {\n return [];\n }\n if (this.numDimensions === undefined) {\n this.numDimensions = vectors[0].length;\n }\n if (vectors.length !== documents.length) {\n throw new Error(`Vectors and metadatas must have the same length`);\n }\n if (vectors[0].length !== this.numDimensions) {\n throw new Error(\n `Vectors must have the same length as the number of dimensions (${this.numDimensions})`\n );\n }\n\n const documentIds =\n options?.ids ?? Array.from({ length: vectors.length }, () => uuid.v1());\n const collection = await this.ensureCollection();\n\n const mappedMetadatas = documents.map(({ metadata }) => {\n let locFrom;\n let locTo;\n\n if (metadata?.loc) {\n if (metadata.loc.lines?.from !== undefined)\n locFrom = metadata.loc.lines.from;\n if (metadata.loc.lines?.to !== undefined) locTo = metadata.loc.lines.to;\n }\n\n const newMetadata: Document[\"metadata\"] = {\n ...metadata,\n ...(locFrom !== undefined && { locFrom }),\n ...(locTo !== undefined && { locTo }),\n };\n\n if (newMetadata.loc) delete newMetadata.loc;\n\n return newMetadata;\n });\n\n await collection.upsert({\n ids: documentIds,\n embeddings: vectors,\n metadatas: mappedMetadatas,\n documents: documents.map(({ pageContent }) => pageContent),\n });\n return documentIds;\n }\n\n /**\n * Deletes documents from the Chroma database. The documents to be deleted\n * can be specified by providing an array of `ids` or a `filter` object.\n * @param params An object containing either an array of `ids` of the documents to be deleted or a `filter` object to specify the documents to be deleted.\n * @returns A promise that resolves when the specified documents have been deleted from the database.\n */\n async delete(params: ChromaDeleteParams<this[\"FilterType\"]>): Promise<void> {\n const collection = await this.ensureCollection();\n if (Array.isArray(params.ids)) {\n await collection.delete({ ids: params.ids });\n } else if (params.filter) {\n await collection.delete({\n where: { ...params.filter },\n });\n } else {\n throw new Error(`You must provide one of \"ids or \"filter\".`);\n }\n }\n\n /**\n * Searches for vectors in the Chroma database that are similar to the\n * provided query vector. The search can be filtered using the provided\n * `filter` object or the `filter` property of the `Chroma` instance.\n * @param query The query vector.\n * @param k The number of similar vectors to return.\n * @param filter Optional. A `filter` object to filter the search results.\n * @returns A promise that resolves with an array of tuples, each containing a `Document` instance and a similarity score.\n */\n async similaritySearchVectorWithScore(\n query: number[],\n k: number,\n filter?: this[\"FilterType\"]\n ) {\n if (filter && this.filter) {\n throw new Error(\"cannot provide both `filter` and `this.filter`\");\n }\n const _filter = filter ?? this.filter;\n const where = _filter === undefined ? undefined : { ..._filter };\n\n const collection = await this.ensureCollection();\n\n // similaritySearchVectorWithScore supports one query vector at a time\n // chroma supports multiple query vectors at a time\n const result = await collection.query({\n queryEmbeddings: [query],\n nResults: k,\n where,\n });\n\n const { ids, distances, documents, metadatas } = result;\n if (!ids || !distances || !documents || !metadatas) {\n return [];\n }\n // get the result data from the first and only query vector\n const [firstIds] = ids;\n const [firstDistances] = distances;\n const [firstDocuments] = documents;\n const [firstMetadatas] = metadatas;\n\n if (firstDistances.some((item) => item === null)) {\n return [];\n }\n\n const cleanDistances = firstDistances.filter((item) => item !== null);\n\n const results: [Document, number][] = [];\n for (let i = 0; i < firstIds.length; i += 1) {\n let metadata: Document[\"metadata\"] = firstMetadatas?.[i] ?? {};\n\n if (metadata.locFrom && metadata.locTo) {\n metadata = {\n ...metadata,\n loc: {\n lines: {\n from: metadata.locFrom,\n to: metadata.locTo,\n },\n },\n };\n\n delete metadata.locFrom;\n delete metadata.locTo;\n }\n\n results.push([\n new Document({\n pageContent: firstDocuments?.[i] ?? \"\",\n metadata,\n id: firstIds[i],\n }),\n cleanDistances[i],\n ]);\n }\n return results;\n }\n\n /**\n * Creates a new `Chroma` instance from an array of text strings. The text\n * strings are converted to `Document` instances and added to the Chroma\n * database.\n * @param texts An array of text strings.\n * @param metadatas An array of metadata objects or a single metadata object. If an array is provided, it must have the same length as the `texts` array.\n * @param embeddings An `Embeddings` instance used to generate embeddings for the documents.\n * @param dbConfig A `ChromaLibArgs` object containing the configuration for the Chroma database.\n * @returns A promise that resolves with a new `Chroma` instance.\n */\n static async fromTexts(\n texts: string[],\n metadatas: object[] | object,\n embeddings: EmbeddingsInterface,\n dbConfig: ChromaLibArgs\n ): Promise<Chroma> {\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 return this.fromDocuments(docs, embeddings, dbConfig);\n }\n\n /**\n * Creates a new `Chroma` instance from an array of `Document` instances.\n * The documents are added to the Chroma database.\n * @param docs An array of `Document` instances.\n * @param embeddings An `Embeddings` instance used to generate embeddings for the documents.\n * @param dbConfig A `ChromaLibArgs` object containing the configuration for the Chroma database.\n * @returns A promise that resolves with a new `Chroma` instance.\n */\n static async fromDocuments(\n docs: Document[],\n embeddings: EmbeddingsInterface,\n dbConfig: ChromaLibArgs\n ): Promise<Chroma> {\n const instance = new this(embeddings, dbConfig);\n await instance.addDocuments(docs);\n return instance;\n }\n\n /**\n * Creates a new `Chroma` instance from an existing collection in the\n * Chroma database.\n * @param embeddings An `Embeddings` instance used to generate embeddings for the documents.\n * @param dbConfig A `ChromaLibArgs` object containing the configuration for the Chroma database.\n * @returns A promise that resolves with a new `Chroma` instance.\n */\n static async fromExistingCollection(\n embeddings: EmbeddingsInterface,\n dbConfig: ChromaLibArgs\n ): Promise<Chroma> {\n const instance = new this(embeddings, dbConfig);\n await instance.ensureCollection();\n return instance;\n }\n\n /** @ignore */\n static async imports(): Promise<{\n ChromaClient: typeof ChromaClientT;\n }> {\n try {\n const { ChromaClient } = await import(\"chromadb\");\n return { ChromaClient };\n } catch {\n throw new Error(\n \"Please install chromadb as a dependency with, e.g. `npm install -S chromadb`\"\n );\n }\n }\n}\n\n/**\n * Generates a unique collection name if none is provided.\n */\nfunction ensureCollectionName(collectionName?: string) {\n if (!collectionName) {\n return `langchain-${uuid.v4()}`;\n }\n return collectionName;\n}\n"],"mappings":"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"}