@langchain/google-genai 0.2.18 → 1.0.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/CHANGELOG.md +17 -0
- package/LICENSE +6 -6
- package/README.md +8 -8
- package/dist/_virtual/rolldown_runtime.cjs +25 -0
- package/dist/chat_models.cjs +688 -847
- package/dist/chat_models.cjs.map +1 -0
- package/dist/chat_models.d.cts +575 -0
- package/dist/chat_models.d.cts.map +1 -0
- package/dist/chat_models.d.ts +190 -157
- package/dist/chat_models.d.ts.map +1 -0
- package/dist/chat_models.js +686 -842
- package/dist/chat_models.js.map +1 -0
- package/dist/embeddings.cjs +97 -151
- package/dist/embeddings.cjs.map +1 -0
- package/dist/embeddings.d.cts +104 -0
- package/dist/embeddings.d.cts.map +1 -0
- package/dist/embeddings.d.ts +76 -70
- package/dist/embeddings.d.ts.map +1 -0
- package/dist/embeddings.js +93 -144
- package/dist/embeddings.js.map +1 -0
- package/dist/index.cjs +5 -18
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +4 -2
- package/dist/output_parsers.cjs +47 -75
- package/dist/output_parsers.cjs.map +1 -0
- package/dist/output_parsers.js +47 -72
- package/dist/output_parsers.js.map +1 -0
- package/dist/profiles.cjs +345 -0
- package/dist/profiles.cjs.map +1 -0
- package/dist/profiles.js +344 -0
- package/dist/profiles.js.map +1 -0
- package/dist/types.d.cts +8 -0
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.ts +7 -2
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/common.cjs +356 -549
- package/dist/utils/common.cjs.map +1 -0
- package/dist/utils/common.js +357 -545
- package/dist/utils/common.js.map +1 -0
- package/dist/utils/tools.cjs +65 -102
- package/dist/utils/tools.cjs.map +1 -0
- package/dist/utils/tools.js +64 -99
- package/dist/utils/tools.js.map +1 -0
- package/dist/utils/zod_to_genai_parameters.cjs +31 -49
- package/dist/utils/zod_to_genai_parameters.cjs.map +1 -0
- package/dist/utils/zod_to_genai_parameters.js +29 -45
- package/dist/utils/zod_to_genai_parameters.js.map +1 -0
- package/package.json +45 -51
- package/dist/output_parsers.d.ts +0 -20
- package/dist/types.cjs +0 -2
- package/dist/types.js +0 -1
- package/dist/utils/common.d.ts +0 -22
- package/dist/utils/tools.d.ts +0 -10
- package/dist/utils/zod_to_genai_parameters.d.ts +0 -14
- package/index.cjs +0 -1
- package/index.d.cts +0 -1
- package/index.d.ts +0 -1
- package/index.js +0 -1
package/dist/embeddings.d.ts
CHANGED
|
@@ -1,49 +1,52 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { TaskType } from "@google/generative-ai";
|
|
2
2
|
import { Embeddings, EmbeddingsParams } from "@langchain/core/embeddings";
|
|
3
|
+
|
|
4
|
+
//#region src/embeddings.d.ts
|
|
5
|
+
|
|
3
6
|
/**
|
|
4
7
|
* Interface that extends EmbeddingsParams and defines additional
|
|
5
8
|
* parameters specific to the GoogleGenerativeAIEmbeddings class.
|
|
6
9
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
10
|
+
interface GoogleGenerativeAIEmbeddingsParams extends EmbeddingsParams {
|
|
11
|
+
/**
|
|
12
|
+
* Model Name to use
|
|
13
|
+
*
|
|
14
|
+
* Alias for `model`
|
|
15
|
+
*
|
|
16
|
+
* Note: The format must follow the pattern - `{model}`
|
|
17
|
+
*/
|
|
18
|
+
modelName?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Model Name to use
|
|
21
|
+
*
|
|
22
|
+
* Note: The format must follow the pattern - `{model}`
|
|
23
|
+
*/
|
|
24
|
+
model?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Type of task for which the embedding will be used
|
|
27
|
+
*
|
|
28
|
+
* Note: currently only supported by `embedding-001` model
|
|
29
|
+
*/
|
|
30
|
+
taskType?: TaskType;
|
|
31
|
+
/**
|
|
32
|
+
* An optional title for the text. Only applicable when TaskType is
|
|
33
|
+
* `RETRIEVAL_DOCUMENT`
|
|
34
|
+
*
|
|
35
|
+
* Note: currently only supported by `embedding-001` model
|
|
36
|
+
*/
|
|
37
|
+
title?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Whether to strip new lines from the input text. Default to true
|
|
40
|
+
*/
|
|
41
|
+
stripNewLines?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Google API key to use
|
|
44
|
+
*/
|
|
45
|
+
apiKey?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Google API base URL to use
|
|
48
|
+
*/
|
|
49
|
+
baseUrl?: string;
|
|
47
50
|
}
|
|
48
51
|
/**
|
|
49
52
|
* Class that extends the Embeddings class and provides methods for
|
|
@@ -66,33 +69,36 @@ export interface GoogleGenerativeAIEmbeddingsParams extends EmbeddingsParams {
|
|
|
66
69
|
* console.log({ documentRes });
|
|
67
70
|
* ```
|
|
68
71
|
*/
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
72
|
+
declare class GoogleGenerativeAIEmbeddings extends Embeddings implements GoogleGenerativeAIEmbeddingsParams {
|
|
73
|
+
apiKey?: string;
|
|
74
|
+
modelName: string;
|
|
75
|
+
model: string;
|
|
76
|
+
taskType?: TaskType;
|
|
77
|
+
title?: string;
|
|
78
|
+
stripNewLines: boolean;
|
|
79
|
+
maxBatchSize: number; // Max batch size for embedDocuments set by GenerativeModel client's batchEmbedContents call
|
|
80
|
+
private client;
|
|
81
|
+
constructor(fields?: GoogleGenerativeAIEmbeddingsParams);
|
|
82
|
+
private _convertToContent;
|
|
83
|
+
protected _embedQueryContent(text: string): Promise<number[]>;
|
|
84
|
+
protected _embedDocumentsContent(documents: string[]): Promise<number[][]>;
|
|
85
|
+
/**
|
|
86
|
+
* Method that takes a document as input and returns a promise that
|
|
87
|
+
* resolves to an embedding for the document. It calls the _embedText
|
|
88
|
+
* method with the document as the input.
|
|
89
|
+
* @param document Document for which to generate an embedding.
|
|
90
|
+
* @returns Promise that resolves to an embedding for the input document.
|
|
91
|
+
*/
|
|
92
|
+
embedQuery(document: string): Promise<number[]>;
|
|
93
|
+
/**
|
|
94
|
+
* Method that takes an array of documents as input and returns a promise
|
|
95
|
+
* that resolves to a 2D array of embeddings for each document. It calls
|
|
96
|
+
* the _embedText method for each document in the array.
|
|
97
|
+
* @param documents Array of documents for which to generate embeddings.
|
|
98
|
+
* @returns Promise that resolves to a 2D array of embeddings for each input document.
|
|
99
|
+
*/
|
|
100
|
+
embedDocuments(documents: string[]): Promise<number[][]>;
|
|
98
101
|
}
|
|
102
|
+
//#endregion
|
|
103
|
+
export { GoogleGenerativeAIEmbeddings, GoogleGenerativeAIEmbeddingsParams };
|
|
104
|
+
//# sourceMappingURL=embeddings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embeddings.d.ts","names":["TaskType","Embeddings","EmbeddingsParams","GoogleGenerativeAIEmbeddingsParams","GoogleGenerativeAIEmbeddings","Promise"],"sources":["../src/embeddings.d.ts"],"sourcesContent":["import type { TaskType } from \"@google/generative-ai\";\nimport { Embeddings, EmbeddingsParams } from \"@langchain/core/embeddings\";\n/**\n * Interface that extends EmbeddingsParams and defines additional\n * parameters specific to the GoogleGenerativeAIEmbeddings class.\n */\nexport interface GoogleGenerativeAIEmbeddingsParams extends EmbeddingsParams {\n /**\n * Model Name to use\n *\n * Alias for `model`\n *\n * Note: The format must follow the pattern - `{model}`\n */\n modelName?: string;\n /**\n * Model Name to use\n *\n * Note: The format must follow the pattern - `{model}`\n */\n model?: string;\n /**\n * Type of task for which the embedding will be used\n *\n * Note: currently only supported by `embedding-001` model\n */\n taskType?: TaskType;\n /**\n * An optional title for the text. Only applicable when TaskType is\n * `RETRIEVAL_DOCUMENT`\n *\n * Note: currently only supported by `embedding-001` model\n */\n title?: string;\n /**\n * Whether to strip new lines from the input text. Default to true\n */\n stripNewLines?: boolean;\n /**\n * Google API key to use\n */\n apiKey?: string;\n /**\n * Google API base URL to use\n */\n baseUrl?: string;\n}\n/**\n * Class that extends the Embeddings class and provides methods for\n * generating embeddings using the Google Palm API.\n * @example\n * ```typescript\n * const model = new GoogleGenerativeAIEmbeddings({\n * apiKey: \"<YOUR API KEY>\",\n * modelName: \"embedding-001\",\n * });\n *\n * // Embed a single query\n * const res = await model.embedQuery(\n * \"What would be a good company name for a company that makes colorful socks?\"\n * );\n * console.log({ res });\n *\n * // Embed multiple documents\n * const documentRes = await model.embedDocuments([\"Hello world\", \"Bye bye\"]);\n * console.log({ documentRes });\n * ```\n */\nexport declare class GoogleGenerativeAIEmbeddings extends Embeddings implements GoogleGenerativeAIEmbeddingsParams {\n apiKey?: string;\n modelName: string;\n model: string;\n taskType?: TaskType;\n title?: string;\n stripNewLines: boolean;\n maxBatchSize: number; // Max batch size for embedDocuments set by GenerativeModel client's batchEmbedContents call\n private client;\n constructor(fields?: GoogleGenerativeAIEmbeddingsParams);\n private _convertToContent;\n protected _embedQueryContent(text: string): Promise<number[]>;\n protected _embedDocumentsContent(documents: string[]): Promise<number[][]>;\n /**\n * Method that takes a document as input and returns a promise that\n * resolves to an embedding for the document. It calls the _embedText\n * method with the document as the input.\n * @param document Document for which to generate an embedding.\n * @returns Promise that resolves to an embedding for the input document.\n */\n embedQuery(document: string): Promise<number[]>;\n /**\n * Method that takes an array of documents as input and returns a promise\n * that resolves to a 2D array of embeddings for each document. It calls\n * the _embedText method for each document in the array.\n * @param documents Array of documents for which to generate embeddings.\n * @returns Promise that resolves to a 2D array of embeddings for each input document.\n */\n embedDocuments(documents: string[]): Promise<number[][]>;\n}\n"],"mappings":";;;;;;;AAMA;;AAoBeA,UApBEG,kCAAAA,SAA2CD,gBAoB7CF,CAAAA;EAAQ;AApBqD;AA8D5E;;;;;EAWuD,SACIK,CAAAA,EAAAA,MAAAA;EAAO;;;;AAZgD;;;;;;;aA1CnGL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA0CMI,4BAAAA,SAAqCH,UAAAA,YAAsBE;;;;aAIjEH;;;;;uBAKUG;;8CAEuBE;yDACWA;;;;;;;;gCAQzBA;;;;;;;;uCAQOA"}
|
package/dist/embeddings.js
CHANGED
|
@@ -2,148 +2,97 @@ import { GoogleGenerativeAI } from "@google/generative-ai";
|
|
|
2
2
|
import { getEnvironmentVariable } from "@langchain/core/utils/env";
|
|
3
3
|
import { Embeddings } from "@langchain/core/embeddings";
|
|
4
4
|
import { chunkArray } from "@langchain/core/utils/chunk_array";
|
|
5
|
+
|
|
6
|
+
//#region src/embeddings.ts
|
|
5
7
|
/**
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
baseUrl: fields?.baseUrl,
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
_convertToContent(text) {
|
|
101
|
-
const cleanedText = this.stripNewLines ? text.replace(/\n/g, " ") : text;
|
|
102
|
-
return {
|
|
103
|
-
content: { role: "user", parts: [{ text: cleanedText }] },
|
|
104
|
-
taskType: this.taskType,
|
|
105
|
-
title: this.title,
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
async _embedQueryContent(text) {
|
|
109
|
-
const req = this._convertToContent(text);
|
|
110
|
-
const res = await this.client.embedContent(req);
|
|
111
|
-
return res.embedding.values ?? [];
|
|
112
|
-
}
|
|
113
|
-
async _embedDocumentsContent(documents) {
|
|
114
|
-
const batchEmbedChunks = chunkArray(documents, this.maxBatchSize);
|
|
115
|
-
const batchEmbedRequests = batchEmbedChunks.map((chunk) => ({
|
|
116
|
-
requests: chunk.map((doc) => this._convertToContent(doc)),
|
|
117
|
-
}));
|
|
118
|
-
const responses = await Promise.allSettled(batchEmbedRequests.map((req) => this.client.batchEmbedContents(req)));
|
|
119
|
-
const embeddings = responses.flatMap((res, idx) => {
|
|
120
|
-
if (res.status === "fulfilled") {
|
|
121
|
-
return res.value.embeddings.map((e) => e.values || []);
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
return Array(batchEmbedChunks[idx].length).fill([]);
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
return embeddings;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Method that takes a document as input and returns a promise that
|
|
131
|
-
* resolves to an embedding for the document. It calls the _embedText
|
|
132
|
-
* method with the document as the input.
|
|
133
|
-
* @param document Document for which to generate an embedding.
|
|
134
|
-
* @returns Promise that resolves to an embedding for the input document.
|
|
135
|
-
*/
|
|
136
|
-
embedQuery(document) {
|
|
137
|
-
return this.caller.call(this._embedQueryContent.bind(this), document);
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* Method that takes an array of documents as input and returns a promise
|
|
141
|
-
* that resolves to a 2D array of embeddings for each document. It calls
|
|
142
|
-
* the _embedText method for each document in the array.
|
|
143
|
-
* @param documents Array of documents for which to generate embeddings.
|
|
144
|
-
* @returns Promise that resolves to a 2D array of embeddings for each input document.
|
|
145
|
-
*/
|
|
146
|
-
embedDocuments(documents) {
|
|
147
|
-
return this.caller.call(this._embedDocumentsContent.bind(this), documents);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
8
|
+
* Class that extends the Embeddings class and provides methods for
|
|
9
|
+
* generating embeddings using the Google Palm API.
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const model = new GoogleGenerativeAIEmbeddings({
|
|
13
|
+
* apiKey: "<YOUR API KEY>",
|
|
14
|
+
* modelName: "embedding-001",
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* // Embed a single query
|
|
18
|
+
* const res = await model.embedQuery(
|
|
19
|
+
* "What would be a good company name for a company that makes colorful socks?"
|
|
20
|
+
* );
|
|
21
|
+
* console.log({ res });
|
|
22
|
+
*
|
|
23
|
+
* // Embed multiple documents
|
|
24
|
+
* const documentRes = await model.embedDocuments(["Hello world", "Bye bye"]);
|
|
25
|
+
* console.log({ documentRes });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
var GoogleGenerativeAIEmbeddings = class extends Embeddings {
|
|
29
|
+
apiKey;
|
|
30
|
+
modelName = "embedding-001";
|
|
31
|
+
model = "embedding-001";
|
|
32
|
+
taskType;
|
|
33
|
+
title;
|
|
34
|
+
stripNewLines = true;
|
|
35
|
+
maxBatchSize = 100;
|
|
36
|
+
client;
|
|
37
|
+
constructor(fields) {
|
|
38
|
+
super(fields ?? {});
|
|
39
|
+
this.modelName = fields?.model?.replace(/^models\//, "") ?? fields?.modelName?.replace(/^models\//, "") ?? this.modelName;
|
|
40
|
+
this.model = this.modelName;
|
|
41
|
+
this.taskType = fields?.taskType ?? this.taskType;
|
|
42
|
+
this.title = fields?.title ?? this.title;
|
|
43
|
+
if (this.title && this.taskType !== "RETRIEVAL_DOCUMENT") throw new Error("title can only be sepcified with TaskType.RETRIEVAL_DOCUMENT");
|
|
44
|
+
this.apiKey = fields?.apiKey ?? getEnvironmentVariable("GOOGLE_API_KEY");
|
|
45
|
+
if (!this.apiKey) throw new Error("Please set an API key for Google GenerativeAI in the environmentb variable GOOGLE_API_KEY or in the `apiKey` field of the GoogleGenerativeAIEmbeddings constructor");
|
|
46
|
+
this.client = new GoogleGenerativeAI(this.apiKey).getGenerativeModel({ model: this.model }, { baseUrl: fields?.baseUrl });
|
|
47
|
+
}
|
|
48
|
+
_convertToContent(text) {
|
|
49
|
+
const cleanedText = this.stripNewLines ? text.replace(/\n/g, " ") : text;
|
|
50
|
+
return {
|
|
51
|
+
content: {
|
|
52
|
+
role: "user",
|
|
53
|
+
parts: [{ text: cleanedText }]
|
|
54
|
+
},
|
|
55
|
+
taskType: this.taskType,
|
|
56
|
+
title: this.title
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
async _embedQueryContent(text) {
|
|
60
|
+
const req = this._convertToContent(text);
|
|
61
|
+
const res = await this.client.embedContent(req);
|
|
62
|
+
return res.embedding.values ?? [];
|
|
63
|
+
}
|
|
64
|
+
async _embedDocumentsContent(documents) {
|
|
65
|
+
const batchEmbedChunks = chunkArray(documents, this.maxBatchSize);
|
|
66
|
+
const batchEmbedRequests = batchEmbedChunks.map((chunk) => ({ requests: chunk.map((doc) => this._convertToContent(doc)) }));
|
|
67
|
+
const responses = await Promise.allSettled(batchEmbedRequests.map((req) => this.client.batchEmbedContents(req)));
|
|
68
|
+
const embeddings = responses.flatMap((res, idx) => {
|
|
69
|
+
if (res.status === "fulfilled") return res.value.embeddings.map((e) => e.values || []);
|
|
70
|
+
else return Array(batchEmbedChunks[idx].length).fill([]);
|
|
71
|
+
});
|
|
72
|
+
return embeddings;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Method that takes a document as input and returns a promise that
|
|
76
|
+
* resolves to an embedding for the document. It calls the _embedText
|
|
77
|
+
* method with the document as the input.
|
|
78
|
+
* @param document Document for which to generate an embedding.
|
|
79
|
+
* @returns Promise that resolves to an embedding for the input document.
|
|
80
|
+
*/
|
|
81
|
+
embedQuery(document) {
|
|
82
|
+
return this.caller.call(this._embedQueryContent.bind(this), document);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Method that takes an array of documents as input and returns a promise
|
|
86
|
+
* that resolves to a 2D array of embeddings for each document. It calls
|
|
87
|
+
* the _embedText method for each document in the array.
|
|
88
|
+
* @param documents Array of documents for which to generate embeddings.
|
|
89
|
+
* @returns Promise that resolves to a 2D array of embeddings for each input document.
|
|
90
|
+
*/
|
|
91
|
+
embedDocuments(documents) {
|
|
92
|
+
return this.caller.call(this._embedDocumentsContent.bind(this), documents);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
//#endregion
|
|
97
|
+
export { GoogleGenerativeAIEmbeddings };
|
|
98
|
+
//# sourceMappingURL=embeddings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embeddings.js","names":["fields?: GoogleGenerativeAIEmbeddingsParams","text: string","documents: string[]","batchEmbedChunks: string[][]","document: string"],"sources":["../src/embeddings.ts"],"sourcesContent":["import { GoogleGenerativeAI, GenerativeModel } from \"@google/generative-ai\";\nimport type { TaskType, EmbedContentRequest } from \"@google/generative-ai\";\nimport { getEnvironmentVariable } from \"@langchain/core/utils/env\";\nimport { Embeddings, EmbeddingsParams } from \"@langchain/core/embeddings\";\nimport { chunkArray } from \"@langchain/core/utils/chunk_array\";\n\n/**\n * Interface that extends EmbeddingsParams and defines additional\n * parameters specific to the GoogleGenerativeAIEmbeddings class.\n */\nexport interface GoogleGenerativeAIEmbeddingsParams extends EmbeddingsParams {\n /**\n * Model Name to use\n *\n * Alias for `model`\n *\n * Note: The format must follow the pattern - `{model}`\n */\n modelName?: string;\n /**\n * Model Name to use\n *\n * Note: The format must follow the pattern - `{model}`\n */\n model?: string;\n\n /**\n * Type of task for which the embedding will be used\n *\n * Note: currently only supported by `embedding-001` model\n */\n taskType?: TaskType;\n\n /**\n * An optional title for the text. Only applicable when TaskType is\n * `RETRIEVAL_DOCUMENT`\n *\n * Note: currently only supported by `embedding-001` model\n */\n title?: string;\n\n /**\n * Whether to strip new lines from the input text. Default to true\n */\n stripNewLines?: boolean;\n\n /**\n * Google API key to use\n */\n apiKey?: string;\n\n /**\n * Google API base URL to use\n */\n baseUrl?: string;\n}\n\n/**\n * Class that extends the Embeddings class and provides methods for\n * generating embeddings using the Google Palm API.\n * @example\n * ```typescript\n * const model = new GoogleGenerativeAIEmbeddings({\n * apiKey: \"<YOUR API KEY>\",\n * modelName: \"embedding-001\",\n * });\n *\n * // Embed a single query\n * const res = await model.embedQuery(\n * \"What would be a good company name for a company that makes colorful socks?\"\n * );\n * console.log({ res });\n *\n * // Embed multiple documents\n * const documentRes = await model.embedDocuments([\"Hello world\", \"Bye bye\"]);\n * console.log({ documentRes });\n * ```\n */\nexport class GoogleGenerativeAIEmbeddings\n extends Embeddings\n implements GoogleGenerativeAIEmbeddingsParams\n{\n apiKey?: string;\n\n modelName = \"embedding-001\";\n\n model = \"embedding-001\";\n\n taskType?: TaskType;\n\n title?: string;\n\n stripNewLines = true;\n\n maxBatchSize = 100; // Max batch size for embedDocuments set by GenerativeModel client's batchEmbedContents call\n\n private client: GenerativeModel;\n\n constructor(fields?: GoogleGenerativeAIEmbeddingsParams) {\n super(fields ?? {});\n\n this.modelName =\n fields?.model?.replace(/^models\\//, \"\") ??\n fields?.modelName?.replace(/^models\\//, \"\") ??\n this.modelName;\n this.model = this.modelName;\n\n this.taskType = fields?.taskType ?? this.taskType;\n\n this.title = fields?.title ?? this.title;\n\n if (this.title && this.taskType !== \"RETRIEVAL_DOCUMENT\") {\n throw new Error(\n \"title can only be sepcified with TaskType.RETRIEVAL_DOCUMENT\"\n );\n }\n\n this.apiKey = fields?.apiKey ?? getEnvironmentVariable(\"GOOGLE_API_KEY\");\n if (!this.apiKey) {\n throw new Error(\n \"Please set an API key for Google GenerativeAI \" +\n \"in the environmentb variable GOOGLE_API_KEY \" +\n \"or in the `apiKey` field of the \" +\n \"GoogleGenerativeAIEmbeddings constructor\"\n );\n }\n\n this.client = new GoogleGenerativeAI(this.apiKey).getGenerativeModel(\n {\n model: this.model,\n },\n {\n baseUrl: fields?.baseUrl,\n }\n );\n }\n\n private _convertToContent(text: string): EmbedContentRequest {\n const cleanedText = this.stripNewLines ? text.replace(/\\n/g, \" \") : text;\n return {\n content: { role: \"user\", parts: [{ text: cleanedText }] },\n taskType: this.taskType,\n title: this.title,\n };\n }\n\n protected async _embedQueryContent(text: string): Promise<number[]> {\n const req = this._convertToContent(text);\n const res = await this.client.embedContent(req);\n return res.embedding.values ?? [];\n }\n\n protected async _embedDocumentsContent(\n documents: string[]\n ): Promise<number[][]> {\n const batchEmbedChunks: string[][] = chunkArray<string>(\n documents,\n this.maxBatchSize\n );\n\n const batchEmbedRequests = batchEmbedChunks.map((chunk) => ({\n requests: chunk.map((doc) => this._convertToContent(doc)),\n }));\n\n const responses = await Promise.allSettled(\n batchEmbedRequests.map((req) => this.client.batchEmbedContents(req))\n );\n\n const embeddings = responses.flatMap((res, idx) => {\n if (res.status === \"fulfilled\") {\n return res.value.embeddings.map((e) => e.values || []);\n } else {\n return Array(batchEmbedChunks[idx].length).fill([]);\n }\n });\n\n return embeddings;\n }\n\n /**\n * Method that takes a document as input and returns a promise that\n * resolves to an embedding for the document. It calls the _embedText\n * method with the document as the input.\n * @param document Document for which to generate an embedding.\n * @returns Promise that resolves to an embedding for the input document.\n */\n embedQuery(document: string): Promise<number[]> {\n return this.caller.call(this._embedQueryContent.bind(this), document);\n }\n\n /**\n * Method that takes an array of documents as input and returns a promise\n * that resolves to a 2D array of embeddings for each document. It calls\n * the _embedText method for each document in the array.\n * @param documents Array of documents for which to generate embeddings.\n * @returns Promise that resolves to a 2D array of embeddings for each input document.\n */\n embedDocuments(documents: string[]): Promise<number[][]> {\n return this.caller.call(this._embedDocumentsContent.bind(this), documents);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA8EA,IAAa,+BAAb,cACU,WAEV;CACE;CAEA,YAAY;CAEZ,QAAQ;CAER;CAEA;CAEA,gBAAgB;CAEhB,eAAe;CAEf,AAAQ;CAER,YAAYA,QAA6C;EACvD,MAAM,UAAU,CAAE,EAAC;EAEnB,KAAK,YACH,QAAQ,OAAO,QAAQ,aAAa,GAAG,IACvC,QAAQ,WAAW,QAAQ,aAAa,GAAG,IAC3C,KAAK;EACP,KAAK,QAAQ,KAAK;EAElB,KAAK,WAAW,QAAQ,YAAY,KAAK;EAEzC,KAAK,QAAQ,QAAQ,SAAS,KAAK;AAEnC,MAAI,KAAK,SAAS,KAAK,aAAa,qBAClC,OAAM,IAAI,MACR;EAIJ,KAAK,SAAS,QAAQ,UAAU,uBAAuB,iBAAiB;AACxE,MAAI,CAAC,KAAK,OACR,OAAM,IAAI,MACR;EAOJ,KAAK,SAAS,IAAI,mBAAmB,KAAK,QAAQ,mBAChD,EACE,OAAO,KAAK,MACb,GACD,EACE,SAAS,QAAQ,QAClB,EACF;CACF;CAED,AAAQ,kBAAkBC,MAAmC;EAC3D,MAAM,cAAc,KAAK,gBAAgB,KAAK,QAAQ,OAAO,IAAI,GAAG;AACpE,SAAO;GACL,SAAS;IAAE,MAAM;IAAQ,OAAO,CAAC,EAAE,MAAM,YAAa,CAAC;GAAE;GACzD,UAAU,KAAK;GACf,OAAO,KAAK;EACb;CACF;CAED,MAAgB,mBAAmBA,MAAiC;EAClE,MAAM,MAAM,KAAK,kBAAkB,KAAK;EACxC,MAAM,MAAM,MAAM,KAAK,OAAO,aAAa,IAAI;AAC/C,SAAO,IAAI,UAAU,UAAU,CAAE;CAClC;CAED,MAAgB,uBACdC,WACqB;EACrB,MAAMC,mBAA+B,WACnC,WACA,KAAK,aACN;EAED,MAAM,qBAAqB,iBAAiB,IAAI,CAAC,WAAW,EAC1D,UAAU,MAAM,IAAI,CAAC,QAAQ,KAAK,kBAAkB,IAAI,CAAC,CAC1D,GAAE;EAEH,MAAM,YAAY,MAAM,QAAQ,WAC9B,mBAAmB,IAAI,CAAC,QAAQ,KAAK,OAAO,mBAAmB,IAAI,CAAC,CACrE;EAED,MAAM,aAAa,UAAU,QAAQ,CAAC,KAAK,QAAQ;AACjD,OAAI,IAAI,WAAW,YACjB,QAAO,IAAI,MAAM,WAAW,IAAI,CAAC,MAAM,EAAE,UAAU,CAAE,EAAC;OAEtD,QAAO,MAAM,iBAAiB,KAAK,OAAO,CAAC,KAAK,CAAE,EAAC;EAEtD,EAAC;AAEF,SAAO;CACR;;;;;;;;CASD,WAAWC,UAAqC;AAC9C,SAAO,KAAK,OAAO,KAAK,KAAK,mBAAmB,KAAK,KAAK,EAAE,SAAS;CACtE;;;;;;;;CASD,eAAeF,WAA0C;AACvD,SAAO,KAAK,OAAO,KAAK,KAAK,uBAAuB,KAAK,KAAK,EAAE,UAAU;CAC3E;AACF"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,18 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./chat_models.cjs"), exports);
|
|
18
|
-
__exportStar(require("./embeddings.cjs"), exports);
|
|
1
|
+
const require_chat_models = require('./chat_models.cjs');
|
|
2
|
+
const require_embeddings = require('./embeddings.cjs');
|
|
3
|
+
|
|
4
|
+
exports.ChatGoogleGenerativeAI = require_chat_models.ChatGoogleGenerativeAI;
|
|
5
|
+
exports.GoogleGenerativeAIEmbeddings = require_embeddings.GoogleGenerativeAIEmbeddings;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { BaseMessageExamplePair, ChatGoogleGenerativeAI, GoogleGenerativeAIChatCallOptions, GoogleGenerativeAIChatInput } from "./chat_models.cjs";
|
|
2
|
+
import { GoogleGenerativeAIEmbeddings, GoogleGenerativeAIEmbeddingsParams } from "./embeddings.cjs";
|
|
3
|
+
export { BaseMessageExamplePair, ChatGoogleGenerativeAI, GoogleGenerativeAIChatCallOptions, GoogleGenerativeAIChatInput, GoogleGenerativeAIEmbeddings, GoogleGenerativeAIEmbeddingsParams };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { BaseMessageExamplePair, ChatGoogleGenerativeAI, GoogleGenerativeAIChatCallOptions, GoogleGenerativeAIChatInput } from "./chat_models.js";
|
|
2
|
+
import { GoogleGenerativeAIEmbeddings, GoogleGenerativeAIEmbeddingsParams } from "./embeddings.js";
|
|
3
|
+
export { BaseMessageExamplePair, ChatGoogleGenerativeAI, GoogleGenerativeAIChatCallOptions, GoogleGenerativeAIChatInput, GoogleGenerativeAIEmbeddings, GoogleGenerativeAIEmbeddingsParams };
|
package/dist/index.js
CHANGED
package/dist/output_parsers.cjs
CHANGED
|
@@ -1,76 +1,48 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
async _validateResult(result) {
|
|
49
|
-
if (this.zodSchema === undefined) {
|
|
50
|
-
return result;
|
|
51
|
-
}
|
|
52
|
-
const zodParsedResult = await (0, types_1.interopSafeParseAsync)(this.zodSchema, result);
|
|
53
|
-
if (zodParsedResult.success) {
|
|
54
|
-
return zodParsedResult.data;
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
throw new output_parsers_1.OutputParserException(`Failed to parse. Text: "${JSON.stringify(result, null, 2)}". Error: ${JSON.stringify(zodParsedResult.error.issues)}`, JSON.stringify(result, null, 2));
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
async parseResult(generations) {
|
|
61
|
-
const tools = generations.flatMap((generation) => {
|
|
62
|
-
const { message } = generation;
|
|
63
|
-
if (!("tool_calls" in message) || !Array.isArray(message.tool_calls)) {
|
|
64
|
-
return [];
|
|
65
|
-
}
|
|
66
|
-
return message.tool_calls;
|
|
67
|
-
});
|
|
68
|
-
if (tools[0] === undefined) {
|
|
69
|
-
throw new Error("No parseable tool calls provided to GoogleGenerativeAIToolsOutputParser.");
|
|
70
|
-
}
|
|
71
|
-
const [tool] = tools;
|
|
72
|
-
const validatedResult = await this._validateResult(tool.args);
|
|
73
|
-
return validatedResult;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
1
|
+
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const __langchain_core_utils_types = require_rolldown_runtime.__toESM(require("@langchain/core/utils/types"));
|
|
3
|
+
const __langchain_core_output_parsers = require_rolldown_runtime.__toESM(require("@langchain/core/output_parsers"));
|
|
4
|
+
|
|
5
|
+
//#region src/output_parsers.ts
|
|
6
|
+
var GoogleGenerativeAIToolsOutputParser = class extends __langchain_core_output_parsers.BaseLLMOutputParser {
|
|
7
|
+
static lc_name() {
|
|
8
|
+
return "GoogleGenerativeAIToolsOutputParser";
|
|
9
|
+
}
|
|
10
|
+
lc_namespace = [
|
|
11
|
+
"langchain",
|
|
12
|
+
"google_genai",
|
|
13
|
+
"output_parsers"
|
|
14
|
+
];
|
|
15
|
+
returnId = false;
|
|
16
|
+
/** The type of tool calls to return. */
|
|
17
|
+
keyName;
|
|
18
|
+
/** Whether to return only the first tool call. */
|
|
19
|
+
returnSingle = false;
|
|
20
|
+
zodSchema;
|
|
21
|
+
constructor(params) {
|
|
22
|
+
super(params);
|
|
23
|
+
this.keyName = params.keyName;
|
|
24
|
+
this.returnSingle = params.returnSingle ?? this.returnSingle;
|
|
25
|
+
this.zodSchema = params.zodSchema;
|
|
26
|
+
}
|
|
27
|
+
async _validateResult(result) {
|
|
28
|
+
if (this.zodSchema === void 0) return result;
|
|
29
|
+
const zodParsedResult = await (0, __langchain_core_utils_types.interopSafeParseAsync)(this.zodSchema, result);
|
|
30
|
+
if (zodParsedResult.success) return zodParsedResult.data;
|
|
31
|
+
else throw new __langchain_core_output_parsers.OutputParserException(`Failed to parse. Text: "${JSON.stringify(result, null, 2)}". Error: ${JSON.stringify(zodParsedResult.error.issues)}`, JSON.stringify(result, null, 2));
|
|
32
|
+
}
|
|
33
|
+
async parseResult(generations) {
|
|
34
|
+
const tools = generations.flatMap((generation) => {
|
|
35
|
+
const { message } = generation;
|
|
36
|
+
if (!("tool_calls" in message) || !Array.isArray(message.tool_calls)) return [];
|
|
37
|
+
return message.tool_calls;
|
|
38
|
+
});
|
|
39
|
+
if (tools[0] === void 0) throw new Error("No parseable tool calls provided to GoogleGenerativeAIToolsOutputParser.");
|
|
40
|
+
const [tool] = tools;
|
|
41
|
+
const validatedResult = await this._validateResult(tool.args);
|
|
42
|
+
return validatedResult;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
//#endregion
|
|
76
47
|
exports.GoogleGenerativeAIToolsOutputParser = GoogleGenerativeAIToolsOutputParser;
|
|
48
|
+
//# sourceMappingURL=output_parsers.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output_parsers.cjs","names":["BaseLLMOutputParser","params: GoogleGenerativeAIToolsOutputParserParams<T>","result: unknown","OutputParserException","generations: ChatGeneration[]"],"sources":["../src/output_parsers.ts"],"sourcesContent":["import {\n BaseLLMOutputParser,\n OutputParserException,\n} from \"@langchain/core/output_parsers\";\nimport { ChatGeneration } from \"@langchain/core/outputs\";\nimport { ToolCall } from \"@langchain/core/messages/tool\";\nimport {\n InteropZodType,\n interopSafeParseAsync,\n} from \"@langchain/core/utils/types\";\nimport { JsonOutputKeyToolsParserParamsInterop } from \"@langchain/core/output_parsers/openai_tools\";\n\ninterface GoogleGenerativeAIToolsOutputParserParams<\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n T extends Record<string, any>\n> extends JsonOutputKeyToolsParserParamsInterop<T> {}\n\nexport class GoogleGenerativeAIToolsOutputParser<\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n T extends Record<string, any> = Record<string, any>\n> extends BaseLLMOutputParser<T> {\n static lc_name() {\n return \"GoogleGenerativeAIToolsOutputParser\";\n }\n\n lc_namespace = [\"langchain\", \"google_genai\", \"output_parsers\"];\n\n returnId = false;\n\n /** The type of tool calls to return. */\n keyName: string;\n\n /** Whether to return only the first tool call. */\n returnSingle = false;\n\n zodSchema?: InteropZodType<T>;\n\n constructor(params: GoogleGenerativeAIToolsOutputParserParams<T>) {\n super(params);\n this.keyName = params.keyName;\n this.returnSingle = params.returnSingle ?? this.returnSingle;\n this.zodSchema = params.zodSchema;\n }\n\n protected async _validateResult(result: unknown): Promise<T> {\n if (this.zodSchema === undefined) {\n return result as T;\n }\n const zodParsedResult = await interopSafeParseAsync(this.zodSchema, result);\n if (zodParsedResult.success) {\n return zodParsedResult.data;\n } else {\n throw new OutputParserException(\n `Failed to parse. Text: \"${JSON.stringify(\n result,\n null,\n 2\n )}\". Error: ${JSON.stringify(zodParsedResult.error.issues)}`,\n JSON.stringify(result, null, 2)\n );\n }\n }\n\n async parseResult(generations: ChatGeneration[]): Promise<T> {\n const tools = generations.flatMap((generation) => {\n const { message } = generation;\n if (!(\"tool_calls\" in message) || !Array.isArray(message.tool_calls)) {\n return [];\n }\n return message.tool_calls as ToolCall[];\n });\n if (tools[0] === undefined) {\n throw new Error(\n \"No parseable tool calls provided to GoogleGenerativeAIToolsOutputParser.\"\n );\n }\n const [tool] = tools;\n const validatedResult = await this._validateResult(tool.args);\n return validatedResult;\n }\n}\n"],"mappings":";;;;;AAiBA,IAAa,sCAAb,cAGUA,oDAAuB;CAC/B,OAAO,UAAU;AACf,SAAO;CACR;CAED,eAAe;EAAC;EAAa;EAAgB;CAAiB;CAE9D,WAAW;;CAGX;;CAGA,eAAe;CAEf;CAEA,YAAYC,QAAsD;EAChE,MAAM,OAAO;EACb,KAAK,UAAU,OAAO;EACtB,KAAK,eAAe,OAAO,gBAAgB,KAAK;EAChD,KAAK,YAAY,OAAO;CACzB;CAED,MAAgB,gBAAgBC,QAA6B;AAC3D,MAAI,KAAK,cAAc,OACrB,QAAO;EAET,MAAM,kBAAkB,8DAA4B,KAAK,WAAW,OAAO;AAC3E,MAAI,gBAAgB,QAClB,QAAO,gBAAgB;MAEvB,OAAM,IAAIC,sDACR,CAAC,wBAAwB,EAAE,KAAK,UAC9B,QACA,MACA,EACD,CAAC,UAAU,EAAE,KAAK,UAAU,gBAAgB,MAAM,OAAO,EAAE,EAC5D,KAAK,UAAU,QAAQ,MAAM,EAAE;CAGpC;CAED,MAAM,YAAYC,aAA2C;EAC3D,MAAM,QAAQ,YAAY,QAAQ,CAAC,eAAe;GAChD,MAAM,EAAE,SAAS,GAAG;AACpB,OAAI,EAAE,gBAAgB,YAAY,CAAC,MAAM,QAAQ,QAAQ,WAAW,CAClE,QAAO,CAAE;AAEX,UAAO,QAAQ;EAChB,EAAC;AACF,MAAI,MAAM,OAAO,OACf,OAAM,IAAI,MACR;EAGJ,MAAM,CAAC,KAAK,GAAG;EACf,MAAM,kBAAkB,MAAM,KAAK,gBAAgB,KAAK,KAAK;AAC7D,SAAO;CACR;AACF"}
|