@langchain/core 0.0.10 → 0.0.11-rc.1
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/documents/transformers.cjs +16 -1
- package/dist/documents/transformers.d.ts +8 -0
- package/dist/documents/transformers.js +14 -0
- package/dist/load/import_map.cjs +2 -1
- package/dist/load/import_map.d.ts +1 -0
- package/dist/load/import_map.js +1 -0
- package/dist/load/index.cjs +9 -3
- package/dist/load/index.js +9 -3
- package/dist/messages/index.cjs +23 -1
- package/dist/messages/index.d.ts +16 -0
- package/dist/messages/index.js +20 -0
- package/dist/utils/math.cjs +125 -0
- package/dist/utils/math.d.ts +40 -0
- package/dist/utils/math.js +116 -0
- package/package.json +11 -1
- package/utils/math.cjs +1 -0
- package/utils/math.d.ts +1 -0
- package/utils/math.js +1 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BaseDocumentTransformer = void 0;
|
|
3
|
+
exports.MappingDocumentTransformer = exports.BaseDocumentTransformer = void 0;
|
|
4
4
|
const base_js_1 = require("../runnables/base.cjs");
|
|
5
5
|
/**
|
|
6
6
|
* Abstract base class for document transformation systems.
|
|
@@ -34,3 +34,18 @@ class BaseDocumentTransformer extends base_js_1.Runnable {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
exports.BaseDocumentTransformer = BaseDocumentTransformer;
|
|
37
|
+
/**
|
|
38
|
+
* Class for document transformers that return exactly one transformed document
|
|
39
|
+
* for each input document.
|
|
40
|
+
*/
|
|
41
|
+
class MappingDocumentTransformer extends BaseDocumentTransformer {
|
|
42
|
+
async transformDocuments(documents) {
|
|
43
|
+
const newDocuments = [];
|
|
44
|
+
for (const document of documents) {
|
|
45
|
+
const transformedDocument = await this._transformDocument(document);
|
|
46
|
+
newDocuments.push(transformedDocument);
|
|
47
|
+
}
|
|
48
|
+
return newDocuments;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.MappingDocumentTransformer = MappingDocumentTransformer;
|
|
@@ -28,3 +28,11 @@ export declare abstract class BaseDocumentTransformer<RunInput extends Document[
|
|
|
28
28
|
*/
|
|
29
29
|
invoke(input: RunInput, _options: BaseCallbackConfig): Promise<RunOutput>;
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Class for document transformers that return exactly one transformed document
|
|
33
|
+
* for each input document.
|
|
34
|
+
*/
|
|
35
|
+
export declare abstract class MappingDocumentTransformer extends BaseDocumentTransformer {
|
|
36
|
+
transformDocuments(documents: Document[]): Promise<Document[]>;
|
|
37
|
+
abstract _transformDocument(document: Document): Promise<Document>;
|
|
38
|
+
}
|
|
@@ -30,3 +30,17 @@ export class BaseDocumentTransformer extends Runnable {
|
|
|
30
30
|
return this.transformDocuments(input);
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Class for document transformers that return exactly one transformed document
|
|
35
|
+
* for each input document.
|
|
36
|
+
*/
|
|
37
|
+
export class MappingDocumentTransformer extends BaseDocumentTransformer {
|
|
38
|
+
async transformDocuments(documents) {
|
|
39
|
+
const newDocuments = [];
|
|
40
|
+
for (const document of documents) {
|
|
41
|
+
const transformedDocument = await this._transformDocument(document);
|
|
42
|
+
newDocuments.push(transformedDocument);
|
|
43
|
+
}
|
|
44
|
+
return newDocuments;
|
|
45
|
+
}
|
|
46
|
+
}
|
package/dist/load/import_map.cjs
CHANGED
|
@@ -24,7 +24,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
24
24
|
return result;
|
|
25
25
|
};
|
|
26
26
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
-
exports.vectorstores = exports.utils__types = exports.utils__tiktoken = exports.utils__testing = exports.utils__stream = exports.utils__json_schema = exports.utils__json_patch = exports.utils__hash = exports.utils__env = exports.utils__async_caller = exports.tracers__tracer_langchain = exports.tracers__tracer_langchain_v1 = exports.tracers__run_collector = exports.tracers__log_stream = exports.tracers__initialize = exports.tracers__console = exports.tracers__base = exports.tools = exports.stores = exports.retrievers = exports.runnables = exports.prompt_values = exports.prompts = exports.outputs = exports.output_parsers = exports.messages = exports.memory = exports.load__serializable = exports.language_models__llms = exports.language_models__chat_models = exports.language_models__base = exports.example_selectors = exports.embeddings = exports.documents = exports.chat_history = exports.callbacks__promises = exports.callbacks__manager = exports.callbacks__base = exports.caches = exports.agents = void 0;
|
|
27
|
+
exports.vectorstores = exports.utils__types = exports.utils__tiktoken = exports.utils__testing = exports.utils__stream = exports.utils__math = exports.utils__json_schema = exports.utils__json_patch = exports.utils__hash = exports.utils__env = exports.utils__async_caller = exports.tracers__tracer_langchain = exports.tracers__tracer_langchain_v1 = exports.tracers__run_collector = exports.tracers__log_stream = exports.tracers__initialize = exports.tracers__console = exports.tracers__base = exports.tools = exports.stores = exports.retrievers = exports.runnables = exports.prompt_values = exports.prompts = exports.outputs = exports.output_parsers = exports.messages = exports.memory = exports.load__serializable = exports.language_models__llms = exports.language_models__chat_models = exports.language_models__base = exports.example_selectors = exports.embeddings = exports.documents = exports.chat_history = exports.callbacks__promises = exports.callbacks__manager = exports.callbacks__base = exports.caches = exports.agents = void 0;
|
|
28
28
|
exports.agents = __importStar(require("../agents.cjs"));
|
|
29
29
|
exports.caches = __importStar(require("../caches.cjs"));
|
|
30
30
|
exports.callbacks__base = __importStar(require("../callbacks/base.cjs"));
|
|
@@ -60,6 +60,7 @@ exports.utils__env = __importStar(require("../utils/env.cjs"));
|
|
|
60
60
|
exports.utils__hash = __importStar(require("../utils/hash.cjs"));
|
|
61
61
|
exports.utils__json_patch = __importStar(require("../utils/json_patch.cjs"));
|
|
62
62
|
exports.utils__json_schema = __importStar(require("../utils/json_schema.cjs"));
|
|
63
|
+
exports.utils__math = __importStar(require("../utils/math.cjs"));
|
|
63
64
|
exports.utils__stream = __importStar(require("../utils/stream.cjs"));
|
|
64
65
|
exports.utils__testing = __importStar(require("../utils/testing/index.cjs"));
|
|
65
66
|
exports.utils__tiktoken = __importStar(require("../utils/tiktoken.cjs"));
|
|
@@ -33,6 +33,7 @@ export * as utils__env from "../utils/env.js";
|
|
|
33
33
|
export * as utils__hash from "../utils/hash.js";
|
|
34
34
|
export * as utils__json_patch from "../utils/json_patch.js";
|
|
35
35
|
export * as utils__json_schema from "../utils/json_schema.js";
|
|
36
|
+
export * as utils__math from "../utils/math.js";
|
|
36
37
|
export * as utils__stream from "../utils/stream.js";
|
|
37
38
|
export * as utils__testing from "../utils/testing/index.js";
|
|
38
39
|
export * as utils__tiktoken from "../utils/tiktoken.js";
|
package/dist/load/import_map.js
CHANGED
|
@@ -34,6 +34,7 @@ export * as utils__env from "../utils/env.js";
|
|
|
34
34
|
export * as utils__hash from "../utils/hash.js";
|
|
35
35
|
export * as utils__json_patch from "../utils/json_patch.js";
|
|
36
36
|
export * as utils__json_schema from "../utils/json_schema.js";
|
|
37
|
+
export * as utils__math from "../utils/math.js";
|
|
37
38
|
export * as utils__stream from "../utils/stream.js";
|
|
38
39
|
export * as utils__testing from "../utils/testing/index.js";
|
|
39
40
|
export * as utils__tiktoken from "../utils/tiktoken.js";
|
package/dist/load/index.cjs
CHANGED
|
@@ -93,12 +93,17 @@ async function reviver(value) {
|
|
|
93
93
|
const namespace = namespaceReverse.reverse();
|
|
94
94
|
const finalImportMap = { ...defaultImportMap, ...importMap };
|
|
95
95
|
let module = null;
|
|
96
|
+
const optionalImportNamespaceAliases = [namespace.join("/")];
|
|
97
|
+
if (namespace[0] === "langchain_community") {
|
|
98
|
+
optionalImportNamespaceAliases.push(["langchain", ...namespace.slice(1)].join("/"));
|
|
99
|
+
}
|
|
100
|
+
const matchingNamespaceAlias = optionalImportNamespaceAliases.find((alias) => alias in optionalImportsMap);
|
|
96
101
|
if (import_constants_js_1.optionalImportEntrypoints
|
|
97
102
|
.concat(optionalImportEntrypoints)
|
|
98
103
|
.includes(namespace.join("/")) ||
|
|
99
|
-
|
|
100
|
-
if (
|
|
101
|
-
module = await optionalImportsMap[
|
|
104
|
+
matchingNamespaceAlias) {
|
|
105
|
+
if (matchingNamespaceAlias !== undefined) {
|
|
106
|
+
module = await optionalImportsMap[matchingNamespaceAlias];
|
|
102
107
|
}
|
|
103
108
|
else {
|
|
104
109
|
throw new Error(`Missing key "${namespace.join("/")}" for ${pathStr} in load(optionalImportsMap={})`);
|
|
@@ -108,6 +113,7 @@ async function reviver(value) {
|
|
|
108
113
|
// Currently, we only support langchain imports.
|
|
109
114
|
if (namespace[0] === "langchain" ||
|
|
110
115
|
namespace[0] === "langchain_core" ||
|
|
116
|
+
namespace[0] === "langchain_community" ||
|
|
111
117
|
namespace[0] === "langchain_anthropic" ||
|
|
112
118
|
namespace[0] === "langchain_openai") {
|
|
113
119
|
namespace.shift();
|
package/dist/load/index.js
CHANGED
|
@@ -67,12 +67,17 @@ async function reviver(value) {
|
|
|
67
67
|
const namespace = namespaceReverse.reverse();
|
|
68
68
|
const finalImportMap = { ...defaultImportMap, ...importMap };
|
|
69
69
|
let module = null;
|
|
70
|
+
const optionalImportNamespaceAliases = [namespace.join("/")];
|
|
71
|
+
if (namespace[0] === "langchain_community") {
|
|
72
|
+
optionalImportNamespaceAliases.push(["langchain", ...namespace.slice(1)].join("/"));
|
|
73
|
+
}
|
|
74
|
+
const matchingNamespaceAlias = optionalImportNamespaceAliases.find((alias) => alias in optionalImportsMap);
|
|
70
75
|
if (defaultOptionalImportEntrypoints
|
|
71
76
|
.concat(optionalImportEntrypoints)
|
|
72
77
|
.includes(namespace.join("/")) ||
|
|
73
|
-
|
|
74
|
-
if (
|
|
75
|
-
module = await optionalImportsMap[
|
|
78
|
+
matchingNamespaceAlias) {
|
|
79
|
+
if (matchingNamespaceAlias !== undefined) {
|
|
80
|
+
module = await optionalImportsMap[matchingNamespaceAlias];
|
|
76
81
|
}
|
|
77
82
|
else {
|
|
78
83
|
throw new Error(`Missing key "${namespace.join("/")}" for ${pathStr} in load(optionalImportsMap={})`);
|
|
@@ -82,6 +87,7 @@ async function reviver(value) {
|
|
|
82
87
|
// Currently, we only support langchain imports.
|
|
83
88
|
if (namespace[0] === "langchain" ||
|
|
84
89
|
namespace[0] === "langchain_core" ||
|
|
90
|
+
namespace[0] === "langchain_community" ||
|
|
85
91
|
namespace[0] === "langchain_anthropic" ||
|
|
86
92
|
namespace[0] === "langchain_openai") {
|
|
87
93
|
namespace.shift();
|
package/dist/messages/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.mapStoredMessageToChatMessage = exports.getBufferString = exports.ChatMessageChunk = exports.coerceMessageLikeToMessage = exports.isBaseMessageChunk = exports.isBaseMessage = exports.ChatMessage = exports.ToolMessageChunk = exports.ToolMessage = exports.FunctionMessageChunk = exports.FunctionMessage = exports.SystemMessageChunk = exports.SystemMessage = exports.AIMessageChunk = exports.AIMessage = exports.HumanMessageChunk = exports.HumanMessage = exports.BaseMessageChunk = exports.BaseMessage = void 0;
|
|
3
|
+
exports.mapChatMessagesToStoredMessages = exports.mapStoredMessagesToChatMessages = exports.mapStoredMessageToChatMessage = exports.getBufferString = exports.ChatMessageChunk = exports.coerceMessageLikeToMessage = exports.isBaseMessageChunk = exports.isBaseMessage = exports.ChatMessage = exports.ToolMessageChunk = exports.ToolMessage = exports.FunctionMessageChunk = exports.FunctionMessage = exports.SystemMessageChunk = exports.SystemMessage = exports.AIMessageChunk = exports.AIMessage = exports.HumanMessageChunk = exports.HumanMessage = exports.BaseMessageChunk = exports.BaseMessage = void 0;
|
|
4
4
|
const serializable_js_1 = require("../load/serializable.cjs");
|
|
5
5
|
function mergeContent(firstContent, secondContent) {
|
|
6
6
|
// If first content is a string
|
|
@@ -556,3 +556,25 @@ function mapStoredMessageToChatMessage(message) {
|
|
|
556
556
|
}
|
|
557
557
|
}
|
|
558
558
|
exports.mapStoredMessageToChatMessage = mapStoredMessageToChatMessage;
|
|
559
|
+
/**
|
|
560
|
+
* Transforms an array of `StoredMessage` instances into an array of
|
|
561
|
+
* `BaseMessage` instances. It uses the `mapV1MessageToStoredMessage`
|
|
562
|
+
* function to ensure all messages are in the `StoredMessage` format, then
|
|
563
|
+
* creates new instances of the appropriate `BaseMessage` subclass based
|
|
564
|
+
* on the type of each message. This function is used to prepare stored
|
|
565
|
+
* messages for use in a chat context.
|
|
566
|
+
*/
|
|
567
|
+
function mapStoredMessagesToChatMessages(messages) {
|
|
568
|
+
return messages.map(mapStoredMessageToChatMessage);
|
|
569
|
+
}
|
|
570
|
+
exports.mapStoredMessagesToChatMessages = mapStoredMessagesToChatMessages;
|
|
571
|
+
/**
|
|
572
|
+
* Transforms an array of `BaseMessage` instances into an array of
|
|
573
|
+
* `StoredMessage` instances. It does this by calling the `toDict` method
|
|
574
|
+
* on each `BaseMessage`, which returns a `StoredMessage`. This function
|
|
575
|
+
* is used to prepare chat messages for storage.
|
|
576
|
+
*/
|
|
577
|
+
function mapChatMessagesToStoredMessages(messages) {
|
|
578
|
+
return messages.map((message) => message.toDict());
|
|
579
|
+
}
|
|
580
|
+
exports.mapChatMessagesToStoredMessages = mapChatMessagesToStoredMessages;
|
package/dist/messages/index.d.ts
CHANGED
|
@@ -234,3 +234,19 @@ export declare class ChatMessageChunk extends BaseMessageChunk {
|
|
|
234
234
|
*/
|
|
235
235
|
export declare function getBufferString(messages: BaseMessage[], humanPrefix?: string, aiPrefix?: string): string;
|
|
236
236
|
export declare function mapStoredMessageToChatMessage(message: StoredMessage): ChatMessage | HumanMessage | AIMessage | SystemMessage | FunctionMessage | ToolMessage;
|
|
237
|
+
/**
|
|
238
|
+
* Transforms an array of `StoredMessage` instances into an array of
|
|
239
|
+
* `BaseMessage` instances. It uses the `mapV1MessageToStoredMessage`
|
|
240
|
+
* function to ensure all messages are in the `StoredMessage` format, then
|
|
241
|
+
* creates new instances of the appropriate `BaseMessage` subclass based
|
|
242
|
+
* on the type of each message. This function is used to prepare stored
|
|
243
|
+
* messages for use in a chat context.
|
|
244
|
+
*/
|
|
245
|
+
export declare function mapStoredMessagesToChatMessages(messages: StoredMessage[]): BaseMessage[];
|
|
246
|
+
/**
|
|
247
|
+
* Transforms an array of `BaseMessage` instances into an array of
|
|
248
|
+
* `StoredMessage` instances. It does this by calling the `toDict` method
|
|
249
|
+
* on each `BaseMessage`, which returns a `StoredMessage`. This function
|
|
250
|
+
* is used to prepare chat messages for storage.
|
|
251
|
+
*/
|
|
252
|
+
export declare function mapChatMessagesToStoredMessages(messages: BaseMessage[]): StoredMessage[];
|
package/dist/messages/index.js
CHANGED
|
@@ -534,3 +534,23 @@ export function mapStoredMessageToChatMessage(message) {
|
|
|
534
534
|
throw new Error(`Got unexpected type: ${storedMessage.type}`);
|
|
535
535
|
}
|
|
536
536
|
}
|
|
537
|
+
/**
|
|
538
|
+
* Transforms an array of `StoredMessage` instances into an array of
|
|
539
|
+
* `BaseMessage` instances. It uses the `mapV1MessageToStoredMessage`
|
|
540
|
+
* function to ensure all messages are in the `StoredMessage` format, then
|
|
541
|
+
* creates new instances of the appropriate `BaseMessage` subclass based
|
|
542
|
+
* on the type of each message. This function is used to prepare stored
|
|
543
|
+
* messages for use in a chat context.
|
|
544
|
+
*/
|
|
545
|
+
export function mapStoredMessagesToChatMessages(messages) {
|
|
546
|
+
return messages.map(mapStoredMessageToChatMessage);
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Transforms an array of `BaseMessage` instances into an array of
|
|
550
|
+
* `StoredMessage` instances. It does this by calling the `toDict` method
|
|
551
|
+
* on each `BaseMessage`, which returns a `StoredMessage`. This function
|
|
552
|
+
* is used to prepare chat messages for storage.
|
|
553
|
+
*/
|
|
554
|
+
export function mapChatMessagesToStoredMessages(messages) {
|
|
555
|
+
return messages.map((message) => message.toDict());
|
|
556
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.maximalMarginalRelevance = exports.euclideanDistance = exports.innerProduct = exports.cosineSimilarity = exports.normalize = exports.matrixFunc = void 0;
|
|
4
|
+
const ml_distance_1 = require("ml-distance");
|
|
5
|
+
/**
|
|
6
|
+
* Apply a row-wise function between two matrices with the same number of columns.
|
|
7
|
+
*
|
|
8
|
+
* @param {number[][]} X - The first matrix.
|
|
9
|
+
* @param {number[][]} Y - The second matrix.
|
|
10
|
+
* @param {VectorFunction} func - The function to apply.
|
|
11
|
+
*
|
|
12
|
+
* @throws {Error} If the number of columns in X and Y are not the same.
|
|
13
|
+
*
|
|
14
|
+
* @returns {number[][] | [[]]} A matrix where each row represents the result of applying the function between the corresponding rows of X and Y.
|
|
15
|
+
*/
|
|
16
|
+
function matrixFunc(X, Y, func) {
|
|
17
|
+
if (X.length === 0 ||
|
|
18
|
+
X[0].length === 0 ||
|
|
19
|
+
Y.length === 0 ||
|
|
20
|
+
Y[0].length === 0) {
|
|
21
|
+
return [[]];
|
|
22
|
+
}
|
|
23
|
+
if (X[0].length !== Y[0].length) {
|
|
24
|
+
throw new Error(`Number of columns in X and Y must be the same. X has shape ${[
|
|
25
|
+
X.length,
|
|
26
|
+
X[0].length,
|
|
27
|
+
]} and Y has shape ${[Y.length, Y[0].length]}.`);
|
|
28
|
+
}
|
|
29
|
+
return X.map((xVector) => Y.map((yVector) => func(xVector, yVector)).map((similarity) => Number.isNaN(similarity) ? 0 : similarity));
|
|
30
|
+
}
|
|
31
|
+
exports.matrixFunc = matrixFunc;
|
|
32
|
+
function normalize(M, similarity = false) {
|
|
33
|
+
const max = matrixMaxVal(M);
|
|
34
|
+
return M.map((row) => row.map((val) => (similarity ? 1 - val / max : val / max)));
|
|
35
|
+
}
|
|
36
|
+
exports.normalize = normalize;
|
|
37
|
+
/**
|
|
38
|
+
* This function calculates the row-wise cosine similarity between two matrices with the same number of columns.
|
|
39
|
+
*
|
|
40
|
+
* @param {number[][]} X - The first matrix.
|
|
41
|
+
* @param {number[][]} Y - The second matrix.
|
|
42
|
+
*
|
|
43
|
+
* @throws {Error} If the number of columns in X and Y are not the same.
|
|
44
|
+
*
|
|
45
|
+
* @returns {number[][] | [[]]} A matrix where each row represents the cosine similarity values between the corresponding rows of X and Y.
|
|
46
|
+
*/
|
|
47
|
+
function cosineSimilarity(X, Y) {
|
|
48
|
+
return matrixFunc(X, Y, ml_distance_1.similarity.cosine);
|
|
49
|
+
}
|
|
50
|
+
exports.cosineSimilarity = cosineSimilarity;
|
|
51
|
+
function innerProduct(X, Y) {
|
|
52
|
+
return matrixFunc(X, Y, ml_distance_1.distance.innerProduct);
|
|
53
|
+
}
|
|
54
|
+
exports.innerProduct = innerProduct;
|
|
55
|
+
function euclideanDistance(X, Y) {
|
|
56
|
+
return matrixFunc(X, Y, ml_distance_1.distance.euclidean);
|
|
57
|
+
}
|
|
58
|
+
exports.euclideanDistance = euclideanDistance;
|
|
59
|
+
/**
|
|
60
|
+
* This function implements the Maximal Marginal Relevance algorithm
|
|
61
|
+
* to select a set of embeddings that maximizes the diversity and relevance to a query embedding.
|
|
62
|
+
*
|
|
63
|
+
* @param {number[]|number[][]} queryEmbedding - The query embedding.
|
|
64
|
+
* @param {number[][]} embeddingList - The list of embeddings to select from.
|
|
65
|
+
* @param {number} [lambda=0.5] - The trade-off parameter between relevance and diversity.
|
|
66
|
+
* @param {number} [k=4] - The maximum number of embeddings to select.
|
|
67
|
+
*
|
|
68
|
+
* @returns {number[]} The indexes of the selected embeddings in the embeddingList.
|
|
69
|
+
*/
|
|
70
|
+
function maximalMarginalRelevance(queryEmbedding, embeddingList, lambda = 0.5, k = 4) {
|
|
71
|
+
if (Math.min(k, embeddingList.length) <= 0) {
|
|
72
|
+
return [];
|
|
73
|
+
}
|
|
74
|
+
const queryEmbeddingExpanded = (Array.isArray(queryEmbedding[0]) ? queryEmbedding : [queryEmbedding]);
|
|
75
|
+
const similarityToQuery = cosineSimilarity(queryEmbeddingExpanded, embeddingList)[0];
|
|
76
|
+
const mostSimilarEmbeddingIndex = argMax(similarityToQuery).maxIndex;
|
|
77
|
+
const selectedEmbeddings = [embeddingList[mostSimilarEmbeddingIndex]];
|
|
78
|
+
const selectedEmbeddingsIndexes = [mostSimilarEmbeddingIndex];
|
|
79
|
+
while (selectedEmbeddingsIndexes.length < Math.min(k, embeddingList.length)) {
|
|
80
|
+
let bestScore = -Infinity;
|
|
81
|
+
let bestIndex = -1;
|
|
82
|
+
const similarityToSelected = cosineSimilarity(embeddingList, selectedEmbeddings);
|
|
83
|
+
similarityToQuery.forEach((queryScore, queryScoreIndex) => {
|
|
84
|
+
if (selectedEmbeddingsIndexes.includes(queryScoreIndex)) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const maxSimilarityToSelected = Math.max(...similarityToSelected[queryScoreIndex]);
|
|
88
|
+
const score = lambda * queryScore - (1 - lambda) * maxSimilarityToSelected;
|
|
89
|
+
if (score > bestScore) {
|
|
90
|
+
bestScore = score;
|
|
91
|
+
bestIndex = queryScoreIndex;
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
selectedEmbeddings.push(embeddingList[bestIndex]);
|
|
95
|
+
selectedEmbeddingsIndexes.push(bestIndex);
|
|
96
|
+
}
|
|
97
|
+
return selectedEmbeddingsIndexes;
|
|
98
|
+
}
|
|
99
|
+
exports.maximalMarginalRelevance = maximalMarginalRelevance;
|
|
100
|
+
/**
|
|
101
|
+
* Finds the index of the maximum value in the given array.
|
|
102
|
+
* @param {number[]} array - The input array.
|
|
103
|
+
*
|
|
104
|
+
* @returns {number} The index of the maximum value in the array. If the array is empty, returns -1.
|
|
105
|
+
*/
|
|
106
|
+
function argMax(array) {
|
|
107
|
+
if (array.length === 0) {
|
|
108
|
+
return {
|
|
109
|
+
maxIndex: -1,
|
|
110
|
+
maxValue: NaN,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
let maxValue = array[0];
|
|
114
|
+
let maxIndex = 0;
|
|
115
|
+
for (let i = 1; i < array.length; i += 1) {
|
|
116
|
+
if (array[i] > maxValue) {
|
|
117
|
+
maxIndex = i;
|
|
118
|
+
maxValue = array[i];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return { maxIndex, maxValue };
|
|
122
|
+
}
|
|
123
|
+
function matrixMaxVal(arrays) {
|
|
124
|
+
return arrays.reduce((acc, array) => Math.max(acc, argMax(array).maxValue), 0);
|
|
125
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
type VectorFunction = (xVector: number[], yVector: number[]) => number;
|
|
2
|
+
/**
|
|
3
|
+
* Apply a row-wise function between two matrices with the same number of columns.
|
|
4
|
+
*
|
|
5
|
+
* @param {number[][]} X - The first matrix.
|
|
6
|
+
* @param {number[][]} Y - The second matrix.
|
|
7
|
+
* @param {VectorFunction} func - The function to apply.
|
|
8
|
+
*
|
|
9
|
+
* @throws {Error} If the number of columns in X and Y are not the same.
|
|
10
|
+
*
|
|
11
|
+
* @returns {number[][] | [[]]} A matrix where each row represents the result of applying the function between the corresponding rows of X and Y.
|
|
12
|
+
*/
|
|
13
|
+
export declare function matrixFunc(X: number[][], Y: number[][], func: VectorFunction): number[][];
|
|
14
|
+
export declare function normalize(M: number[][], similarity?: boolean): number[][];
|
|
15
|
+
/**
|
|
16
|
+
* This function calculates the row-wise cosine similarity between two matrices with the same number of columns.
|
|
17
|
+
*
|
|
18
|
+
* @param {number[][]} X - The first matrix.
|
|
19
|
+
* @param {number[][]} Y - The second matrix.
|
|
20
|
+
*
|
|
21
|
+
* @throws {Error} If the number of columns in X and Y are not the same.
|
|
22
|
+
*
|
|
23
|
+
* @returns {number[][] | [[]]} A matrix where each row represents the cosine similarity values between the corresponding rows of X and Y.
|
|
24
|
+
*/
|
|
25
|
+
export declare function cosineSimilarity(X: number[][], Y: number[][]): number[][];
|
|
26
|
+
export declare function innerProduct(X: number[][], Y: number[][]): number[][];
|
|
27
|
+
export declare function euclideanDistance(X: number[][], Y: number[][]): number[][];
|
|
28
|
+
/**
|
|
29
|
+
* This function implements the Maximal Marginal Relevance algorithm
|
|
30
|
+
* to select a set of embeddings that maximizes the diversity and relevance to a query embedding.
|
|
31
|
+
*
|
|
32
|
+
* @param {number[]|number[][]} queryEmbedding - The query embedding.
|
|
33
|
+
* @param {number[][]} embeddingList - The list of embeddings to select from.
|
|
34
|
+
* @param {number} [lambda=0.5] - The trade-off parameter between relevance and diversity.
|
|
35
|
+
* @param {number} [k=4] - The maximum number of embeddings to select.
|
|
36
|
+
*
|
|
37
|
+
* @returns {number[]} The indexes of the selected embeddings in the embeddingList.
|
|
38
|
+
*/
|
|
39
|
+
export declare function maximalMarginalRelevance(queryEmbedding: number[] | number[][], embeddingList: number[][], lambda?: number, k?: number): number[];
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { similarity as ml_distance_similarity, distance as ml_distance, } from "ml-distance";
|
|
2
|
+
/**
|
|
3
|
+
* Apply a row-wise function between two matrices with the same number of columns.
|
|
4
|
+
*
|
|
5
|
+
* @param {number[][]} X - The first matrix.
|
|
6
|
+
* @param {number[][]} Y - The second matrix.
|
|
7
|
+
* @param {VectorFunction} func - The function to apply.
|
|
8
|
+
*
|
|
9
|
+
* @throws {Error} If the number of columns in X and Y are not the same.
|
|
10
|
+
*
|
|
11
|
+
* @returns {number[][] | [[]]} A matrix where each row represents the result of applying the function between the corresponding rows of X and Y.
|
|
12
|
+
*/
|
|
13
|
+
export function matrixFunc(X, Y, func) {
|
|
14
|
+
if (X.length === 0 ||
|
|
15
|
+
X[0].length === 0 ||
|
|
16
|
+
Y.length === 0 ||
|
|
17
|
+
Y[0].length === 0) {
|
|
18
|
+
return [[]];
|
|
19
|
+
}
|
|
20
|
+
if (X[0].length !== Y[0].length) {
|
|
21
|
+
throw new Error(`Number of columns in X and Y must be the same. X has shape ${[
|
|
22
|
+
X.length,
|
|
23
|
+
X[0].length,
|
|
24
|
+
]} and Y has shape ${[Y.length, Y[0].length]}.`);
|
|
25
|
+
}
|
|
26
|
+
return X.map((xVector) => Y.map((yVector) => func(xVector, yVector)).map((similarity) => Number.isNaN(similarity) ? 0 : similarity));
|
|
27
|
+
}
|
|
28
|
+
export function normalize(M, similarity = false) {
|
|
29
|
+
const max = matrixMaxVal(M);
|
|
30
|
+
return M.map((row) => row.map((val) => (similarity ? 1 - val / max : val / max)));
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* This function calculates the row-wise cosine similarity between two matrices with the same number of columns.
|
|
34
|
+
*
|
|
35
|
+
* @param {number[][]} X - The first matrix.
|
|
36
|
+
* @param {number[][]} Y - The second matrix.
|
|
37
|
+
*
|
|
38
|
+
* @throws {Error} If the number of columns in X and Y are not the same.
|
|
39
|
+
*
|
|
40
|
+
* @returns {number[][] | [[]]} A matrix where each row represents the cosine similarity values between the corresponding rows of X and Y.
|
|
41
|
+
*/
|
|
42
|
+
export function cosineSimilarity(X, Y) {
|
|
43
|
+
return matrixFunc(X, Y, ml_distance_similarity.cosine);
|
|
44
|
+
}
|
|
45
|
+
export function innerProduct(X, Y) {
|
|
46
|
+
return matrixFunc(X, Y, ml_distance.innerProduct);
|
|
47
|
+
}
|
|
48
|
+
export function euclideanDistance(X, Y) {
|
|
49
|
+
return matrixFunc(X, Y, ml_distance.euclidean);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* This function implements the Maximal Marginal Relevance algorithm
|
|
53
|
+
* to select a set of embeddings that maximizes the diversity and relevance to a query embedding.
|
|
54
|
+
*
|
|
55
|
+
* @param {number[]|number[][]} queryEmbedding - The query embedding.
|
|
56
|
+
* @param {number[][]} embeddingList - The list of embeddings to select from.
|
|
57
|
+
* @param {number} [lambda=0.5] - The trade-off parameter between relevance and diversity.
|
|
58
|
+
* @param {number} [k=4] - The maximum number of embeddings to select.
|
|
59
|
+
*
|
|
60
|
+
* @returns {number[]} The indexes of the selected embeddings in the embeddingList.
|
|
61
|
+
*/
|
|
62
|
+
export function maximalMarginalRelevance(queryEmbedding, embeddingList, lambda = 0.5, k = 4) {
|
|
63
|
+
if (Math.min(k, embeddingList.length) <= 0) {
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
const queryEmbeddingExpanded = (Array.isArray(queryEmbedding[0]) ? queryEmbedding : [queryEmbedding]);
|
|
67
|
+
const similarityToQuery = cosineSimilarity(queryEmbeddingExpanded, embeddingList)[0];
|
|
68
|
+
const mostSimilarEmbeddingIndex = argMax(similarityToQuery).maxIndex;
|
|
69
|
+
const selectedEmbeddings = [embeddingList[mostSimilarEmbeddingIndex]];
|
|
70
|
+
const selectedEmbeddingsIndexes = [mostSimilarEmbeddingIndex];
|
|
71
|
+
while (selectedEmbeddingsIndexes.length < Math.min(k, embeddingList.length)) {
|
|
72
|
+
let bestScore = -Infinity;
|
|
73
|
+
let bestIndex = -1;
|
|
74
|
+
const similarityToSelected = cosineSimilarity(embeddingList, selectedEmbeddings);
|
|
75
|
+
similarityToQuery.forEach((queryScore, queryScoreIndex) => {
|
|
76
|
+
if (selectedEmbeddingsIndexes.includes(queryScoreIndex)) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const maxSimilarityToSelected = Math.max(...similarityToSelected[queryScoreIndex]);
|
|
80
|
+
const score = lambda * queryScore - (1 - lambda) * maxSimilarityToSelected;
|
|
81
|
+
if (score > bestScore) {
|
|
82
|
+
bestScore = score;
|
|
83
|
+
bestIndex = queryScoreIndex;
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
selectedEmbeddings.push(embeddingList[bestIndex]);
|
|
87
|
+
selectedEmbeddingsIndexes.push(bestIndex);
|
|
88
|
+
}
|
|
89
|
+
return selectedEmbeddingsIndexes;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Finds the index of the maximum value in the given array.
|
|
93
|
+
* @param {number[]} array - The input array.
|
|
94
|
+
*
|
|
95
|
+
* @returns {number} The index of the maximum value in the array. If the array is empty, returns -1.
|
|
96
|
+
*/
|
|
97
|
+
function argMax(array) {
|
|
98
|
+
if (array.length === 0) {
|
|
99
|
+
return {
|
|
100
|
+
maxIndex: -1,
|
|
101
|
+
maxValue: NaN,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
let maxValue = array[0];
|
|
105
|
+
let maxIndex = 0;
|
|
106
|
+
for (let i = 1; i < array.length; i += 1) {
|
|
107
|
+
if (array[i] > maxValue) {
|
|
108
|
+
maxIndex = i;
|
|
109
|
+
maxValue = array[i];
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return { maxIndex, maxValue };
|
|
113
|
+
}
|
|
114
|
+
function matrixMaxVal(arrays) {
|
|
115
|
+
return arrays.reduce((acc, array) => Math.max(acc, argMax(array).maxValue), 0);
|
|
116
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@langchain/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11-rc.1",
|
|
4
4
|
"description": "Core LangChain.js abstractions and schemas",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"decamelize": "1.2.0",
|
|
41
41
|
"js-tiktoken": "^1.0.8",
|
|
42
42
|
"langsmith": "~0.0.48",
|
|
43
|
+
"ml-distance": "^4.0.0",
|
|
43
44
|
"p-queue": "^6.6.2",
|
|
44
45
|
"p-retry": "4",
|
|
45
46
|
"uuid": "^9.0.0",
|
|
@@ -59,6 +60,7 @@
|
|
|
59
60
|
"eslint-plugin-prettier": "^4.2.1",
|
|
60
61
|
"jest": "^29.5.0",
|
|
61
62
|
"jest-environment-node": "^29.6.4",
|
|
63
|
+
"ml-matrix": "^6.10.4",
|
|
62
64
|
"prettier": "^2.8.3",
|
|
63
65
|
"release-it": "^15.10.1",
|
|
64
66
|
"rimraf": "^5.0.1",
|
|
@@ -263,6 +265,11 @@
|
|
|
263
265
|
"import": "./utils/json_schema.js",
|
|
264
266
|
"require": "./utils/json_schema.cjs"
|
|
265
267
|
},
|
|
268
|
+
"./utils/math": {
|
|
269
|
+
"types": "./utils/math.d.ts",
|
|
270
|
+
"import": "./utils/math.js",
|
|
271
|
+
"require": "./utils/math.cjs"
|
|
272
|
+
},
|
|
266
273
|
"./utils/stream": {
|
|
267
274
|
"types": "./utils/stream.d.ts",
|
|
268
275
|
"import": "./utils/stream.js",
|
|
@@ -400,6 +407,9 @@
|
|
|
400
407
|
"utils/json_schema.cjs",
|
|
401
408
|
"utils/json_schema.js",
|
|
402
409
|
"utils/json_schema.d.ts",
|
|
410
|
+
"utils/math.cjs",
|
|
411
|
+
"utils/math.js",
|
|
412
|
+
"utils/math.d.ts",
|
|
403
413
|
"utils/stream.cjs",
|
|
404
414
|
"utils/stream.js",
|
|
405
415
|
"utils/stream.d.ts",
|
package/utils/math.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('../dist/utils/math.cjs');
|
package/utils/math.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../dist/utils/math.js'
|
package/utils/math.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../dist/utils/math.js'
|