From c90b829d73902afc75d7e985a7f9a22a7f34bd3d Mon Sep 17 00:00:00 2001 From: Wang Jiyuan <59059173+EurFelux@users.noreply.github.com> Date: Mon, 9 Jun 2025 16:52:01 +0800 Subject: [PATCH] fix: ollama embedding knowledge query score always 100% (#7001) * fix: ollama embedding knowledge query score always 100% * fix: force ollama to use api without v1 --- package.json | 2 + src/main/embeddings/Embeddings.ts | 11 +++- src/main/embeddings/EmbeddingsFactory.ts | 25 ++++++- src/main/services/KnowledgeService.ts | 10 ++- src/renderer/src/services/KnowledgeService.ts | 1 + src/renderer/src/types/index.ts | 1 + yarn.lock | 65 +++++++++++++++++++ 7 files changed, 110 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 0536e89407..57ca31e318 100644 --- a/package.json +++ b/package.json @@ -68,9 +68,11 @@ "@cherrystudio/embedjs-loader-sitemap": "^0.1.31", "@cherrystudio/embedjs-loader-web": "^0.1.31", "@cherrystudio/embedjs-loader-xml": "^0.1.31", + "@cherrystudio/embedjs-ollama": "^0.1.31", "@cherrystudio/embedjs-openai": "^0.1.31", "@electron-toolkit/utils": "^3.0.0", "@langchain/community": "^0.3.36", + "@langchain/ollama": "^0.2.1", "@strongtz/win32-arm64-msvc": "^0.4.7", "@tanstack/react-query": "^5.27.0", "@types/react-infinite-scroll-component": "^5.0.0", diff --git a/src/main/embeddings/Embeddings.ts b/src/main/embeddings/Embeddings.ts index cf354450ef..0701e7db2d 100644 --- a/src/main/embeddings/Embeddings.ts +++ b/src/main/embeddings/Embeddings.ts @@ -5,8 +5,15 @@ import EmbeddingsFactory from './EmbeddingsFactory' export default class Embeddings { private sdk: BaseEmbeddings - constructor({ model, apiKey, apiVersion, baseURL, dimensions }: KnowledgeBaseParams) { - this.sdk = EmbeddingsFactory.create({ model, apiKey, apiVersion, baseURL, dimensions } as KnowledgeBaseParams) + constructor({ model, provider, apiKey, apiVersion, baseURL, dimensions }: KnowledgeBaseParams) { + this.sdk = EmbeddingsFactory.create({ + model, + provider, + apiKey, + apiVersion, + baseURL, + dimensions + } as KnowledgeBaseParams) } public async init(): Promise { return this.sdk.init() diff --git a/src/main/embeddings/EmbeddingsFactory.ts b/src/main/embeddings/EmbeddingsFactory.ts index 5924d00d7d..6dfc049293 100644 --- a/src/main/embeddings/EmbeddingsFactory.ts +++ b/src/main/embeddings/EmbeddingsFactory.ts @@ -1,4 +1,5 @@ import type { BaseEmbeddings } from '@cherrystudio/embedjs-interfaces' +import { OllamaEmbeddings } from '@cherrystudio/embedjs-ollama' import { OpenAiEmbeddings } from '@cherrystudio/embedjs-openai' import { AzureOpenAiEmbeddings } from '@cherrystudio/embedjs-openai/src/azure-openai-embeddings' import { getInstanceName } from '@main/utils' @@ -7,9 +8,9 @@ import { KnowledgeBaseParams } from '@types' import VoyageEmbeddings from './VoyageEmbeddings' export default class EmbeddingsFactory { - static create({ model, apiKey, apiVersion, baseURL, dimensions }: KnowledgeBaseParams): BaseEmbeddings { + static create({ model, provider, apiKey, apiVersion, baseURL, dimensions }: KnowledgeBaseParams): BaseEmbeddings { const batchSize = 10 - if (model.includes('voyage')) { + if (provider === 'voyageai') { return new VoyageEmbeddings({ modelName: model, apiKey, @@ -17,6 +18,26 @@ export default class EmbeddingsFactory { batchSize: 8 }) } + if (provider === 'ollama') { + if (baseURL.includes('v1/')) { + return new OllamaEmbeddings({ + model: model, + baseUrl: baseURL.replace('v1/', ''), + requestOptions: { + // @ts-ignore expected + 'encoding-format': 'float' + } + }) + } + return new OllamaEmbeddings({ + model: model, + baseUrl: baseURL, + requestOptions: { + // @ts-ignore expected + 'encoding-format': 'float' + } + }) + } if (apiVersion !== undefined) { return new AzureOpenAiEmbeddings({ azureOpenAIApiKey: apiKey, diff --git a/src/main/services/KnowledgeService.ts b/src/main/services/KnowledgeService.ts index e82b54d0d2..d18f5d0a84 100644 --- a/src/main/services/KnowledgeService.ts +++ b/src/main/services/KnowledgeService.ts @@ -110,13 +110,21 @@ class KnowledgeService { private getRagApplication = async ({ id, model, + provider, apiKey, apiVersion, baseURL, dimensions }: KnowledgeBaseParams): Promise => { let ragApplication: RAGApplication - const embeddings = new Embeddings({ model, apiKey, apiVersion, baseURL, dimensions } as KnowledgeBaseParams) + const embeddings = new Embeddings({ + model, + provider, + apiKey, + apiVersion, + baseURL, + dimensions + } as KnowledgeBaseParams) try { ragApplication = await new RAGApplicationBuilder() .setModel('NO_MODEL') diff --git a/src/renderer/src/services/KnowledgeService.ts b/src/renderer/src/services/KnowledgeService.ts index 626788a4e2..af44b8e8de 100644 --- a/src/renderer/src/services/KnowledgeService.ts +++ b/src/renderer/src/services/KnowledgeService.ts @@ -39,6 +39,7 @@ export const getKnowledgeBaseParams = (base: KnowledgeBase): KnowledgeBaseParams return { id: base.id, model: base.model.id, + provider: base.model.provider, dimensions: ONLY_SUPPORTED_DIMENSION_PROVIDERS.includes(base.model.provider) ? base.dimensions : undefined, apiKey: aiProvider.getApiKey() || 'secret', apiVersion: provider.apiVersion, diff --git a/src/renderer/src/types/index.ts b/src/renderer/src/types/index.ts index c0df8f88f3..40a53d0a27 100644 --- a/src/renderer/src/types/index.ts +++ b/src/renderer/src/types/index.ts @@ -423,6 +423,7 @@ export interface KnowledgeBase { export type KnowledgeBaseParams = { id: string model: string + provider: string dimensions?: number apiKey: string apiVersion?: string diff --git a/yarn.lock b/yarn.lock index e9aadd59c0..8d9c5d1c59 100644 --- a/yarn.lock +++ b/yarn.lock @@ -654,6 +654,18 @@ __metadata: languageName: node linkType: hard +"@cherrystudio/embedjs-ollama@npm:^0.1.31": + version: 0.1.31 + resolution: "@cherrystudio/embedjs-ollama@npm:0.1.31" + dependencies: + "@cherrystudio/embedjs-interfaces": "npm:0.1.31" + "@langchain/core": "npm:^0.3.26" + "@langchain/ollama": "npm:^0.1.4" + debug: "npm:^4.4.0" + checksum: 10c0/7ac807aca5a99dccc2d2bfc8245c9b9c5184c7b0b48f1ea4d3367a2175a8978c5cbc425614e1851074cffd93ffbb31350e4e567de308aa5100a6a2cbd795813f + languageName: node + linkType: hard + "@cherrystudio/embedjs-openai@npm:^0.1.31": version: 0.1.31 resolution: "@cherrystudio/embedjs-openai@npm:0.1.31" @@ -2617,6 +2629,34 @@ __metadata: languageName: node linkType: hard +"@langchain/ollama@npm:^0.1.4": + version: 0.1.6 + resolution: "@langchain/ollama@npm:0.1.6" + dependencies: + ollama: "npm:^0.5.12" + uuid: "npm:^10.0.0" + zod: "npm:^3.24.1" + zod-to-json-schema: "npm:^3.24.1" + peerDependencies: + "@langchain/core": ">=0.2.21 <0.4.0" + checksum: 10c0/535f2f4304edf125d0133a80fcb7657c5ffcab3c180e3ea69ce171c7a5fadb220b0d00c3bb7523bbe4f2f56663e0dd59cd19e19adadf0091c800b9ddca17ed3b + languageName: node + linkType: hard + +"@langchain/ollama@npm:^0.2.1": + version: 0.2.1 + resolution: "@langchain/ollama@npm:0.2.1" + dependencies: + ollama: "npm:^0.5.12" + uuid: "npm:^10.0.0" + zod: "npm:^3.24.1" + zod-to-json-schema: "npm:^3.24.1" + peerDependencies: + "@langchain/core": ">=0.2.21 <0.4.0" + checksum: 10c0/be3083a15e879f2c19d0a51aafb88a3ba4ea69f9fdd90e6069b84edd92649c00a29a34cb885746e099f5cab0791b55df3776cd582cba7de299b8bd574d32b8c1 + languageName: node + linkType: hard + "@langchain/openai@npm:0.3.16": version: 0.3.16 resolution: "@langchain/openai@npm:0.3.16" @@ -5544,6 +5584,7 @@ __metadata: "@cherrystudio/embedjs-loader-sitemap": "npm:^0.1.31" "@cherrystudio/embedjs-loader-web": "npm:^0.1.31" "@cherrystudio/embedjs-loader-xml": "npm:^0.1.31" + "@cherrystudio/embedjs-ollama": "npm:^0.1.31" "@cherrystudio/embedjs-openai": "npm:^0.1.31" "@electron-toolkit/eslint-config-prettier": "npm:^3.0.0" "@electron-toolkit/eslint-config-ts": "npm:^3.0.0" @@ -5558,6 +5599,7 @@ __metadata: "@hello-pangea/dnd": "npm:^16.6.0" "@kangfenmao/keyv-storage": "npm:^0.1.0" "@langchain/community": "npm:^0.3.36" + "@langchain/ollama": "npm:^0.2.1" "@modelcontextprotocol/sdk": "npm:^1.11.4" "@mozilla/readability": "npm:^0.6.0" "@notionhq/client": "npm:^2.2.15" @@ -13910,6 +13952,15 @@ __metadata: languageName: node linkType: hard +"ollama@npm:^0.5.12": + version: 0.5.16 + resolution: "ollama@npm:0.5.16" + dependencies: + whatwg-fetch: "npm:^3.6.20" + checksum: 10c0/901f9dac5692447219b3a48dcb9ad4f7da292a8ddbbbf429482cdde56e787a8a37123f3df18957733b8990f70b67fd05eb13b9bb17bd029eb6597d5b36345d7a + languageName: node + linkType: hard + "on-finished@npm:^2.4.1": version: 2.4.1 resolution: "on-finished@npm:2.4.1" @@ -18442,6 +18493,13 @@ __metadata: languageName: node linkType: hard +"whatwg-fetch@npm:^3.6.20": + version: 3.6.20 + resolution: "whatwg-fetch@npm:3.6.20" + checksum: 10c0/fa972dd14091321d38f36a4d062298df58c2248393ef9e8b154493c347c62e2756e25be29c16277396046d6eaa4b11bd174f34e6403fff6aaca9fb30fa1ff46d + languageName: node + linkType: hard + "whatwg-mimetype@npm:^4.0.0": version: 4.0.0 resolution: "whatwg-mimetype@npm:4.0.0" @@ -18812,6 +18870,13 @@ __metadata: languageName: node linkType: hard +"zod@npm:^3.24.1": + version: 3.25.56 + resolution: "zod@npm:3.25.56" + checksum: 10c0/3800f01d4b1df932b91354eb1e648f69cc7e5561549e6d2bf83827d930a5f33bbf92926099445f6fc1ebb64ca9c6513ef9ae5e5409cfef6325f354bcf6fc9a24 + languageName: node + linkType: hard + "zustand@npm:^4.4.0": version: 4.5.6 resolution: "zustand@npm:4.5.6"