@semiont/vectors 0.5.28 → 0.5.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-Q7XXWZRC.js → chunk-WCD6P6QQ.js} +2 -2
- package/dist/{chunk-Q7XXWZRC.js.map → chunk-WCD6P6QQ.js.map} +1 -1
- package/dist/index.js +3 -3
- package/dist/qdrant-EUQ53YHP.js +3 -0
- package/dist/{qdrant-JMDT7ZI5.js.map → qdrant-EUQ53YHP.js.map} +1 -1
- package/package.json +5 -5
- package/dist/qdrant-JMDT7ZI5.js +0 -3
|
@@ -301,5 +301,5 @@ var QdrantVectorStore = class _QdrantVectorStore {
|
|
|
301
301
|
};
|
|
302
302
|
|
|
303
303
|
export { QdrantVectorStore, mergeByResource };
|
|
304
|
-
//# sourceMappingURL=chunk-
|
|
305
|
-
//# sourceMappingURL=chunk-
|
|
304
|
+
//# sourceMappingURL=chunk-WCD6P6QQ.js.map
|
|
305
|
+
//# sourceMappingURL=chunk-WCD6P6QQ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/store/merge.ts","../src/store/qdrant.ts"],"names":[],"mappings":"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","file":"chunk-Q7XXWZRC.js","sourcesContent":["/**\n * Chunk→resource max-sim merge.\n *\n * Vector search returns *chunk*-level hits: one resource can match on several\n * of its chunks, and a caller that wants a list of resources has to fold them.\n * The fold is max-sim (late interaction): a resource scores as its single\n * best-matching chunk, and carries that chunk's text — so the caller can show\n * the passage that actually matched. Averaging instead would blur a\n * multi-topic resource into a vague centroid and lose which passage hit;\n * keeping the first hit seen would make the result order-dependent.\n *\n * Three callers share this: both `searchByResource` implementations (qdrant\n * batches one query per source chunk; memory scores every candidate against\n * every source chunk) and the SEMANTIC-FALLBACK fold over raw `searchResources`\n * output, whose hits map one-to-one with no dedup. All three normalise to\n * `VectorSearchResult[]` first, so this fold is the only copy of the logic.\n *\n * Deliberately does NOT slice to a limit: `searchByResource` and the fallback\n * want different slices, and a fold that silently truncates is the kind of\n * hidden cap that reads as \"covered everything\" when it didn't.\n */\n\nimport type { VectorSearchResult } from './interface';\n\n/**\n * Fold chunk-level hits to one entry per resource — the highest-scoring chunk\n * wins, carrying its own text and metadata — sorted score-descending.\n */\nexport function mergeByResource(hits: VectorSearchResult[]): VectorSearchResult[] {\n const bestByResource = new Map<string, VectorSearchResult>();\n\n for (const hit of hits) {\n const key = String(hit.resourceId);\n const prev = bestByResource.get(key);\n if (!prev || hit.score > prev.score) bestByResource.set(key, hit);\n }\n\n return [...bestByResource.values()].sort((a, b) => b.score - a.score);\n}\n","/**\n * Qdrant VectorStore Implementation\n *\n * Uses the Qdrant REST API via @qdrant/js-client-rest.\n * Manages two collections: 'resources' and 'annotations'.\n */\n\nimport { createHash } from 'crypto';\nimport type { QdrantClient, Schemas } from '@qdrant/js-client-rest';\nimport type { ResourceId, AnnotationId } from '@semiont/core';\nimport type { VectorStore, EmbeddingChunk, AnnotationPayload, VectorSearchResult, SearchOptions, ResourceStamp } from './interface';\nimport { mergeByResource } from './merge';\n\n/**\n * Generate a deterministic UUID v5-style ID from an arbitrary string.\n * Qdrant requires point IDs to be UUIDs or unsigned integers.\n */\nfunction toQdrantId(input: string): string {\n const hex = createHash('md5').update(input).digest('hex');\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;\n}\n\n/**\n * Map a scored point to the store-agnostic result shape. Shared by every read\n * path so the payload→result contract (including `machineRead`) has one home.\n */\nfunction toSearchResult(point: Schemas['ScoredPoint']): VectorSearchResult {\n const payload = point.payload ?? {};\n return {\n id: String(point.id),\n score: point.score,\n resourceId: payload.resourceId as ResourceId,\n annotationId: payload.annotationId as AnnotationId | undefined,\n text: payload.text as string,\n entityTypes: payload.entityTypes as string[] | undefined,\n ...(payload.machineRead ? { machineRead: true } : {}),\n };\n}\n\nexport interface QdrantConfig {\n host: string;\n port: number;\n /** Resolves the embedding dimensionality; called only when creating a collection. */\n dimensions: () => Promise<number>;\n}\n\n/** The payload fields a stamp is read from — one list for the scroll and the\n * targeted read, so the two cannot drift. */\nconst STAMP_FIELDS = ['resourceId', 'contentChecksum', 'entityTypes', 'machineRead'];\n\nfunction toStamp(payload: Record<string, unknown> | null | undefined): ResourceStamp {\n const checksum = payload?.contentChecksum;\n const entityTypes = payload?.entityTypes;\n return {\n contentChecksum: typeof checksum === 'string' ? checksum : undefined,\n entityTypes: Array.isArray(entityTypes)\n ? entityTypes.filter((t): t is string => typeof t === 'string')\n : [],\n ...(payload?.machineRead ? { machineRead: true } : {}),\n };\n}\n\nexport class QdrantVectorStore implements VectorStore {\n /**\n * Per-batch point over-fetch for `searchByResource`. The batch limit caps\n * points while the caller wants resources, so multi-chunk targets would\n * otherwise crowd the top-K. See the call site.\n */\n private static readonly SEARCH_BY_RESOURCE_OVER_FETCH = 4;\n\n private client: QdrantClient | null = null;\n private config: QdrantConfig;\n\n constructor(config: QdrantConfig) {\n this.config = config;\n }\n\n private get qdrant(): QdrantClient {\n if (!this.client) throw new Error('QdrantVectorStore is not connected');\n return this.client;\n }\n\n async connect(): Promise<void> {\n const { QdrantClient } = await import('@qdrant/js-client-rest');\n this.client = new QdrantClient({\n host: this.config.host,\n port: this.config.port,\n });\n\n // Ensure collections exist\n await this.ensureCollection('resources');\n await this.ensureCollection('annotations');\n // Payload indexes so filtered operations scale:\n // - entityTypes: the excludeEntityTypes recall filter.\n // - resourceId: searchByResource's by-resource scroll + self-exclusion, and\n // the per-resource delete paths (deleteResourceVectors /\n // deleteAnnotationVectorsForResource).\n await this.ensurePayloadIndex('resources', 'entityTypes');\n await this.ensurePayloadIndex('resources', 'resourceId');\n await this.ensurePayloadIndex('annotations', 'resourceId');\n }\n\n async disconnect(): Promise<void> {\n this.client = null;\n }\n\n async clearAll(): Promise<void> {\n try { await this.qdrant.deleteCollection('resources'); } catch { /* may not exist */ }\n try { await this.qdrant.deleteCollection('annotations'); } catch { /* may not exist */ }\n await this.ensureCollection('resources');\n await this.ensureCollection('annotations');\n }\n\n isConnected(): boolean {\n return this.client !== null;\n }\n\n private async ensureCollection(name: string): Promise<void> {\n try {\n await this.qdrant.getCollection(name);\n return;\n } catch { /* absent — create it below, which is the only path needing the size */ }\n\n // The dimensionality is discovered from the embedding provider, so it is\n // resolved HERE and nowhere else: an existing collection already encodes\n // its vector size, and consulting the provider to re-derive a number we\n // would not use is exactly the eager-probe coupling this avoids.\n await this.qdrant.createCollection(name, {\n vectors: { size: await this.config.dimensions(), distance: 'Cosine' },\n });\n }\n\n /**\n * Idempotently create a keyword payload index. Qdrant accepts a repeat call\n * for an already-indexed field, so this runs safely on every connect and\n * back-fills the index on collections created before the field was indexed.\n */\n private async ensurePayloadIndex(collection: string, field: string): Promise<void> {\n try {\n await this.qdrant.createPayloadIndex(collection, { field_name: field, field_schema: 'keyword' });\n } catch { /* already indexed, or created concurrently */ }\n }\n\n async upsertResourceVectors(resourceId: ResourceId, chunks: EmbeddingChunk[], contentChecksum: string, entityTypes: string[], machineRead?: boolean): Promise<void> {\n // Replace semantics: purge existing chunks first, or a resource that\n // shrinks leaves orphan points at the higher chunk indices.\n await this.deleteResourceVectors(resourceId);\n if (chunks.length === 0) return;\n\n const points = chunks.map((chunk) => ({\n id: toQdrantId(`${resourceId}-${chunk.chunkIndex}`),\n vector: chunk.embedding,\n payload: {\n resourceId: String(resourceId),\n chunkIndex: chunk.chunkIndex,\n text: chunk.text,\n contentChecksum,\n entityTypes,\n // Only stamped when true: absence is the common case and carries no\n // claim, so a native extraction stores nothing extra.\n ...(machineRead ? { machineRead: true } : {}),\n },\n }));\n\n await this.qdrant.upsert('resources', { points });\n }\n\n async upsertAnnotationVector(\n annotationId: AnnotationId,\n embedding: number[],\n payload: AnnotationPayload\n ): Promise<void> {\n await this.qdrant.upsert('annotations', {\n points: [{\n id: toQdrantId(String(annotationId)),\n vector: embedding,\n payload: {\n annotationId: String(payload.annotationId),\n resourceId: String(payload.resourceId),\n motivation: payload.motivation,\n entityTypes: payload.entityTypes,\n text: payload.exactText,\n ...(payload.machineRead ? { machineRead: true } : {}),\n },\n }],\n });\n }\n\n async deleteResourceVectors(resourceId: ResourceId): Promise<void> {\n await this.qdrant.delete('resources', {\n filter: {\n must: [{ key: 'resourceId', match: { value: String(resourceId) } }],\n },\n });\n }\n\n async deleteAnnotationVector(annotationId: AnnotationId): Promise<void> {\n await this.qdrant.delete('annotations', {\n points: [toQdrantId(String(annotationId))],\n });\n }\n\n async deleteAnnotationVectorsForResource(resourceId: ResourceId): Promise<void> {\n await this.qdrant.delete('annotations', {\n filter: {\n must: [{ key: 'resourceId', match: { value: String(resourceId) } }],\n },\n });\n }\n\n async count(): Promise<number> {\n const [resources, annotations] = await Promise.all([\n this.qdrant.count('resources', { exact: true }),\n this.qdrant.count('annotations', { exact: true }),\n ]);\n return resources.count + annotations.count;\n }\n\n async updateResourceEntityTypes(resourceId: ResourceId, entityTypes: string[]): Promise<void> {\n // Payload-only rewrite across the resource's points — no vectors touched,\n // no embedding involved (S13). Qdrant set_payload with a filter is a\n // no-op when the resource has no points.\n await this.qdrant.setPayload('resources', {\n payload: { entityTypes },\n filter: {\n must: [{ key: 'resourceId', match: { value: String(resourceId) } }],\n },\n });\n }\n\n async getResourceStamp(resourceId: ResourceId): Promise<ResourceStamp | undefined> {\n const page = await this.qdrant.scroll('resources', {\n limit: 1,\n filter: { must: [{ key: 'resourceId', match: { value: String(resourceId) } }] },\n with_payload: STAMP_FIELDS,\n with_vector: false,\n });\n const point = page.points[0];\n return point ? toStamp(point.payload) : undefined;\n }\n\n async listResourceStamps(): Promise<Map<string, ResourceStamp>> {\n const stamps = new Map<string, ResourceStamp>();\n let offset: Schemas['ScrollRequest']['offset'] = undefined;\n do {\n const page = await this.qdrant.scroll('resources', {\n limit: 1000,\n offset,\n with_payload: STAMP_FIELDS,\n with_vector: false,\n });\n for (const point of page.points) {\n const rid = point.payload?.resourceId;\n if (typeof rid !== 'string' || stamps.has(rid)) continue;\n stamps.set(rid, toStamp(point.payload));\n }\n offset = page.next_page_offset ?? undefined;\n } while (offset !== undefined && offset !== null);\n return stamps;\n }\n\n async listAnnotationIds(): Promise<Set<string>> {\n return this.scrollPayloadField('annotations', 'annotationId');\n }\n\n /** Collect the distinct values of one payload field across a collection. */\n private async scrollPayloadField(collection: string, field: string): Promise<Set<string>> {\n const values = new Set<string>();\n let offset: Schemas['ScrollRequest']['offset'] = undefined;\n do {\n const page = await this.qdrant.scroll(collection, {\n limit: 1000,\n offset,\n with_payload: [field],\n with_vector: false,\n });\n for (const point of page.points) {\n const value = point.payload?.[field];\n if (typeof value === 'string') values.add(value);\n }\n offset = page.next_page_offset ?? undefined;\n } while (offset !== undefined && offset !== null);\n return values;\n }\n\n async searchResources(embedding: number[], opts: SearchOptions): Promise<VectorSearchResult[]> {\n return this.search('resources', embedding, opts);\n }\n\n async searchAnnotations(embedding: number[], opts: SearchOptions): Promise<VectorSearchResult[]> {\n return this.search('annotations', embedding, opts);\n }\n\n async searchByResource(resourceId: ResourceId, opts: SearchOptions): Promise<VectorSearchResult[]> {\n // Fetch the resource's stored chunk vectors (page through all of them so a\n // long resource isn't silently truncated).\n const queryVectors: number[][] = [];\n let offset: Schemas['ScrollRequest']['offset'] = undefined;\n do {\n const page = await this.qdrant.scroll('resources', {\n filter: { must: [{ key: 'resourceId', match: { value: String(resourceId) } }] },\n with_vector: true,\n with_payload: false,\n limit: 256,\n offset,\n });\n for (const point of page.points) {\n if (Array.isArray(point.vector)) queryVectors.push(point.vector as number[]);\n }\n offset = page.next_page_offset ?? undefined;\n } while (offset !== undefined && offset !== null);\n\n if (queryVectors.length === 0) return [];\n\n // Self-exclude the source; carry the caller's filter (e.g. excludeEntityTypes).\n const filter = this.buildFilter({ ...opts.filter, excludeResourceId: resourceId });\n\n // One batched query per source chunk (single round-trip). Each batch's\n // `limit` caps POINTS, but the merge below yields RESOURCES — so a target\n // with many chunks can fill several point-slots and crowd out resources\n // that belong in the top-`limit` after folding. Over-fetch per batch to\n // leave the merge material to work with; the memory store scores every\n // candidate exhaustively, and without this the two backends disagree on\n // recall. Headroom, not a guarantee: a resource whose chunks are all\n // outranked by OVER_FETCH×limit points in every batch is still missed.\n // Qdrant's group-by would make it exact, but only via the `search`-family\n // endpoints 1.19.0 removed (see qdrant-query-api.test.ts).\n const searches = queryVectors.map((vector) => ({\n query: vector,\n limit: opts.limit * QdrantVectorStore.SEARCH_BY_RESOURCE_OVER_FETCH,\n score_threshold: opts.scoreThreshold,\n filter: filter ?? undefined,\n with_payload: true,\n }));\n const batches = await this.qdrant.queryBatch('resources', { searches });\n\n // Normalise to VectorSearchResult, then fold chunk hits to one entry per\n // resource (max-sim) via the shared merge; slice to the caller's limit.\n const hits = batches.flatMap((batch) => batch.points.map((r) => toSearchResult(r)));\n return mergeByResource(hits).slice(0, opts.limit);\n }\n\n private async search(collection: string, embedding: number[], opts: SearchOptions): Promise<VectorSearchResult[]> {\n const filter = this.buildFilter(opts.filter);\n\n // `query`, not `search`: the REST client dropped `search`/`searchBatch` in\n // 1.19.0 in favour of the universal query endpoint. Same request but the\n // vector moves to `query`, and the response is wrapped in `{ points }`.\n const { points } = await this.qdrant.query(collection, {\n query: embedding,\n limit: opts.limit,\n score_threshold: opts.scoreThreshold,\n filter: filter ?? undefined,\n with_payload: true,\n });\n\n return points.map((r) => toSearchResult(r));\n }\n\n private buildFilter(filter?: SearchOptions['filter']): Schemas['Filter'] | null {\n if (!filter) return null;\n\n const must: Schemas['FieldCondition'][] = [];\n\n if (filter.entityTypes && filter.entityTypes.length > 0) {\n // any-of: match payloads whose `entityTypes` array contains at least one\n // of the requested types. Matches the memory store's `some(t => ...)`\n // semantics; pushing one `must` clause per type would mean all-of.\n must.push({ key: 'entityTypes', match: { any: filter.entityTypes } });\n }\n\n if (filter.resourceId) {\n must.push({ key: 'resourceId', match: { value: String(filter.resourceId) } });\n }\n\n if (filter.motivation) {\n must.push({ key: 'motivation', match: { value: filter.motivation } });\n }\n\n const must_not: Schemas['FieldCondition'][] = [];\n\n if (filter.excludeResourceId) {\n must_not.push({ key: 'resourceId', match: { value: String(filter.excludeResourceId) } });\n }\n\n if (filter.excludeEntityTypes && filter.excludeEntityTypes.length > 0) {\n // any-of exclusion: drop points whose entityTypes contain any of these.\n must_not.push({ key: 'entityTypes', match: { any: filter.excludeEntityTypes } });\n }\n\n if (must.length === 0 && must_not.length === 0) return null;\n\n return {\n ...(must.length > 0 ? { must } : {}),\n ...(must_not.length > 0 ? { must_not } : {}),\n };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/store/merge.ts","../src/store/qdrant.ts"],"names":[],"mappings":"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","file":"chunk-WCD6P6QQ.js","sourcesContent":["/**\n * Chunk→resource max-sim merge.\n *\n * Vector search returns *chunk*-level hits: one resource can match on several\n * of its chunks, and a caller that wants a list of resources has to fold them.\n * The fold is max-sim (late interaction): a resource scores as its single\n * best-matching chunk, and carries that chunk's text — so the caller can show\n * the passage that actually matched. Averaging instead would blur a\n * multi-topic resource into a vague centroid and lose which passage hit;\n * keeping the first hit seen would make the result order-dependent.\n *\n * Three callers share this: both `searchByResource` implementations (qdrant\n * batches one query per source chunk; memory scores every candidate against\n * every source chunk) and the SEMANTIC-FALLBACK fold over raw `searchResources`\n * output, whose hits map one-to-one with no dedup. All three normalise to\n * `VectorSearchResult[]` first, so this fold is the only copy of the logic.\n *\n * Deliberately does NOT slice to a limit: `searchByResource` and the fallback\n * want different slices, and a fold that silently truncates is the kind of\n * hidden cap that reads as \"covered everything\" when it didn't.\n */\n\nimport type { VectorSearchResult } from './interface';\n\n/**\n * Fold chunk-level hits to one entry per resource — the highest-scoring chunk\n * wins, carrying its own text and metadata — sorted score-descending.\n */\nexport function mergeByResource(hits: VectorSearchResult[]): VectorSearchResult[] {\n const bestByResource = new Map<string, VectorSearchResult>();\n\n for (const hit of hits) {\n const key = String(hit.resourceId);\n const prev = bestByResource.get(key);\n if (!prev || hit.score > prev.score) bestByResource.set(key, hit);\n }\n\n return [...bestByResource.values()].sort((a, b) => b.score - a.score);\n}\n","/**\n * Qdrant VectorStore Implementation\n *\n * Uses the Qdrant REST API via @qdrant/js-client-rest.\n * Manages two collections: 'resources' and 'annotations'.\n */\n\nimport { createHash } from 'crypto';\nimport type { QdrantClient, Schemas } from '@qdrant/js-client-rest';\nimport type { ResourceId, AnnotationId } from '@semiont/core';\nimport type { VectorStore, EmbeddingChunk, AnnotationPayload, VectorSearchResult, SearchOptions, ResourceStamp } from './interface';\nimport { mergeByResource } from './merge';\n\n/**\n * Generate a deterministic UUID v5-style ID from an arbitrary string.\n * Qdrant requires point IDs to be UUIDs or unsigned integers.\n */\nfunction toQdrantId(input: string): string {\n const hex = createHash('md5').update(input).digest('hex');\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;\n}\n\n/**\n * Map a scored point to the store-agnostic result shape. Shared by every read\n * path so the payload→result contract (including `machineRead`) has one home.\n */\nfunction toSearchResult(point: Schemas['ScoredPoint']): VectorSearchResult {\n const payload = point.payload ?? {};\n return {\n id: String(point.id),\n score: point.score,\n resourceId: payload.resourceId as ResourceId,\n annotationId: payload.annotationId as AnnotationId | undefined,\n text: payload.text as string,\n entityTypes: payload.entityTypes as string[] | undefined,\n ...(payload.machineRead ? { machineRead: true } : {}),\n };\n}\n\nexport interface QdrantConfig {\n host: string;\n port: number;\n /** Resolves the embedding dimensionality; called only when creating a collection. */\n dimensions: () => Promise<number>;\n}\n\n/** The payload fields a stamp is read from — one list for the scroll and the\n * targeted read, so the two cannot drift. */\nconst STAMP_FIELDS = ['resourceId', 'contentChecksum', 'entityTypes', 'machineRead'];\n\nfunction toStamp(payload: Record<string, unknown> | null | undefined): ResourceStamp {\n const checksum = payload?.contentChecksum;\n const entityTypes = payload?.entityTypes;\n return {\n contentChecksum: typeof checksum === 'string' ? checksum : undefined,\n entityTypes: Array.isArray(entityTypes)\n ? entityTypes.filter((t): t is string => typeof t === 'string')\n : [],\n ...(payload?.machineRead ? { machineRead: true } : {}),\n };\n}\n\nexport class QdrantVectorStore implements VectorStore {\n /**\n * Per-batch point over-fetch for `searchByResource`. The batch limit caps\n * points while the caller wants resources, so multi-chunk targets would\n * otherwise crowd the top-K. See the call site.\n */\n private static readonly SEARCH_BY_RESOURCE_OVER_FETCH = 4;\n\n private client: QdrantClient | null = null;\n private config: QdrantConfig;\n\n constructor(config: QdrantConfig) {\n this.config = config;\n }\n\n private get qdrant(): QdrantClient {\n if (!this.client) throw new Error('QdrantVectorStore is not connected');\n return this.client;\n }\n\n async connect(): Promise<void> {\n const { QdrantClient } = await import('@qdrant/js-client-rest');\n this.client = new QdrantClient({\n host: this.config.host,\n port: this.config.port,\n });\n\n // Ensure collections exist\n await this.ensureCollection('resources');\n await this.ensureCollection('annotations');\n // Payload indexes so filtered operations scale:\n // - entityTypes: the excludeEntityTypes recall filter.\n // - resourceId: searchByResource's by-resource scroll + self-exclusion, and\n // the per-resource delete paths (deleteResourceVectors /\n // deleteAnnotationVectorsForResource).\n await this.ensurePayloadIndex('resources', 'entityTypes');\n await this.ensurePayloadIndex('resources', 'resourceId');\n await this.ensurePayloadIndex('annotations', 'resourceId');\n }\n\n async disconnect(): Promise<void> {\n this.client = null;\n }\n\n async clearAll(): Promise<void> {\n try { await this.qdrant.deleteCollection('resources'); } catch { /* may not exist */ }\n try { await this.qdrant.deleteCollection('annotations'); } catch { /* may not exist */ }\n await this.ensureCollection('resources');\n await this.ensureCollection('annotations');\n }\n\n isConnected(): boolean {\n return this.client !== null;\n }\n\n private async ensureCollection(name: string): Promise<void> {\n try {\n await this.qdrant.getCollection(name);\n return;\n } catch { /* absent — create it below, which is the only path needing the size */ }\n\n // The dimensionality is discovered from the embedding provider, so it is\n // resolved HERE and nowhere else: an existing collection already encodes\n // its vector size, and consulting the provider to re-derive a number we\n // would not use is exactly the eager-probe coupling this avoids.\n await this.qdrant.createCollection(name, {\n vectors: { size: await this.config.dimensions(), distance: 'Cosine' },\n });\n }\n\n /**\n * Idempotently create a keyword payload index. Qdrant accepts a repeat call\n * for an already-indexed field, so this runs safely on every connect and\n * back-fills the index on collections created before the field was indexed.\n */\n private async ensurePayloadIndex(collection: string, field: string): Promise<void> {\n try {\n await this.qdrant.createPayloadIndex(collection, { field_name: field, field_schema: 'keyword' });\n } catch { /* already indexed, or created concurrently */ }\n }\n\n async upsertResourceVectors(resourceId: ResourceId, chunks: EmbeddingChunk[], contentChecksum: string, entityTypes: string[], machineRead?: boolean): Promise<void> {\n // Replace semantics: purge existing chunks first, or a resource that\n // shrinks leaves orphan points at the higher chunk indices.\n await this.deleteResourceVectors(resourceId);\n if (chunks.length === 0) return;\n\n const points = chunks.map((chunk) => ({\n id: toQdrantId(`${resourceId}-${chunk.chunkIndex}`),\n vector: chunk.embedding,\n payload: {\n resourceId: String(resourceId),\n chunkIndex: chunk.chunkIndex,\n text: chunk.text,\n contentChecksum,\n entityTypes,\n // Only stamped when true: absence is the common case and carries no\n // claim, so a native extraction stores nothing extra.\n ...(machineRead ? { machineRead: true } : {}),\n },\n }));\n\n await this.qdrant.upsert('resources', { points });\n }\n\n async upsertAnnotationVector(\n annotationId: AnnotationId,\n embedding: number[],\n payload: AnnotationPayload\n ): Promise<void> {\n await this.qdrant.upsert('annotations', {\n points: [{\n id: toQdrantId(String(annotationId)),\n vector: embedding,\n payload: {\n annotationId: String(payload.annotationId),\n resourceId: String(payload.resourceId),\n motivation: payload.motivation,\n entityTypes: payload.entityTypes,\n text: payload.exactText,\n ...(payload.machineRead ? { machineRead: true } : {}),\n },\n }],\n });\n }\n\n async deleteResourceVectors(resourceId: ResourceId): Promise<void> {\n await this.qdrant.delete('resources', {\n filter: {\n must: [{ key: 'resourceId', match: { value: String(resourceId) } }],\n },\n });\n }\n\n async deleteAnnotationVector(annotationId: AnnotationId): Promise<void> {\n await this.qdrant.delete('annotations', {\n points: [toQdrantId(String(annotationId))],\n });\n }\n\n async deleteAnnotationVectorsForResource(resourceId: ResourceId): Promise<void> {\n await this.qdrant.delete('annotations', {\n filter: {\n must: [{ key: 'resourceId', match: { value: String(resourceId) } }],\n },\n });\n }\n\n async count(): Promise<number> {\n const [resources, annotations] = await Promise.all([\n this.qdrant.count('resources', { exact: true }),\n this.qdrant.count('annotations', { exact: true }),\n ]);\n return resources.count + annotations.count;\n }\n\n async updateResourceEntityTypes(resourceId: ResourceId, entityTypes: string[]): Promise<void> {\n // Payload-only rewrite across the resource's points — no vectors touched,\n // no embedding involved (S13). Qdrant set_payload with a filter is a\n // no-op when the resource has no points.\n await this.qdrant.setPayload('resources', {\n payload: { entityTypes },\n filter: {\n must: [{ key: 'resourceId', match: { value: String(resourceId) } }],\n },\n });\n }\n\n async getResourceStamp(resourceId: ResourceId): Promise<ResourceStamp | undefined> {\n const page = await this.qdrant.scroll('resources', {\n limit: 1,\n filter: { must: [{ key: 'resourceId', match: { value: String(resourceId) } }] },\n with_payload: STAMP_FIELDS,\n with_vector: false,\n });\n const point = page.points[0];\n return point ? toStamp(point.payload) : undefined;\n }\n\n async listResourceStamps(): Promise<Map<string, ResourceStamp>> {\n const stamps = new Map<string, ResourceStamp>();\n let offset: Schemas['ScrollRequest']['offset'] = undefined;\n do {\n const page = await this.qdrant.scroll('resources', {\n limit: 1000,\n offset,\n with_payload: STAMP_FIELDS,\n with_vector: false,\n });\n for (const point of page.points) {\n const rid = point.payload?.resourceId;\n if (typeof rid !== 'string' || stamps.has(rid)) continue;\n stamps.set(rid, toStamp(point.payload));\n }\n offset = page.next_page_offset ?? undefined;\n } while (offset !== undefined && offset !== null);\n return stamps;\n }\n\n async listAnnotationIds(): Promise<Set<string>> {\n return this.scrollPayloadField('annotations', 'annotationId');\n }\n\n /** Collect the distinct values of one payload field across a collection. */\n private async scrollPayloadField(collection: string, field: string): Promise<Set<string>> {\n const values = new Set<string>();\n let offset: Schemas['ScrollRequest']['offset'] = undefined;\n do {\n const page = await this.qdrant.scroll(collection, {\n limit: 1000,\n offset,\n with_payload: [field],\n with_vector: false,\n });\n for (const point of page.points) {\n const value = point.payload?.[field];\n if (typeof value === 'string') values.add(value);\n }\n offset = page.next_page_offset ?? undefined;\n } while (offset !== undefined && offset !== null);\n return values;\n }\n\n async searchResources(embedding: number[], opts: SearchOptions): Promise<VectorSearchResult[]> {\n return this.search('resources', embedding, opts);\n }\n\n async searchAnnotations(embedding: number[], opts: SearchOptions): Promise<VectorSearchResult[]> {\n return this.search('annotations', embedding, opts);\n }\n\n async searchByResource(resourceId: ResourceId, opts: SearchOptions): Promise<VectorSearchResult[]> {\n // Fetch the resource's stored chunk vectors (page through all of them so a\n // long resource isn't silently truncated).\n const queryVectors: number[][] = [];\n let offset: Schemas['ScrollRequest']['offset'] = undefined;\n do {\n const page = await this.qdrant.scroll('resources', {\n filter: { must: [{ key: 'resourceId', match: { value: String(resourceId) } }] },\n with_vector: true,\n with_payload: false,\n limit: 256,\n offset,\n });\n for (const point of page.points) {\n if (Array.isArray(point.vector)) queryVectors.push(point.vector as number[]);\n }\n offset = page.next_page_offset ?? undefined;\n } while (offset !== undefined && offset !== null);\n\n if (queryVectors.length === 0) return [];\n\n // Self-exclude the source; carry the caller's filter (e.g. excludeEntityTypes).\n const filter = this.buildFilter({ ...opts.filter, excludeResourceId: resourceId });\n\n // One batched query per source chunk (single round-trip). Each batch's\n // `limit` caps POINTS, but the merge below yields RESOURCES — so a target\n // with many chunks can fill several point-slots and crowd out resources\n // that belong in the top-`limit` after folding. Over-fetch per batch to\n // leave the merge material to work with; the memory store scores every\n // candidate exhaustively, and without this the two gateways disagree on\n // recall. Headroom, not a guarantee: a resource whose chunks are all\n // outranked by OVER_FETCH×limit points in every batch is still missed.\n // Qdrant's group-by would make it exact, but only via the `search`-family\n // endpoints 1.19.0 removed (see qdrant-query-api.test.ts).\n const searches = queryVectors.map((vector) => ({\n query: vector,\n limit: opts.limit * QdrantVectorStore.SEARCH_BY_RESOURCE_OVER_FETCH,\n score_threshold: opts.scoreThreshold,\n filter: filter ?? undefined,\n with_payload: true,\n }));\n const batches = await this.qdrant.queryBatch('resources', { searches });\n\n // Normalise to VectorSearchResult, then fold chunk hits to one entry per\n // resource (max-sim) via the shared merge; slice to the caller's limit.\n const hits = batches.flatMap((batch) => batch.points.map((r) => toSearchResult(r)));\n return mergeByResource(hits).slice(0, opts.limit);\n }\n\n private async search(collection: string, embedding: number[], opts: SearchOptions): Promise<VectorSearchResult[]> {\n const filter = this.buildFilter(opts.filter);\n\n // `query`, not `search`: the REST client dropped `search`/`searchBatch` in\n // 1.19.0 in favour of the universal query endpoint. Same request but the\n // vector moves to `query`, and the response is wrapped in `{ points }`.\n const { points } = await this.qdrant.query(collection, {\n query: embedding,\n limit: opts.limit,\n score_threshold: opts.scoreThreshold,\n filter: filter ?? undefined,\n with_payload: true,\n });\n\n return points.map((r) => toSearchResult(r));\n }\n\n private buildFilter(filter?: SearchOptions['filter']): Schemas['Filter'] | null {\n if (!filter) return null;\n\n const must: Schemas['FieldCondition'][] = [];\n\n if (filter.entityTypes && filter.entityTypes.length > 0) {\n // any-of: match payloads whose `entityTypes` array contains at least one\n // of the requested types. Matches the memory store's `some(t => ...)`\n // semantics; pushing one `must` clause per type would mean all-of.\n must.push({ key: 'entityTypes', match: { any: filter.entityTypes } });\n }\n\n if (filter.resourceId) {\n must.push({ key: 'resourceId', match: { value: String(filter.resourceId) } });\n }\n\n if (filter.motivation) {\n must.push({ key: 'motivation', match: { value: filter.motivation } });\n }\n\n const must_not: Schemas['FieldCondition'][] = [];\n\n if (filter.excludeResourceId) {\n must_not.push({ key: 'resourceId', match: { value: String(filter.excludeResourceId) } });\n }\n\n if (filter.excludeEntityTypes && filter.excludeEntityTypes.length > 0) {\n // any-of exclusion: drop points whose entityTypes contain any of these.\n must_not.push({ key: 'entityTypes', match: { any: filter.excludeEntityTypes } });\n }\n\n if (must.length === 0 && must_not.length === 0) return null;\n\n return {\n ...(must.length > 0 ? { must } : {}),\n ...(must_not.length > 0 ? { must_not } : {}),\n };\n }\n}\n"]}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { mergeByResource } from './chunk-
|
|
2
|
-
export { QdrantVectorStore, mergeByResource } from './chunk-
|
|
1
|
+
import { mergeByResource } from './chunk-WCD6P6QQ.js';
|
|
2
|
+
export { QdrantVectorStore, mergeByResource } from './chunk-WCD6P6QQ.js';
|
|
3
3
|
export { VoyageEmbeddingProvider } from './chunk-PJ72DF6E.js';
|
|
4
4
|
export { OllamaEmbeddingProvider } from './chunk-GWXB645H.js';
|
|
5
5
|
|
|
@@ -183,7 +183,7 @@ var MemoryVectorStore = class {
|
|
|
183
183
|
async function createVectorStore(config) {
|
|
184
184
|
let store;
|
|
185
185
|
if (config.type === "qdrant") {
|
|
186
|
-
const { QdrantVectorStore: QdrantVectorStore2 } = await import('./qdrant-
|
|
186
|
+
const { QdrantVectorStore: QdrantVectorStore2 } = await import('./qdrant-EUQ53YHP.js');
|
|
187
187
|
store = new QdrantVectorStore2({
|
|
188
188
|
host: config.host ?? "localhost",
|
|
189
189
|
port: config.port ?? 6333,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"qdrant-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"qdrant-EUQ53YHP.js"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@semiont/vectors",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.29",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=24.0.0"
|
|
6
6
|
},
|
|
@@ -30,15 +30,15 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@qdrant/js-client-rest": "^1.18.0",
|
|
33
|
-
"@semiont/core": "0.5.
|
|
33
|
+
"@semiont/core": "0.5.29"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@vitest/coverage-v8": "^4.1.
|
|
37
|
-
"rollup": "^4.
|
|
36
|
+
"@vitest/coverage-v8": "^4.1.11",
|
|
37
|
+
"rollup": "^4.63.0",
|
|
38
38
|
"rollup-plugin-dts": "^6.4.1",
|
|
39
39
|
"tsup": "^8.5.1",
|
|
40
40
|
"typescript": "^6.0.2",
|
|
41
|
-
"vitest": "^4.1.
|
|
41
|
+
"vitest": "^4.1.11"
|
|
42
42
|
},
|
|
43
43
|
"files": [
|
|
44
44
|
"dist",
|
package/dist/qdrant-JMDT7ZI5.js
DELETED