genkitx-qdrant
Version:
Genkit AI framework plugin for the Qdrant vector database.
1 lines • 13.3 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.mts"],"sourcesContent":["import { EmbedderArgument } from '@genkit-ai/ai/embedder';\nimport {\n CommonRetrieverOptionsSchema,\n Document,\n indexerRef,\n retrieverRef,\n} from '@genkit-ai/ai/retriever';\nimport type { QdrantClientParams, Schemas } from '@qdrant/js-client-rest';\nimport { QdrantClient } from '@qdrant/js-client-rest';\nimport { z, type Genkit } from 'genkit';\nimport { genkitPlugin, type GenkitPlugin } from 'genkit/plugin';\nimport { v5 as uuidv5 } from 'uuid';\n\nconst FilterType: z.ZodType<Schemas['Filter']> = z.any();\n\nconst QdrantRetrieverOptionsSchema = CommonRetrieverOptionsSchema.extend({\n k: z.number().default(10),\n filter: FilterType.optional(),\n scoreThreshold: z.number().optional(),\n});\n\nexport const QdrantIndexerOptionsSchema = z.null().optional();\n\nconst CONTENT_PAYLOAD_KEY = 'content';\nconst METADATA_PAYLOAD_KEY = 'metadata';\nconst CONTENT_TYPE_KEY = '_content_type';\n\n/**\n * Parameters for the Qdrant plugin.\n */\ninterface QdrantPluginParams<E extends z.ZodTypeAny = z.ZodTypeAny> {\n /**\n * Parameters for instantiating `QdrantClient`.\n */\n clientParams: QdrantClientParams;\n /**\n * Name of the Qdrant collection.\n */\n collectionName: string;\n /**\n * Embedder to use for the retriever and indexer.\n */\n embedder: EmbedderArgument<E>;\n /**\n * Addtional options for the embedder.\n */\n embedderOptions?: z.infer<E>;\n /**\n * Document content key in the Qdrant payload.\n * Default is 'content'.\n */\n contentPayloadKey?: string;\n /**\n * Document metadata key in the Qdrant payload.\n * Default is 'metadata'.\n */\n metadataPayloadKey?: string;\n /**\n * Document data type key in the Qdrant payload.\n * Default is '_content_type'.\n * This is used to store the type of content.\n */\n dataTypePayloadKey?: string;\n /**\n * Additional options when creating a collection.\n */\n collectionCreateOptions?: Schemas['CreateCollection'];\n}\n\n/**\n * qdrantRetrieverRef function creates a retriever for Qdrant.\n * @param params The params for the new Qdrant retriever\n * @param params.collectionName The collection name for the Qdrant retriever\n * @param params.displayName A display name for the retriever. If not specified, the default label will be `Qdrant - <collectionName>`\n * @returns A reference to a Qdrant retriever.\n */\nexport const qdrantRetrieverRef = (\n collectionName: string,\n displayName: string | null = null,\n) => {\n return retrieverRef({\n name: `qdrant/${collectionName}`,\n info: {\n label: displayName ?? `Qdrant - ${collectionName}`,\n },\n configSchema: QdrantRetrieverOptionsSchema,\n });\n};\n\n/**\n * qdrantIndexerRef function creates an indexer for Qdrant.\n * @param params The params for the new Qdrant indexer.\n * @param params.collectionName The collection name for the Qdrant indexer.\n * @param params.displayName A display name for the indexer. If not specified, the default label will be `Qdrant - <collectionName>`\n * @returns A reference to a Qdrant indexer.\n */\nexport const qdrantIndexerRef = (\n collectionName: string,\n displayName: string | null = null,\n) => {\n return indexerRef({\n name: `qdrant/${collectionName}`,\n info: {\n label: displayName ?? `Qdrant - ${collectionName}`,\n },\n configSchema: QdrantIndexerOptionsSchema,\n });\n};\n\n/**\n * Qdrant plugin that provides the Qdrant retriever\n * and indexer\n */\nexport function qdrant<EmbedderCustomOptions extends z.ZodTypeAny>(\n params: QdrantPluginParams<EmbedderCustomOptions>[],\n): GenkitPlugin {\n return genkitPlugin('qdrant', async (ai) => {\n params.forEach((p) => configureQdrantRetriever(ai, p));\n params.forEach((p) => configureQdrantIndexer(ai, p));\n });\n}\n\nexport default qdrant;\n\nexport function configureQdrantRetriever<\n EmbedderCustomOptions extends z.ZodTypeAny,\n>(ai: Genkit, params: QdrantPluginParams<EmbedderCustomOptions>) {\n const {\n embedder,\n collectionName,\n embedderOptions,\n clientParams,\n contentPayloadKey,\n metadataPayloadKey,\n } = params;\n const client = new QdrantClient(clientParams);\n const contentKey = contentPayloadKey ?? CONTENT_PAYLOAD_KEY;\n const metadataKey = metadataPayloadKey ?? METADATA_PAYLOAD_KEY;\n const dataTypeKey = params.dataTypePayloadKey ?? CONTENT_TYPE_KEY;\n return ai.defineRetriever(\n {\n name: `qdrant/${collectionName}`,\n configSchema: QdrantRetrieverOptionsSchema,\n },\n async (content, options) => {\n await ensureCollection(params, false, ai);\n const queryEmbeddings = await ai.embed({\n embedder,\n content,\n options: embedderOptions,\n });\n const results = (\n await client.query(collectionName, {\n query: queryEmbeddings[0].embedding,\n limit: options.k,\n filter: options.filter,\n score_threshold: options.scoreThreshold,\n with_payload: [contentKey, metadataKey, dataTypeKey],\n with_vector: false,\n })\n ).points;\n const documents = results.map((result) => {\n const content = result.payload?.[contentKey] ?? '';\n const metadata = {\n ...(result.payload?.[metadataKey] ?? {}),\n _similarityScore: result.score,\n } as Record<string, unknown>;\n const dataType = result.payload?.[dataTypeKey] ?? 'text';\n return Document.fromData(\n content as string,\n dataType as string,\n metadata as Record<string, unknown>,\n ).toJSON();\n });\n return {\n documents,\n };\n },\n );\n}\n\nexport function configureQdrantIndexer<\n EmbedderCustomOptions extends z.ZodTypeAny,\n>(ai: Genkit, params: QdrantPluginParams<EmbedderCustomOptions>) {\n const {\n embedder,\n collectionName,\n embedderOptions,\n clientParams,\n contentPayloadKey,\n metadataPayloadKey,\n } = params;\n const client = new QdrantClient(clientParams);\n const contentKey = contentPayloadKey ?? CONTENT_PAYLOAD_KEY;\n const metadataKey = metadataPayloadKey ?? METADATA_PAYLOAD_KEY;\n const dataTypeKey = params.dataTypePayloadKey ?? CONTENT_TYPE_KEY;\n return ai.defineIndexer(\n {\n name: `qdrant/${collectionName}`,\n configSchema: QdrantIndexerOptionsSchema,\n },\n async (docs, options) => {\n await ensureCollection(params, true, ai);\n const embeddings = await Promise.all(\n docs.map((doc) =>\n ai.embed({\n embedder,\n content: doc,\n options: embedderOptions,\n }),\n ),\n );\n const points = embeddings\n .map((embeddingArr, i) => {\n const doc = docs[i];\n const embeddingDocs = doc.getEmbeddingDocuments(embeddingArr);\n return embeddingArr.map((docEmbedding, j) => {\n const embeddingDoc = embeddingDocs[j] || {};\n const id = uuidv5(JSON.stringify(embeddingDoc), uuidv5.URL);\n return {\n id,\n vector: docEmbedding.embedding,\n payload: {\n [contentKey]: embeddingDoc.data,\n [metadataKey]: embeddingDoc.metadata,\n [dataTypeKey]: embeddingDoc.dataType,\n },\n };\n });\n })\n .reduce((acc, val) => acc.concat(val), []);\n await client.upsert(collectionName, { points });\n },\n );\n}\n\n/**\n * Helper function for creating a Qdrant collection.\n */\nexport async function createQdrantCollection<\n EmbedderCustomOptions extends z.ZodTypeAny,\n>(params: QdrantPluginParams<EmbedderCustomOptions>, ai) {\n const { embedder, embedderOptions, clientParams, collectionName } = params;\n const client = new QdrantClient(clientParams);\n let collectionCreateOptions = params.collectionCreateOptions;\n if (!collectionCreateOptions) {\n const embeddings = await ai.embed({\n embedder,\n content: 'SOME_TEXT',\n options: embedderOptions,\n });\n const vector = Array.isArray(embeddings)\n ? embeddings[0].embedding\n : embeddings.embedding;\n collectionCreateOptions = {\n vectors: {\n size: vector.length,\n distance: 'Cosine',\n },\n };\n }\n return await client.createCollection(collectionName, collectionCreateOptions);\n}\n\n/**\n * Helper function for deleting Qdrant collections.\n */\nexport async function deleteQdrantCollection(params: QdrantPluginParams) {\n const client = new QdrantClient(params.clientParams);\n return await client.deleteCollection(params.collectionName);\n}\n\n/**\n * Private helper for ensuring that a Qdrant collection exists.\n */\nasync function ensureCollection(\n params: QdrantPluginParams,\n createCollection = true,\n ai?,\n) {\n const { clientParams, collectionName } = params;\n const client = new QdrantClient(clientParams);\n\n if ((await client.collectionExists(collectionName)).exists) {\n return;\n }\n\n if (createCollection) {\n await createQdrantCollection(params, ai);\n } else {\n throw new Error(\n `Collection ${collectionName} does not exist. Index some documents first.`,\n );\n }\n}\n"],"mappings":"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","names":["_a","content"]}