diff --git a/packages/semantic-search/package.json b/packages/semantic-search/package.json index 676688a..25d8735 100644 --- a/packages/semantic-search/package.json +++ b/packages/semantic-search/package.json @@ -9,6 +9,10 @@ ".": { "types": "./src/index.ts", "default": "./dist/index.mjs" + }, + "./lancedb": { + "types": "./src/components/lancedb/index.ts", + "default": "./dist/components/lancedb/index.mjs" } }, "scripts": { @@ -20,16 +24,16 @@ "postinstall": "pnpm build:stub" }, "devDependencies": { - "@lancedb/lancedb": "0.10.0", + "@payloadcms/db-mongodb": "^3.0.0-beta.107", "@payloadcms/db-postgres": "^3.0.0-beta.107", - "@types/dockerode": "^3.3.31", - "apache-arrow": "^17.0.0", "dockerode": "^4.0.2", - "mongodb-memory-server": "^10.0.0", - "ollama": "^0.5.9" + "mongodb-memory-server": "^10.0.0" }, "dependencies": { + "apache-arrow": "^17.0.0", + "ollama": "^0.5.9", + "@lancedb/lancedb": "0.10.0", "@workspace/llm-utils": "workspace:*", "defu": "^6.1.4", "pathe": "^1.1.2", diff --git a/packages/semantic-search/src/components/lancedb/index.ts b/packages/semantic-search/src/components/lancedb/index.ts index 5896dfc..11e0e4b 100644 --- a/packages/semantic-search/src/components/lancedb/index.ts +++ b/packages/semantic-search/src/components/lancedb/index.ts @@ -1,8 +1,10 @@ -import { type Table, connect } from '@lancedb/lancedb' -import { LanceSchema } from '@lancedb/lancedb/embedding' -import { Utf8 } from 'apache-arrow' -import type { Identifier, InsertFields, VectorDB } from '../../types' -import { OllamaEmbeddings } from '../ollama' +import {connect, type Table} from '@lancedb/lancedb' +import {getRegistry, LanceSchema} from '@lancedb/lancedb/embedding' +import {Utf8} from 'apache-arrow' +import type {Identifier, InsertFields, VectorDB} from '../../types' +import {OllamaEmbeddings, register} from '../ollama' + +register() export class LanceDB implements VectorDB { public name = 'lancedb' @@ -23,6 +25,7 @@ export class LanceDB implements VectorDB { } static async create(path = './lancedb') { + const func = new OllamaEmbeddings({ host: 'http://100.67.29.127:11434', model: 'nomic-embed-text', diff --git a/packages/semantic-search/src/components/ollama/index.ts b/packages/semantic-search/src/components/ollama/index.ts index 4d86237..5256cb3 100644 --- a/packages/semantic-search/src/components/ollama/index.ts +++ b/packages/semantic-search/src/components/ollama/index.ts @@ -1,19 +1,13 @@ -import { embedding } from '@lancedb/lancedb' -import { - EmbeddingFunction, - TextEmbeddingFunction, - getRegistry, -} from '@lancedb/lancedb/embedding' -import type { Float } from 'apache-arrow' -import { Ollama } from 'ollama' +import {getRegistry, TextEmbeddingFunction,} from '@lancedb/lancedb/embedding' +import type {Float} from 'apache-arrow' +import {Ollama} from 'ollama' interface Options { model: string timeout: number host: string } -// @ts-ignore -@embedding.register('ollama') + export class OllamaEmbeddings extends TextEmbeddingFunction> { private client: Ollama constructor(private modelOptions: Options) { diff --git a/packages/semantic-search/src/hooks/afterChangeHook.ts b/packages/semantic-search/src/hooks/afterChangeHook.ts index 1257203..c430f55 100644 --- a/packages/semantic-search/src/hooks/afterChangeHook.ts +++ b/packages/semantic-search/src/hooks/afterChangeHook.ts @@ -1,6 +1,6 @@ -import type { FieldHook, FieldHookArgs } from 'payload' -import { isObject, isString } from 'radash' -import { getSemanticSearchCustom } from '../utils/customContext' +import type {FieldHook, FieldHookArgs} from 'payload' +import {isObject, isString} from 'radash' +import {getSemanticSearchCustom} from '../utils/customContext' export const afterChangeHook: FieldHook = (args) => { if (args.operation === 'create' || args.operation === 'update') { diff --git a/packages/semantic-search/src/index.ts b/packages/semantic-search/src/index.ts index b202ab1..254d235 100644 --- a/packages/semantic-search/src/index.ts +++ b/packages/semantic-search/src/index.ts @@ -1,9 +1,9 @@ import defu from 'defu' -import type { Config, FieldBase } from 'payload' -import { afterChangeHook } from './hooks/afterChangeHook' -import type { SemanticSearchPluginConfig } from './types' -import { setupSemanticSearchCustom } from './utils/customContext' -import { getField, parseFields } from './utils/fields' +import type {Config, FieldBase} from 'payload' +import {afterChangeHook} from './hooks/afterChangeHook' +import type {SemanticSearchPluginConfig} from './types' +import {setupSemanticSearchCustom} from './utils/customContext' +import {getField, parseFields} from './utils/fields' export const semanticSearchPlugin = (incomingPluginConfig: SemanticSearchPluginConfig) => @@ -16,7 +16,6 @@ export const semanticSearchPlugin = return setupSemanticSearchCustom(config, { vectorDB: incomingPluginConfig.vectorDB, - embeddingFn: incomingPluginConfig.vectorDB, }) } diff --git a/packages/semantic-search/src/utils/customContext.ts b/packages/semantic-search/src/utils/customContext.ts index 88a580b..5d97096 100644 --- a/packages/semantic-search/src/utils/customContext.ts +++ b/packages/semantic-search/src/utils/customContext.ts @@ -1,10 +1,9 @@ -import type { Config } from 'payload' -import { isObject } from 'radash' -import type { SemanticSearchPluginConfig, VectorDB } from '../types' +import type {Config} from 'payload' +import {isObject} from 'radash' +import type {VectorDB} from '../types' export type SemanticSearchCustomObject = { vectorDB: VectorDB - embeddingFn: SemanticSearchPluginConfig['embeddingFn'] } export const CUSTOMKEY = 'semantic-search' diff --git a/packages/semantic-search/src/utils/fields.ts b/packages/semantic-search/src/utils/fields.ts index e7120b4..aaf68d2 100644 --- a/packages/semantic-search/src/utils/fields.ts +++ b/packages/semantic-search/src/utils/fields.ts @@ -1,9 +1,4 @@ -import type { - CollectionConfig, - Config, - TextField, - TextareaField, -} from 'payload' +import type {CollectionConfig, Config, TextareaField, TextField,} from 'payload' export interface FieldEntry { collectionConfig: CollectionConfig diff --git a/playground/.gitignore b/playground/.gitignore index 52bec0f..d787cf0 100644 --- a/playground/.gitignore +++ b/playground/.gitignore @@ -8,3 +8,4 @@ node_modules # Payload default media upload directory public/media/ +db/ diff --git a/playground/next.config.js b/playground/next.config.js index e8e6935..bfb51d8 100644 --- a/playground/next.config.js +++ b/playground/next.config.js @@ -1,4 +1,4 @@ -import { withPayload } from '@payloadcms/next/withPayload' +import {withPayload} from '@payloadcms/next/withPayload' import redirects from './redirects.js' @@ -6,6 +6,11 @@ const NEXT_PUBLIC_SERVER_URL = process.env.NEXT_PUBLIC_SERVER_URL || 'http://loc /** @type {import('next').NextConfig} */ const nextConfig = { + webpack(config) { + config.externals.push('@lancedb/lancedb') + return config; + }, + serverExternalPackages:['@payload-llm-plugins/semantic-search','@lancedb/lancedb'], images: { remotePatterns: [ ...[NEXT_PUBLIC_SERVER_URL /* 'https://example.com' */].map((item) => { diff --git a/playground/playground.db b/playground/playground.db deleted file mode 100644 index a8b3d60..0000000 Binary files a/playground/playground.db and /dev/null differ diff --git a/playground/src/payload.config.ts b/playground/src/payload.config.ts index fd36e22..dba1d4d 100644 --- a/playground/src/payload.config.ts +++ b/playground/src/payload.config.ts @@ -30,6 +30,7 @@ import {Header} from './Header/config' import {revalidateRedirects} from './hooks/revalidateRedirects' import {GenerateTitle, GenerateURL} from '@payloadcms/plugin-seo/types' import {Page, Post} from './payload-types' +import {LanceDB} from "@payload-llm-plugins/semantic-search/lancedb"; const filename = fileURLToPath(import.meta.url) const dirname = path.dirname(filename) @@ -188,7 +189,7 @@ export default buildConfig({ }, }), payloadCloudPlugin(), // storage-adapter-placeholder - semanticSearchPlugin({enabled:true, vectorDB: LanceDB.create('')}) + semanticSearchPlugin({enabled:true, vectorDB: await LanceDB.create('./db/lancedb/'), dimensions:768, indexableFields:['posts.content'] }) ], secret: process.env.PAYLOAD_SECRET!, sharp, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8da29da..c6ea2dc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -50,12 +50,21 @@ importers: packages/semantic-search: dependencies: + '@lancedb/lancedb': + specifier: 0.10.0 + version: 0.10.0(apache-arrow@17.0.0) '@workspace/llm-utils': specifier: workspace:* version: link:../llm-utils + apache-arrow: + specifier: ^17.0.0 + version: 17.0.0 defu: specifier: ^6.1.4 version: 6.1.4 + ollama: + specifier: ^0.5.9 + version: 0.5.9 pathe: specifier: ^1.1.2 version: 1.1.2 @@ -66,30 +75,18 @@ importers: specifier: ^12.1.0 version: 12.1.0 devDependencies: - '@lancedb/lancedb': - specifier: 0.10.0 - version: 0.10.0(apache-arrow@17.0.0) '@payloadcms/db-mongodb': specifier: ^3.0.0-beta.107 version: 3.0.0-canary.ff8c8fd(payload@3.0.0-beta.107(graphql@16.9.0)(monaco-editor@0.38.0)(react-dom@19.0.0-rc-06d0b89e-20240801(react@19.0.0-rc-06d0b89e-20240801))(react@19.0.0-rc-06d0b89e-20240801)(typescript@5.6.2)) '@payloadcms/db-postgres': specifier: ^3.0.0-beta.107 version: 3.0.0-canary.ff8c8fd(@libsql/client@0.6.2)(@types/react@18.3.6)(payload@3.0.0-beta.107(graphql@16.9.0)(monaco-editor@0.38.0)(react-dom@19.0.0-rc-06d0b89e-20240801(react@19.0.0-rc-06d0b89e-20240801))(react@19.0.0-rc-06d0b89e-20240801)(typescript@5.6.2))(react@19.0.0-rc-06d0b89e-20240801) - '@types/dockerode': - specifier: ^3.3.31 - version: 3.3.31 - apache-arrow: - specifier: ^17.0.0 - version: 17.0.0 dockerode: specifier: ^4.0.2 version: 4.0.2 mongodb-memory-server: specifier: ^10.0.0 version: 10.0.0(@aws-sdk/credential-providers@3.651.1)(socks@2.8.3) - ollama: - specifier: ^0.5.9 - version: 0.5.9 playground: dependencies: @@ -1453,7 +1450,6 @@ packages: '@lancedb/lancedb@0.10.0': resolution: {integrity: sha512-/sNUZze9Ed6N2T6y3NuEOSPPE3hSvJ4UHfZ+uAOBjNprrECRoCn4LTjza6dA4Za4Csl7K19AwBhlvhLQLvi48Q==} engines: {node: '>= 18'} - cpu: [x64, arm64] os: [darwin, linux, win32] peerDependencies: apache-arrow: '>=13.0.0 <=17.0.0' @@ -2479,12 +2475,6 @@ packages: '@types/command-line-usage@5.0.4': resolution: {integrity: sha512-BwR5KP3Es/CSht0xqBcUXS3qCAUVXwpRKsV2+arxeb65atasuXG9LykC9Ab10Cw3s2raH92ZqOeILaQbsB2ACg==} - '@types/docker-modem@3.0.6': - resolution: {integrity: sha512-yKpAGEuKRSS8wwx0joknWxsmLha78wNMe9R2S3UNsVOkZded8UqOrV8KoeDXoXsjndxwyF3eIhyClGbO1SEhEg==} - - '@types/dockerode@3.3.31': - resolution: {integrity: sha512-42R9eoVqJDSvVspV89g7RwRqfNExgievLNWoHkg7NoWIqAmavIbgQBb4oc0qRtHkxE+I3Xxvqv7qVXFABKPBTg==} - '@types/escape-html@1.0.4': resolution: {integrity: sha512-qZ72SFTgUAZ5a7Tj6kf2SHLetiH5S6f8G5frB2SPQ3EyF02kxdyBFf4Tz4banE3xCgGnKgWLt//a6VuYHKYJTg==} @@ -2503,9 +2493,6 @@ packages: '@types/jsonwebtoken@9.0.7': resolution: {integrity: sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==} - '@types/node@18.19.50': - resolution: {integrity: sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==} - '@types/node@20.16.5': resolution: {integrity: sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==} @@ -2536,9 +2523,6 @@ packages: '@types/semver@7.5.8': resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - '@types/ssh2@1.15.1': - resolution: {integrity: sha512-ZIbEqKAsi5gj35y4P4vkJYly642wIbY6PqoN0xiyQGshKUGXR9WQjF/iF9mXBQ8uBKy3ezfsCkcoHKhd0BzuDA==} - '@types/uuid@10.0.0': resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} @@ -4546,7 +4530,6 @@ packages: libsql@0.3.19: resolution: {integrity: sha512-Aj5cQ5uk/6fHdmeW0TiXK42FqUlwx7ytmMLPSaUQPin5HKKKuUPD62MAbN4OEweGBBI7q1BekoEN4gPUEL6MZA==} - cpu: [x64, arm64, wasm32] os: [darwin, linux, win32] lilconfig@2.1.0: @@ -6182,9 +6165,6 @@ packages: typescript: optional: true - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - undici-types@6.19.8: resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} @@ -8302,17 +8282,17 @@ snapshots: '@payloadcms/eslint-config@1.1.1(typescript@5.6.2)': dependencies: '@types/eslint': 8.44.2 - '@typescript-eslint/eslint-plugin': 6.6.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2) + '@typescript-eslint/eslint-plugin': 6.6.0(@typescript-eslint/parser@6.6.0(eslint@8.48.0)(typescript@5.6.2))(eslint@8.48.0)(typescript@5.6.2) '@typescript-eslint/parser': 6.6.0(eslint@8.48.0)(typescript@5.6.2) eslint: 8.48.0 eslint-config-prettier: 9.0.0(eslint@8.48.0) eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.6.0(eslint@8.48.0)(typescript@5.6.2))(eslint@8.48.0) - eslint-plugin-jest: 27.2.3(@typescript-eslint/eslint-plugin@6.6.0(@typescript-eslint/parser@6.6.0(eslint@8.48.0)(typescript@5.6.2))(eslint@8.48.0)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2) + eslint-plugin-jest: 27.2.3(@typescript-eslint/eslint-plugin@6.6.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2))(eslint@8.48.0)(typescript@5.6.2) eslint-plugin-jest-dom: 5.1.0(eslint@8.48.0) eslint-plugin-jsx-a11y: 6.7.1(eslint@8.48.0) eslint-plugin-node: 11.1.0(eslint@8.48.0) eslint-plugin-perfectionist: 2.0.0(eslint@8.48.0)(typescript@5.6.2) - eslint-plugin-playwright: 0.16.0(eslint-plugin-jest@27.2.3(@typescript-eslint/eslint-plugin@6.6.0(@typescript-eslint/parser@6.6.0(eslint@8.48.0)(typescript@5.6.2))(eslint@8.48.0)(typescript@5.6.2))(eslint@8.48.0)(typescript@5.6.2))(eslint@8.48.0) + eslint-plugin-playwright: 0.16.0(eslint-plugin-jest@27.2.3(@typescript-eslint/eslint-plugin@6.6.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2))(eslint@8.48.0) eslint-plugin-react: 7.33.2(eslint@8.48.0) eslint-plugin-react-hooks: 4.6.0(eslint@8.48.0) eslint-plugin-regexp: 1.15.0(eslint@8.48.0) @@ -9230,17 +9210,6 @@ snapshots: '@types/command-line-usage@5.0.4': {} - '@types/docker-modem@3.0.6': - dependencies: - '@types/node': 22.5.4 - '@types/ssh2': 1.15.1 - - '@types/dockerode@3.3.31': - dependencies: - '@types/docker-modem': 3.0.6 - '@types/node': 22.5.5 - '@types/ssh2': 1.15.1 - '@types/escape-html@1.0.4': {} '@types/eslint@8.44.2': @@ -9258,10 +9227,6 @@ snapshots: dependencies: '@types/node': 22.5.4 - '@types/node@18.19.50': - dependencies: - undici-types: 5.26.5 - '@types/node@20.16.5': dependencies: undici-types: 6.19.8 @@ -9273,6 +9238,7 @@ snapshots: '@types/node@22.5.5': dependencies: undici-types: 6.19.8 + optional: true '@types/parse-json@4.0.2': {} @@ -9293,10 +9259,6 @@ snapshots: '@types/semver@7.5.8': {} - '@types/ssh2@1.15.1': - dependencies: - '@types/node': 18.19.50 - '@types/uuid@10.0.0': {} '@types/webidl-conversions@7.0.3': {} @@ -9314,16 +9276,16 @@ snapshots: dependencies: '@types/node': 22.5.4 - '@typescript-eslint/eslint-plugin@6.6.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2)': + '@typescript-eslint/eslint-plugin@6.6.0(@typescript-eslint/parser@6.6.0(eslint@8.48.0)(typescript@5.6.2))(eslint@8.48.0)(typescript@5.6.2)': dependencies: '@eslint-community/regexpp': 4.11.1 - '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.6.2) + '@typescript-eslint/parser': 6.6.0(eslint@8.48.0)(typescript@5.6.2) '@typescript-eslint/scope-manager': 6.6.0 '@typescript-eslint/type-utils': 6.6.0(eslint@8.48.0)(typescript@5.6.2) '@typescript-eslint/utils': 6.6.0(eslint@8.48.0)(typescript@5.6.2) '@typescript-eslint/visitor-keys': 6.6.0 debug: 4.3.7 - eslint: 8.57.1 + eslint: 8.48.0 graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 @@ -10798,12 +10760,12 @@ snapshots: eslint: 8.48.0 requireindex: 1.2.0 - eslint-plugin-jest@27.2.3(@typescript-eslint/eslint-plugin@6.6.0(@typescript-eslint/parser@6.6.0(eslint@8.48.0)(typescript@5.6.2))(eslint@8.48.0)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2): + eslint-plugin-jest@27.2.3(@typescript-eslint/eslint-plugin@6.6.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2))(eslint@8.48.0)(typescript@5.6.2): dependencies: '@typescript-eslint/utils': 5.62.0(eslint@8.48.0)(typescript@5.6.2) - eslint: 8.57.1 + eslint: 8.48.0 optionalDependencies: - '@typescript-eslint/eslint-plugin': 6.6.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2) + '@typescript-eslint/eslint-plugin': 6.6.0(@typescript-eslint/parser@6.6.0(eslint@8.48.0)(typescript@5.6.2))(eslint@8.48.0)(typescript@5.6.2) transitivePeerDependencies: - supports-color - typescript @@ -10868,11 +10830,11 @@ snapshots: - supports-color - typescript - eslint-plugin-playwright@0.16.0(eslint-plugin-jest@27.2.3(@typescript-eslint/eslint-plugin@6.6.0(@typescript-eslint/parser@6.6.0(eslint@8.48.0)(typescript@5.6.2))(eslint@8.48.0)(typescript@5.6.2))(eslint@8.48.0)(typescript@5.6.2))(eslint@8.48.0): + eslint-plugin-playwright@0.16.0(eslint-plugin-jest@27.2.3(@typescript-eslint/eslint-plugin@6.6.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2))(eslint@8.48.0): dependencies: eslint: 8.48.0 optionalDependencies: - eslint-plugin-jest: 27.2.3(@typescript-eslint/eslint-plugin@6.6.0(@typescript-eslint/parser@6.6.0(eslint@8.48.0)(typescript@5.6.2))(eslint@8.48.0)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2) + eslint-plugin-jest: 27.2.3(@typescript-eslint/eslint-plugin@6.6.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2))(eslint@8.48.0)(typescript@5.6.2) eslint-plugin-react-hooks@4.6.0(eslint@8.48.0): dependencies: @@ -13545,8 +13507,6 @@ snapshots: - supports-color - vue-tsc - undici-types@5.26.5: {} - undici-types@6.19.8: {} unfetch@4.2.0: {} diff --git a/tsconfig.base.json b/tsconfig.base.json index 590ef73..dd368c0 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -2,8 +2,7 @@ "extends": ["@tsconfig/next/tsconfig.json"], "compilerOptions": { "incremental": false, - "emitDecoratorMetadata": true, - "experimentalDecorators": true + "target": "ES2022" }, "include": [], "exclude": ["node_modules", "dist"]