@langchain/core
Version:
Core LangChain.js abstractions and schemas
1 lines • 7.67 kB
Source Map (JSON)
{"version":3,"file":"math.cjs","names":["X: number[][]","Y: number[][]","func: VectorFunction","M: number[][]","cosine","innerProduct","innerProductDistance","euclidean","queryEmbedding: number[] | number[][]","embeddingList: number[][]","array: number[]","arrays: number[][]"],"sources":["../../src/utils/math.ts"],"sourcesContent":["import { cosine } from \"./ml-distance/similarities.js\";\nimport { innerProduct as innerProductDistance } from \"./ml-distance/distances.js\";\nimport { euclidean } from \"./ml-distance-euclidean/euclidean.js\";\n\ntype VectorFunction = (xVector: number[], yVector: number[]) => number;\n\n/**\n * Apply a row-wise function between two matrices with the same number of columns.\n *\n * @param {number[][]} X - The first matrix.\n * @param {number[][]} Y - The second matrix.\n * @param {VectorFunction} func - The function to apply.\n *\n * @throws {Error} If the number of columns in X and Y are not the same.\n *\n * @returns {number[][] | [[]]} A matrix where each row represents the result of applying the function between the corresponding rows of X and Y.\n */\n\nexport function matrixFunc(\n X: number[][],\n Y: number[][],\n func: VectorFunction\n): number[][] {\n if (\n X.length === 0 ||\n X[0].length === 0 ||\n Y.length === 0 ||\n Y[0].length === 0\n ) {\n return [[]];\n }\n\n if (X[0].length !== Y[0].length) {\n throw new Error(\n `Number of columns in X and Y must be the same. X has shape ${[\n X.length,\n X[0].length,\n ]} and Y has shape ${[Y.length, Y[0].length]}.`\n );\n }\n\n return X.map((xVector) =>\n Y.map((yVector) => func(xVector, yVector)).map((similarity) =>\n Number.isNaN(similarity) ? 0 : similarity\n )\n );\n}\n\nexport function normalize(M: number[][], similarity = false): number[][] {\n const max = matrixMaxVal(M);\n return M.map((row) =>\n row.map((val) => (similarity ? 1 - val / max : val / max))\n );\n}\n\n/**\n * This function calculates the row-wise cosine similarity between two matrices with the same number of columns.\n *\n * @param {number[][]} X - The first matrix.\n * @param {number[][]} Y - The second matrix.\n *\n * @throws {Error} If the number of columns in X and Y are not the same.\n *\n * @returns {number[][] | [[]]} A matrix where each row represents the cosine similarity values between the corresponding rows of X and Y.\n */\nexport function cosineSimilarity(X: number[][], Y: number[][]): number[][] {\n return matrixFunc(X, Y, cosine);\n}\n\nexport function innerProduct(X: number[][], Y: number[][]): number[][] {\n return matrixFunc(X, Y, innerProductDistance);\n}\n\nexport function euclideanDistance(X: number[][], Y: number[][]): number[][] {\n return matrixFunc(X, Y, euclidean);\n}\n\n/**\n * This function implements the Maximal Marginal Relevance algorithm\n * to select a set of embeddings that maximizes the diversity and relevance to a query embedding.\n *\n * @param {number[]|number[][]} queryEmbedding - The query embedding.\n * @param {number[][]} embeddingList - The list of embeddings to select from.\n * @param {number} [lambda=0.5] - The trade-off parameter between relevance and diversity.\n * @param {number} [k=4] - The maximum number of embeddings to select.\n *\n * @returns {number[]} The indexes of the selected embeddings in the embeddingList.\n */\nexport function maximalMarginalRelevance(\n queryEmbedding: number[] | number[][],\n embeddingList: number[][],\n lambda = 0.5,\n k = 4\n): number[] {\n if (Math.min(k, embeddingList.length) <= 0) {\n return [];\n }\n\n const queryEmbeddingExpanded = (\n Array.isArray(queryEmbedding[0]) ? queryEmbedding : [queryEmbedding]\n ) as number[][];\n\n const similarityToQuery = cosineSimilarity(\n queryEmbeddingExpanded,\n embeddingList\n )[0];\n const mostSimilarEmbeddingIndex = argMax(similarityToQuery).maxIndex;\n\n const selectedEmbeddings = [embeddingList[mostSimilarEmbeddingIndex]];\n const selectedEmbeddingsIndexes = [mostSimilarEmbeddingIndex];\n\n while (selectedEmbeddingsIndexes.length < Math.min(k, embeddingList.length)) {\n let bestScore = -Infinity;\n let bestIndex = -1;\n\n const similarityToSelected = cosineSimilarity(\n embeddingList,\n selectedEmbeddings\n );\n\n similarityToQuery.forEach((queryScore, queryScoreIndex) => {\n if (selectedEmbeddingsIndexes.includes(queryScoreIndex)) {\n return;\n }\n const maxSimilarityToSelected = Math.max(\n ...similarityToSelected[queryScoreIndex]\n );\n const score =\n lambda * queryScore - (1 - lambda) * maxSimilarityToSelected;\n\n if (score > bestScore) {\n bestScore = score;\n bestIndex = queryScoreIndex;\n }\n });\n selectedEmbeddings.push(embeddingList[bestIndex]);\n selectedEmbeddingsIndexes.push(bestIndex);\n }\n\n return selectedEmbeddingsIndexes;\n}\n\ntype MaxInfo = {\n maxIndex: number;\n maxValue: number;\n};\n\n/**\n * Finds the index of the maximum value in the given array.\n * @param {number[]} array - The input array.\n *\n * @returns {number} The index of the maximum value in the array. If the array is empty, returns -1.\n */\nfunction argMax(array: number[]): MaxInfo {\n if (array.length === 0) {\n return {\n maxIndex: -1,\n maxValue: NaN,\n };\n }\n\n let maxValue = array[0];\n let maxIndex = 0;\n\n for (let i = 1; i < array.length; i += 1) {\n if (array[i] > maxValue) {\n maxIndex = i;\n maxValue = array[i];\n }\n }\n return { maxIndex, maxValue };\n}\n\nfunction matrixMaxVal(arrays: number[][]): number {\n return arrays.reduce(\n (acc, array) => Math.max(acc, argMax(array).maxValue),\n 0\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,SAAgB,WACdA,GACAC,GACAC,MACY;AACZ,KACE,EAAE,WAAW,KACb,EAAE,GAAG,WAAW,KAChB,EAAE,WAAW,KACb,EAAE,GAAG,WAAW,EAEhB,QAAO,CAAC,CAAE,CAAC;AAGb,KAAI,EAAE,GAAG,WAAW,EAAE,GAAG,OACvB,OAAM,IAAI,MACR,CAAC,2DAA2D,EAAE,CAC5D,EAAE,QACF,EAAE,GAAG,MACN,EAAC,iBAAiB,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,MAAO,EAAC,CAAC,CAAC;AAInD,QAAO,EAAE,IAAI,CAAC,YACZ,EAAE,IAAI,CAAC,YAAY,KAAK,SAAS,QAAQ,CAAC,CAAC,IAAI,CAAC,eAC9C,OAAO,MAAM,WAAW,GAAG,IAAI,WAChC,CACF;AACF;AAED,SAAgB,UAAUC,GAAe,aAAa,OAAmB;CACvE,MAAM,MAAM,aAAa,EAAE;AAC3B,QAAO,EAAE,IAAI,CAAC,QACZ,IAAI,IAAI,CAAC,QAAS,aAAa,IAAI,MAAM,MAAM,MAAM,IAAK,CAC3D;AACF;;;;;;;;;;;AAYD,SAAgB,iBAAiBH,GAAeC,GAA2B;AACzE,QAAO,WAAW,GAAG,GAAGG,4BAAO;AAChC;AAED,SAAgBC,eAAaL,GAAeC,GAA2B;AACrE,QAAO,WAAW,GAAG,GAAGK,+BAAqB;AAC9C;AAED,SAAgB,kBAAkBN,GAAeC,GAA2B;AAC1E,QAAO,WAAW,GAAG,GAAGM,4BAAU;AACnC;;;;;;;;;;;;AAaD,SAAgB,yBACdC,gBACAC,eACA,SAAS,IACT,IAAI,GACM;AACV,KAAI,KAAK,IAAI,GAAG,cAAc,OAAO,IAAI,EACvC,QAAO,CAAE;CAGX,MAAM,yBACJ,MAAM,QAAQ,eAAe,GAAG,GAAG,iBAAiB,CAAC,cAAe;CAGtE,MAAM,oBAAoB,iBACxB,wBACA,cACD,CAAC;CACF,MAAM,4BAA4B,OAAO,kBAAkB,CAAC;CAE5D,MAAM,qBAAqB,CAAC,cAAc,0BAA2B;CACrE,MAAM,4BAA4B,CAAC,yBAA0B;AAE7D,QAAO,0BAA0B,SAAS,KAAK,IAAI,GAAG,cAAc,OAAO,EAAE;EAC3E,IAAI,YAAY;EAChB,IAAI,YAAY;EAEhB,MAAM,uBAAuB,iBAC3B,eACA,mBACD;EAED,kBAAkB,QAAQ,CAAC,YAAY,oBAAoB;AACzD,OAAI,0BAA0B,SAAS,gBAAgB,CACrD;GAEF,MAAM,0BAA0B,KAAK,IACnC,GAAG,qBAAqB,iBACzB;GACD,MAAM,QACJ,SAAS,cAAc,IAAI,UAAU;AAEvC,OAAI,QAAQ,WAAW;IACrB,YAAY;IACZ,YAAY;GACb;EACF,EAAC;EACF,mBAAmB,KAAK,cAAc,WAAW;EACjD,0BAA0B,KAAK,UAAU;CAC1C;AAED,QAAO;AACR;;;;;;;AAaD,SAAS,OAAOC,OAA0B;AACxC,KAAI,MAAM,WAAW,EACnB,QAAO;EACL,UAAU;EACV,UAAU;CACX;CAGH,IAAI,WAAW,MAAM;CACrB,IAAI,WAAW;AAEf,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,EACrC,KAAI,MAAM,KAAK,UAAU;EACvB,WAAW;EACX,WAAW,MAAM;CAClB;AAEH,QAAO;EAAE;EAAU;CAAU;AAC9B;AAED,SAAS,aAAaC,QAA4B;AAChD,QAAO,OAAO,OACZ,CAAC,KAAK,UAAU,KAAK,IAAI,KAAK,OAAO,MAAM,CAAC,SAAS,EACrD,EACD;AACF"}