@langchain/community
Version:
Third-party integrations for LangChain.js
1 lines • 27.5 kB
Source Map (JSON)
{"version":3,"file":"vectara.cjs","names":["DEFAULT_FILTER: VectaraFilter","VectorStore","args: VectaraLibArgs","FakeEmbeddings","_vectors: number[][]","_documents: Document[]","ids: string[]","documents: Document[]","doc_ids: string[]","doc_id: string","files: VectaraFile[]","metadatas: Record<string, unknown> | undefined","query: string","k: number","vectaraFilterObject: VectaraFilter","summary: VectaraSummary","combinedMetadata: Record<string, unknown>","item: { name: string; value: unknown }","res: SummaryResult","response: {\n text: string;\n metadata: Record<string, unknown>;\n score: number;\n }","Document","response","k?: number","filter?: VectaraFilter","_query: number[]","_k: number","_filter?: VectaraFilter | undefined","texts: string[]","metadatas: object | object[]","_embeddings: EmbeddingsInterface","docs: Document[]"],"sources":["../../src/vectorstores/vectara.ts"],"sourcesContent":["import * as uuid from \"uuid\";\nimport { Document } from \"@langchain/core/documents\";\nimport type { EmbeddingsInterface } from \"@langchain/core/embeddings\";\nimport { getEnvironmentVariable } from \"@langchain/core/utils/env\";\nimport { VectorStore } from \"@langchain/core/vectorstores\";\nimport {\n BaseCallbackConfig,\n Callbacks,\n} from \"@langchain/core/callbacks/manager\";\nimport { FakeEmbeddings } from \"@langchain/core/utils/testing\";\n\n/**\n * Interface for the arguments required to initialize a VectaraStore\n * instance.\n */\nexport interface VectaraLibArgs {\n customerId: number;\n corpusId: number | number[];\n apiKey: string;\n verbose?: boolean;\n source?: string;\n}\n\n/**\n * Interface for the headers required for Vectara API calls.\n */\ninterface VectaraCallHeader {\n headers: {\n \"x-api-key\": string;\n \"Content-Type\": string;\n \"customer-id\": string;\n \"X-Source\": string;\n };\n}\n\n/**\n * Interface for the file objects to be uploaded to Vectara.\n */\nexport interface VectaraFile {\n // The contents of the file to be uploaded.\n blob: Blob;\n // The name of the file to be uploaded.\n fileName: string;\n}\n\n/**\n * Interface for the context configuration used in Vectara API calls.\n */\nexport interface VectaraContextConfig {\n // The amount of context before. Ignored if sentences_before is set.\n charsBefore?: number;\n // The amount of context after. Ignored if sentences_after is set.\n charsAfter?: number;\n // The amount of context before, in sentences.\n sentencesBefore?: number;\n // The amount of context after, in sentences.\n sentencesAfter?: number;\n // The tag that wraps the snippet at the start.\n startTag?: string;\n // The tag that wraps the snippet at the end.\n endTag?: string;\n}\n\nexport interface MMRConfig {\n enabled?: boolean;\n mmrTopK?: number;\n diversityBias?: number;\n}\n\nexport interface VectaraSummary {\n // Whether to enable summarization.\n enabled: boolean;\n // The name of the summarizer+prompt combination to use for summarization.\n summarizerPromptName?: string;\n // Maximum number of results to summarize.\n maxSummarizedResults: number;\n // ISO 639-1 or ISO 639-3 language code for the response, or \"auto\" to indicate that\n // the auto-detected language of the incoming query should be used.\n responseLang: string;\n}\n\n// VectaraFilter holds all the arguments for result retrieval by Vectara\n// It's not really a filter, but a collection of arguments for the Vectara API\n// However, it's been named \"XXXFilter\" in other places, so we keep the name here for consistency.\nexport interface VectaraFilter extends BaseCallbackConfig {\n // The start position in the result set\n start?: number;\n // Example of a vectara filter string can be: \"doc.rating > 3.0 and part.lang = 'deu'\"\n // See https://docs.vectara.com/docs/search-apis/sql/filter-overview for more details.\n filter?: string;\n // Improve retrieval accuracy using Hybrid search, by adjusting the value of lambda (0...1)\n // between neural search and keyword-based search factors. Values between 0.01 and 0.2 tend to work well.\n // see https://docs.vectara.com/docs/api-reference/search-apis/lexical-matching for more details.\n lambda?: number;\n // See Vectara Search API docs for more details on the following options: https://docs.vectara.com/docs/api-reference/search-apis/search\n contextConfig?: VectaraContextConfig;\n mmrConfig?: MMRConfig;\n}\n\nexport const DEFAULT_FILTER: VectaraFilter = {\n start: 0,\n filter: \"\",\n lambda: 0.0,\n contextConfig: {\n sentencesBefore: 2,\n sentencesAfter: 2,\n startTag: \"<b>\",\n endTag: \"</b>\",\n },\n mmrConfig: {\n enabled: false,\n mmrTopK: 0,\n diversityBias: 0.0,\n },\n};\n\ninterface SummaryResult {\n documents: Document[];\n scores: number[];\n summary: string;\n}\n\nexport interface VectaraRetrieverInput {\n vectara: VectaraStore;\n topK: number;\n summaryConfig?: VectaraSummary;\n callbacks?: Callbacks;\n tags?: string[];\n metadata?: Record<string, unknown>;\n verbose?: boolean;\n}\n/**\n * Class for interacting with the Vectara API. Extends the VectorStore\n * class.\n */\nexport class VectaraStore extends VectorStore {\n get lc_secrets(): { [key: string]: string } {\n return {\n apiKey: \"VECTARA_API_KEY\",\n corpusId: \"VECTARA_CORPUS_ID\",\n customerId: \"VECTARA_CUSTOMER_ID\",\n };\n }\n\n get lc_aliases(): { [key: string]: string } {\n return {\n apiKey: \"vectara_api_key\",\n corpusId: \"vectara_corpus_id\",\n customerId: \"vectara_customer_id\",\n };\n }\n\n declare FilterType: VectaraFilter;\n\n private apiEndpoint = \"api.vectara.io\";\n\n private apiKey: string;\n\n private corpusId: number[];\n\n private customerId: number;\n\n private verbose: boolean;\n\n private source: string;\n\n private vectaraApiTimeoutSeconds = 60;\n\n _vectorstoreType(): string {\n return \"vectara\";\n }\n\n constructor(args: VectaraLibArgs) {\n // Vectara doesn't need embeddings, but we need to pass something to the parent constructor\n // The embeddings are abstracted out from the user in Vectara.\n super(new FakeEmbeddings(), args);\n\n const apiKey = args.apiKey ?? getEnvironmentVariable(\"VECTARA_API_KEY\");\n if (!apiKey) {\n throw new Error(\"Vectara api key is not provided.\");\n }\n this.apiKey = apiKey;\n this.source = args.source ?? \"langchainjs\";\n\n const corpusId =\n args.corpusId ??\n getEnvironmentVariable(\"VECTARA_CORPUS_ID\")\n ?.split(\",\")\n .map((id) => {\n const num = Number(id);\n if (Number.isNaN(num))\n throw new Error(\"Vectara corpus id is not a number.\");\n return num;\n });\n if (!corpusId) {\n throw new Error(\"Vectara corpus id is not provided.\");\n }\n\n if (typeof corpusId === \"number\") {\n this.corpusId = [corpusId];\n } else {\n if (corpusId.length === 0)\n throw new Error(\"Vectara corpus id is not provided.\");\n this.corpusId = corpusId;\n }\n\n const customerId =\n args.customerId ?? getEnvironmentVariable(\"VECTARA_CUSTOMER_ID\");\n if (!customerId) {\n throw new Error(\"Vectara customer id is not provided.\");\n }\n this.customerId = customerId;\n\n this.verbose = args.verbose ?? false;\n }\n\n /**\n * Returns a header for Vectara API calls.\n * @returns A Promise that resolves to a VectaraCallHeader object.\n */\n async getJsonHeader(): Promise<VectaraCallHeader> {\n return {\n headers: {\n \"x-api-key\": this.apiKey,\n \"Content-Type\": \"application/json\",\n \"customer-id\": this.customerId.toString(),\n \"X-Source\": this.source,\n },\n };\n }\n\n /**\n * Throws an error, as this method is not implemented. Use addDocuments\n * instead.\n * @param _vectors Not used.\n * @param _documents Not used.\n * @returns Does not return a value.\n */\n async addVectors(\n _vectors: number[][],\n _documents: Document[]\n ): Promise<void> {\n throw new Error(\n \"Method not implemented. Please call addDocuments instead.\"\n );\n }\n\n /**\n * Method to delete data from the Vectara corpus.\n * @param params an array of document IDs to be deleted\n * @returns Promise that resolves when the deletion is complete.\n */\n async deleteDocuments(ids: string[]): Promise<void> {\n if (ids && ids.length > 0) {\n const headers = await this.getJsonHeader();\n for (const id of ids) {\n const data = {\n customer_id: this.customerId,\n corpus_id: this.corpusId[0],\n document_id: id,\n };\n\n try {\n const controller = new AbortController();\n const timeout = setTimeout(\n () => controller.abort(),\n this.vectaraApiTimeoutSeconds * 1000\n );\n const response = await fetch(\n `https://${this.apiEndpoint}/v1/delete-doc`,\n {\n method: \"POST\",\n headers: headers?.headers,\n body: JSON.stringify(data),\n signal: controller.signal,\n }\n );\n clearTimeout(timeout);\n if (response.status !== 200) {\n throw new Error(\n `Vectara API returned status code ${response.status} when deleting document ${id}`\n );\n }\n } catch (e) {\n const error = new Error(`Error ${(e as Error).message}`);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (error as any).code = 500;\n throw error;\n }\n }\n } else {\n throw new Error(`no \"ids\" specified for deletion`);\n }\n }\n\n /**\n * Adds documents to the Vectara store.\n * @param documents An array of Document objects to add to the Vectara store.\n * @returns A Promise that resolves to an array of document IDs indexed in Vectara.\n */\n async addDocuments(documents: Document[]): Promise<string[]> {\n if (this.corpusId.length > 1)\n throw new Error(\"addDocuments does not support multiple corpus ids\");\n\n const headers = await this.getJsonHeader();\n const doc_ids: string[] = [];\n let countAdded = 0;\n for (const document of documents) {\n const doc_id: string = document.metadata?.document_id ?? uuid.v4();\n const data = {\n customer_id: this.customerId,\n corpus_id: this.corpusId[0],\n document: {\n document_id: doc_id,\n title: document.metadata?.title ?? \"\",\n metadata_json: JSON.stringify(document.metadata ?? {}),\n section: [\n {\n text: document.pageContent,\n },\n ],\n },\n };\n\n try {\n const controller = new AbortController();\n const timeout = setTimeout(\n () => controller.abort(),\n this.vectaraApiTimeoutSeconds * 1000\n );\n const response = await fetch(`https://${this.apiEndpoint}/v1/index`, {\n method: \"POST\",\n headers: headers?.headers,\n body: JSON.stringify(data),\n signal: controller.signal,\n });\n clearTimeout(timeout);\n const result = await response.json();\n if (\n result.status?.code !== \"OK\" &&\n result.status?.code !== \"ALREADY_EXISTS\"\n ) {\n const error = new Error(\n `Vectara API returned status code ${\n result.status?.code\n }: ${JSON.stringify(result.message)}`\n );\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (error as any).code = 500;\n throw error;\n } else {\n countAdded += 1;\n doc_ids.push(doc_id);\n }\n } catch (e) {\n const error = new Error(\n `Error ${(e as Error).message} while adding document`\n );\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (error as any).code = 500;\n throw error;\n }\n }\n if (this.verbose) {\n console.log(`Added ${countAdded} documents to Vectara`);\n }\n\n return doc_ids;\n }\n\n /**\n * Vectara provides a way to add documents directly via their API. This API handles\n * pre-processing and chunking internally in an optimal manner. This method is a wrapper\n * to utilize that API within LangChain.\n *\n * @param files An array of VectaraFile objects representing the files and their respective file names to be uploaded to Vectara.\n * @param metadata Optional. An array of metadata objects corresponding to each file in the `filePaths` array.\n * @returns A Promise that resolves to the number of successfully uploaded files.\n */\n async addFiles(\n files: VectaraFile[],\n metadatas: Record<string, unknown> | undefined = undefined\n ) {\n if (this.corpusId.length > 1)\n throw new Error(\"addFiles does not support multiple corpus ids\");\n\n const doc_ids: string[] = [];\n\n for (const [index, file] of files.entries()) {\n const md = metadatas ? metadatas[index] : {};\n\n const data = new FormData();\n data.append(\"file\", file.blob, file.fileName);\n data.append(\"doc-metadata\", JSON.stringify(md));\n\n const response = await fetch(\n `https://api.vectara.io/v1/upload?c=${this.customerId}&o=${this.corpusId[0]}&d=true`,\n {\n method: \"POST\",\n headers: {\n \"x-api-key\": this.apiKey,\n \"X-Source\": this.source,\n },\n body: data,\n }\n );\n\n const { status } = response;\n if (status === 409) {\n throw new Error(`File at index ${index} already exists in Vectara`);\n } else if (status !== 200) {\n throw new Error(`Vectara API returned status code ${status}`);\n } else {\n const result = await response.json();\n const doc_id = result.document.documentId;\n doc_ids.push(doc_id);\n }\n }\n\n if (this.verbose) {\n console.log(`Uploaded ${files.length} files to Vectara`);\n }\n\n return doc_ids;\n }\n\n /**\n * Performs a Vectara API call based on the arguments provided.\n * @param query The query string for the similarity search.\n * @param k Optional. The number of results to return. Default is 10.\n * @param filter Optional. A VectaraFilter object to refine the search results.\n * @returns A Promise that resolves to an array of tuples, each containing a Document and its score.\n */\n async vectaraQuery(\n query: string,\n k: number,\n vectaraFilterObject: VectaraFilter,\n summary: VectaraSummary = {\n enabled: false,\n maxSummarizedResults: 0,\n responseLang: \"eng\",\n }\n ): Promise<SummaryResult> {\n const headers = await this.getJsonHeader();\n const { start, filter, lambda, contextConfig, mmrConfig } =\n vectaraFilterObject;\n\n const corpusKeys = this.corpusId.map((corpusId) => ({\n customerId: this.customerId,\n corpusId,\n metadataFilter: filter,\n lexicalInterpolationConfig: { lambda },\n }));\n\n const data = {\n query: [\n {\n query,\n start,\n numResults: mmrConfig?.enabled ? mmrConfig.mmrTopK : k,\n contextConfig,\n ...(mmrConfig?.enabled\n ? {\n rerankingConfig: {\n rerankerId: 272725718,\n mmrConfig: { diversityBias: mmrConfig.diversityBias },\n },\n }\n : {}),\n corpusKey: corpusKeys,\n ...(summary?.enabled ? { summary: [summary] } : {}),\n },\n ],\n };\n\n const controller = new AbortController();\n const timeout = setTimeout(\n () => controller.abort(),\n this.vectaraApiTimeoutSeconds * 1000\n );\n const response = await fetch(`https://${this.apiEndpoint}/v1/query`, {\n method: \"POST\",\n headers: headers?.headers,\n body: JSON.stringify(data),\n signal: controller.signal,\n });\n clearTimeout(timeout);\n if (response.status !== 200) {\n throw new Error(`Vectara API returned status code ${response.status}`);\n }\n\n const result = await response.json();\n const responses = result.responseSet[0].response;\n const documents = result.responseSet[0].document;\n\n for (let i = 0; i < responses.length; i += 1) {\n const responseMetadata = responses[i].metadata;\n const documentMetadata = documents[responses[i].documentIndex].metadata;\n const combinedMetadata: Record<string, unknown> = {};\n\n responseMetadata.forEach((item: { name: string; value: unknown }) => {\n combinedMetadata[item.name] = item.value;\n });\n\n documentMetadata.forEach((item: { name: string; value: unknown }) => {\n combinedMetadata[item.name] = item.value;\n });\n\n responses[i].metadata = combinedMetadata;\n }\n\n const res: SummaryResult = {\n documents: responses.map(\n (response: {\n text: string;\n metadata: Record<string, unknown>;\n score: number;\n }) =>\n new Document({\n pageContent: response.text,\n metadata: response.metadata,\n })\n ),\n scores: responses.map(\n (response: {\n text: string;\n metadata: Record<string, unknown>;\n score: number;\n }) => response.score\n ),\n summary: result.responseSet[0].summary[0]?.text ?? \"\",\n };\n return res;\n }\n\n /**\n * Performs a similarity search and returns documents along with their\n * scores.\n * @param query The query string for the similarity search.\n * @param k Optional. The number of results to return. Default is 10.\n * @param filter Optional. A VectaraFilter object to refine the search results.\n * @returns A Promise that resolves to an array of tuples, each containing a Document and its score.\n */\n async similaritySearchWithScore(\n query: string,\n k?: number,\n filter?: VectaraFilter\n ): Promise<[Document, number][]> {\n const summaryResult = await this.vectaraQuery(\n query,\n k || 10,\n filter || DEFAULT_FILTER\n );\n const res = summaryResult.documents.map(\n (document, index) =>\n [document, summaryResult.scores[index]] as [Document, number]\n );\n return res;\n }\n\n /**\n * Performs a similarity search and returns documents.\n * @param query The query string for the similarity search.\n * @param k Optional. The number of results to return. Default is 10.\n * @param filter Optional. A VectaraFilter object to refine the search results.\n * @returns A Promise that resolves to an array of Document objects.\n */\n async similaritySearch(\n query: string,\n k?: number,\n filter?: VectaraFilter\n ): Promise<Document[]> {\n const documents = await this.similaritySearchWithScore(\n query,\n k || 10,\n filter || DEFAULT_FILTER\n );\n return documents.map((result) => result[0]);\n }\n\n /**\n * Throws an error, as this method is not implemented. Use\n * similaritySearch or similaritySearchWithScore instead.\n * @param _query Not used.\n * @param _k Not used.\n * @param _filter Not used.\n * @returns Does not return a value.\n */\n async similaritySearchVectorWithScore(\n _query: number[],\n _k: number,\n _filter?: VectaraFilter | undefined\n ): Promise<[Document, number][]> {\n throw new Error(\n \"Method not implemented. Please call similaritySearch or similaritySearchWithScore instead.\"\n );\n }\n\n /**\n * Creates a VectaraStore instance from texts.\n * @param texts An array of text strings.\n * @param metadatas Metadata for the texts. Can be a single object or an array of objects.\n * @param _embeddings Not used.\n * @param args A VectaraLibArgs object for initializing the VectaraStore instance.\n * @returns A Promise that resolves to a VectaraStore instance.\n */\n static fromTexts(\n texts: string[],\n metadatas: object | object[],\n _embeddings: EmbeddingsInterface,\n args: VectaraLibArgs\n ): Promise<VectaraStore> {\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 VectaraStore.fromDocuments(docs, new FakeEmbeddings(), args);\n }\n\n /**\n * Creates a VectaraStore instance from documents.\n * @param docs An array of Document objects.\n * @param _embeddings Not used.\n * @param args A VectaraLibArgs object for initializing the VectaraStore instance.\n * @returns A Promise that resolves to a VectaraStore instance.\n */\n static async fromDocuments(\n docs: Document[],\n _embeddings: EmbeddingsInterface,\n args: VectaraLibArgs\n ): Promise<VectaraStore> {\n const instance = new this(args);\n await instance.addDocuments(docs);\n return instance;\n }\n}\n"],"mappings":"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"}