From 16e583b4c3751b7a3ca16c60cf20449aa6aac439 Mon Sep 17 00:00:00 2001 From: shatfield4 Date: Fri, 14 Mar 2025 14:13:11 -0700 Subject: [PATCH 1/3] fix embedding endpoint for openai compatible api --- .../api/openai/compatibility-test-script.cjs | 11 +++++++++++ server/endpoints/api/openai/index.js | 16 ++++++++++++---- server/swagger/openapi.json | 2 +- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/server/endpoints/api/openai/compatibility-test-script.cjs b/server/endpoints/api/openai/compatibility-test-script.cjs index 7ae2b2dbf55..0c422585d7c 100644 --- a/server/endpoints/api/openai/compatibility-test-script.cjs +++ b/server/endpoints/api/openai/compatibility-test-script.cjs @@ -55,6 +55,17 @@ const client = new OpenAI({ console.log({ message }); } + // Test embeddings creation + console.log("Creating embeddings"); + const embedding = await client.embeddings.create({ + model: null, // model is optional for AnythingLLM + input: "This is a test string for embedding", + encoding_format: "float", + }); + console.log("Embedding created successfully:"); + console.log(`Dimensions: ${embedding.data[0].embedding.length}`); + console.log(`First few values: ${embedding.data[0].embedding.slice(0, 5)}`); + // Vector DB functionality console.log("Fetching /vector_stores"); const vectorDBList = await client.beta.vectorStores.list(); diff --git a/server/endpoints/api/openai/index.js b/server/endpoints/api/openai/index.js index ffd641b3e5c..fc3986b05a7 100644 --- a/server/endpoints/api/openai/index.js +++ b/server/endpoints/api/openai/index.js @@ -12,6 +12,8 @@ const { EventLogs } = require("../../../models/eventLogs"); const { OpenAICompatibleChat, } = require("../../../utils/chats/openaiCompatible"); +const path = require("path"); +const fs = require("fs"); function apiOpenAICompatibleEndpoints(app) { if (!app) return; @@ -207,7 +209,7 @@ function apiOpenAICompatibleEndpoints(app) { content: { "application/json": { example: { - inputs: [ + input: [ "This is my first string to embed", "This is my second string to embed", ], @@ -223,13 +225,19 @@ function apiOpenAICompatibleEndpoints(app) { } */ try { - const { inputs = [] } = reqBody(request); - const validArray = inputs.every((input) => typeof input === "string"); + const body = reqBody(request); + let input = body.input || []; + + if (!Array.isArray(input)) { + input = [input]; + } + + const validArray = input.every((text) => typeof text === "string"); if (!validArray) throw new Error("All inputs to be embedded must be strings."); const Embedder = getEmbeddingEngineSelection(); - const embeddings = await Embedder.embedChunks(inputs); + const embeddings = await Embedder.embedChunks(input); const data = []; embeddings.forEach((embedding, index) => { data.push({ diff --git a/server/swagger/openapi.json b/server/swagger/openapi.json index 0eaf3dd8671..7010487e40a 100644 --- a/server/swagger/openapi.json +++ b/server/swagger/openapi.json @@ -3481,7 +3481,7 @@ "content": { "application/json": { "example": { - "inputs": [ + "input": [ "This is my first string to embed", "This is my second string to embed" ], From 8db1aac228ca82872dfdb0aa4dcd5b3f8452110d Mon Sep 17 00:00:00 2001 From: shatfield4 Date: Fri, 14 Mar 2025 14:15:57 -0700 Subject: [PATCH 2/3] remove unused imports --- server/endpoints/api/openai/index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/endpoints/api/openai/index.js b/server/endpoints/api/openai/index.js index fc3986b05a7..b77c6384c53 100644 --- a/server/endpoints/api/openai/index.js +++ b/server/endpoints/api/openai/index.js @@ -12,8 +12,6 @@ const { EventLogs } = require("../../../models/eventLogs"); const { OpenAICompatibleChat, } = require("../../../utils/chats/openaiCompatible"); -const path = require("path"); -const fs = require("fs"); function apiOpenAICompatibleEndpoints(app) { if (!app) return; From 2af0eb8433c25584f8053b33c1687307a5528e27 Mon Sep 17 00:00:00 2001 From: timothycarambat Date: Mon, 17 Mar 2025 18:09:36 -0700 Subject: [PATCH 3/3] add backwards compat for embedding --- .../api/openai/compatibility-test-script.cjs | 6 +++++- server/endpoints/api/openai/index.js | 18 +++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/server/endpoints/api/openai/compatibility-test-script.cjs b/server/endpoints/api/openai/compatibility-test-script.cjs index 0c422585d7c..96e56b0734a 100644 --- a/server/endpoints/api/openai/compatibility-test-script.cjs +++ b/server/endpoints/api/openai/compatibility-test-script.cjs @@ -64,7 +64,11 @@ const client = new OpenAI({ }); console.log("Embedding created successfully:"); console.log(`Dimensions: ${embedding.data[0].embedding.length}`); - console.log(`First few values: ${embedding.data[0].embedding.slice(0, 5)}`); + console.log( + `First few values:`, + embedding.data[0].embedding.slice(0, 5), + `+ ${embedding.data[0].embedding.length - 5} more` + ); // Vector DB functionality console.log("Fetching /vector_stores"); diff --git a/server/endpoints/api/openai/index.js b/server/endpoints/api/openai/index.js index b77c6384c53..e5bd1771b6f 100644 --- a/server/endpoints/api/openai/index.js +++ b/server/endpoints/api/openai/index.js @@ -224,16 +224,20 @@ function apiOpenAICompatibleEndpoints(app) { */ try { const body = reqBody(request); - let input = body.input || []; + // Support input or "inputs" (for backwards compatibility) as an array of strings or a single string + // TODO: "inputs" key support will eventually be fully removed. + let input = body?.input || body?.inputs || []; + // if input is not an array, make it an array and force to string content + if (!Array.isArray(input)) input = [String(input)]; - if (!Array.isArray(input)) { - input = [input]; + if (Array.isArray(input)) { + if (input.length === 0) + throw new Error("Input array cannot be empty."); + const validArray = input.every((text) => typeof text === "string"); + if (!validArray) + throw new Error("All inputs to be embedded must be strings."); } - const validArray = input.every((text) => typeof text === "string"); - if (!validArray) - throw new Error("All inputs to be embedded must be strings."); - const Embedder = getEmbeddingEngineSelection(); const embeddings = await Embedder.embedChunks(input); const data = [];