@langchain/google-common 0.0.27 → 0.1.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/auth.cjs +26 -5
- package/dist/auth.d.ts +3 -2
- package/dist/auth.js +26 -5
- package/dist/chat_models.cjs +13 -11
- package/dist/chat_models.d.ts +5 -6
- package/dist/chat_models.js +13 -12
- package/dist/connection.cjs +34 -7
- package/dist/connection.d.ts +14 -8
- package/dist/connection.js +32 -6
- package/dist/embeddings.cjs +4 -2
- package/dist/embeddings.js +4 -2
- package/dist/experimental/media.cjs +494 -0
- package/dist/experimental/media.d.ts +210 -0
- package/dist/experimental/media.js +478 -0
- package/dist/experimental/utils/media_core.cjs +524 -0
- package/dist/experimental/utils/media_core.d.ts +209 -0
- package/dist/experimental/utils/media_core.js +514 -0
- package/dist/llms.cjs +10 -5
- package/dist/llms.d.ts +4 -1
- package/dist/llms.js +11 -6
- package/dist/types.d.ts +8 -1
- package/dist/utils/gemini.cjs +493 -490
- package/dist/utils/gemini.d.ts +15 -50
- package/dist/utils/gemini.js +491 -464
- package/experimental/media.cjs +1 -0
- package/experimental/media.d.cts +1 -0
- package/experimental/media.d.ts +1 -0
- package/experimental/media.js +1 -0
- package/experimental/utils/media_core.cjs +1 -0
- package/experimental/utils/media_core.d.cts +1 -0
- package/experimental/utils/media_core.d.ts +1 -0
- package/experimental/utils/media_core.js +1 -0
- package/package.json +32 -3
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
import { v1, v4 } from "uuid"; // FIXME - it is importing the wrong uuid, so v6 and v7 aren't implemented
|
|
2
|
+
import { BaseStore } from "@langchain/core/stores";
|
|
3
|
+
import { Serializable } from "@langchain/core/load/serializable";
|
|
4
|
+
function bytesToString(dataArray) {
|
|
5
|
+
// Need to handle the array in smaller chunks to deal with stack size limits
|
|
6
|
+
let ret = "";
|
|
7
|
+
const chunkSize = 102400;
|
|
8
|
+
for (let i = 0; i < dataArray.length; i += chunkSize) {
|
|
9
|
+
const chunk = dataArray.subarray(i, i + chunkSize);
|
|
10
|
+
ret += String.fromCharCode(...chunk);
|
|
11
|
+
}
|
|
12
|
+
return ret;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Represents a chunk of data that can be identified by the path where the
|
|
16
|
+
* data is (or will be) located, along with optional metadata about the data.
|
|
17
|
+
*/
|
|
18
|
+
export class MediaBlob extends Serializable {
|
|
19
|
+
constructor(params) {
|
|
20
|
+
super(params);
|
|
21
|
+
Object.defineProperty(this, "lc_serializable", {
|
|
22
|
+
enumerable: true,
|
|
23
|
+
configurable: true,
|
|
24
|
+
writable: true,
|
|
25
|
+
value: true
|
|
26
|
+
});
|
|
27
|
+
Object.defineProperty(this, "lc_namespace", {
|
|
28
|
+
enumerable: true,
|
|
29
|
+
configurable: true,
|
|
30
|
+
writable: true,
|
|
31
|
+
value: [
|
|
32
|
+
"langchain",
|
|
33
|
+
"google_common",
|
|
34
|
+
"experimental",
|
|
35
|
+
"utils",
|
|
36
|
+
"media_core",
|
|
37
|
+
]
|
|
38
|
+
});
|
|
39
|
+
Object.defineProperty(this, "data", {
|
|
40
|
+
enumerable: true,
|
|
41
|
+
configurable: true,
|
|
42
|
+
writable: true,
|
|
43
|
+
value: {
|
|
44
|
+
value: "",
|
|
45
|
+
type: "text/plain",
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
49
|
+
Object.defineProperty(this, "metadata", {
|
|
50
|
+
enumerable: true,
|
|
51
|
+
configurable: true,
|
|
52
|
+
writable: true,
|
|
53
|
+
value: void 0
|
|
54
|
+
});
|
|
55
|
+
Object.defineProperty(this, "path", {
|
|
56
|
+
enumerable: true,
|
|
57
|
+
configurable: true,
|
|
58
|
+
writable: true,
|
|
59
|
+
value: void 0
|
|
60
|
+
});
|
|
61
|
+
this.data = params.data ?? this.data;
|
|
62
|
+
this.metadata = params.metadata;
|
|
63
|
+
this.path = params.path;
|
|
64
|
+
}
|
|
65
|
+
get size() {
|
|
66
|
+
return this.asBytes.length;
|
|
67
|
+
}
|
|
68
|
+
get dataType() {
|
|
69
|
+
return this.data?.type ?? "";
|
|
70
|
+
}
|
|
71
|
+
get encoding() {
|
|
72
|
+
const charsetEquals = this.dataType.indexOf("charset=");
|
|
73
|
+
return charsetEquals === -1
|
|
74
|
+
? "utf-8"
|
|
75
|
+
: this.dataType.substring(charsetEquals + 8);
|
|
76
|
+
}
|
|
77
|
+
get mimetype() {
|
|
78
|
+
const semicolon = this.dataType.indexOf(";");
|
|
79
|
+
return semicolon === -1
|
|
80
|
+
? this.dataType
|
|
81
|
+
: this.dataType.substring(0, semicolon);
|
|
82
|
+
}
|
|
83
|
+
get asBytes() {
|
|
84
|
+
if (!this.data) {
|
|
85
|
+
return Uint8Array.from([]);
|
|
86
|
+
}
|
|
87
|
+
const binString = atob(this.data?.value);
|
|
88
|
+
const ret = new Uint8Array(binString.length);
|
|
89
|
+
for (let co = 0; co < binString.length; co += 1) {
|
|
90
|
+
ret[co] = binString.charCodeAt(co);
|
|
91
|
+
}
|
|
92
|
+
return ret;
|
|
93
|
+
}
|
|
94
|
+
async asString() {
|
|
95
|
+
return bytesToString(this.asBytes);
|
|
96
|
+
}
|
|
97
|
+
async asBase64() {
|
|
98
|
+
return this.data?.value ?? "";
|
|
99
|
+
}
|
|
100
|
+
async asDataUrl() {
|
|
101
|
+
return `data:${this.mimetype};base64,${await this.asBase64()}`;
|
|
102
|
+
}
|
|
103
|
+
async asUri() {
|
|
104
|
+
return this.path ?? (await this.asDataUrl());
|
|
105
|
+
}
|
|
106
|
+
async encode() {
|
|
107
|
+
const dataUrl = await this.asDataUrl();
|
|
108
|
+
const comma = dataUrl.indexOf(",");
|
|
109
|
+
const encoded = dataUrl.substring(comma + 1);
|
|
110
|
+
const encoding = dataUrl.indexOf("base64") > -1 ? "base64" : "8bit";
|
|
111
|
+
return {
|
|
112
|
+
encoded,
|
|
113
|
+
encoding,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
static fromDataUrl(url) {
|
|
117
|
+
if (!url.startsWith("data:")) {
|
|
118
|
+
throw new Error("Not a data: URL");
|
|
119
|
+
}
|
|
120
|
+
const colon = url.indexOf(":");
|
|
121
|
+
const semicolon = url.indexOf(";");
|
|
122
|
+
const mimeType = url.substring(colon + 1, semicolon);
|
|
123
|
+
const comma = url.indexOf(",");
|
|
124
|
+
const base64Data = url.substring(comma + 1);
|
|
125
|
+
const data = {
|
|
126
|
+
type: mimeType,
|
|
127
|
+
value: base64Data,
|
|
128
|
+
};
|
|
129
|
+
return new MediaBlob({
|
|
130
|
+
data,
|
|
131
|
+
path: url,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
static async fromBlob(blob, other) {
|
|
135
|
+
const valueBuffer = await blob.arrayBuffer();
|
|
136
|
+
const valueArray = new Uint8Array(valueBuffer);
|
|
137
|
+
const valueStr = bytesToString(valueArray);
|
|
138
|
+
const value = btoa(valueStr);
|
|
139
|
+
return new MediaBlob({
|
|
140
|
+
...other,
|
|
141
|
+
data: {
|
|
142
|
+
value,
|
|
143
|
+
type: blob.type,
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* A specialized Store that is designed to handle MediaBlobs and use the
|
|
150
|
+
* key that is included in the blob to determine exactly how it is stored.
|
|
151
|
+
*
|
|
152
|
+
* The full details of a MediaBlob may be changed when it is stored.
|
|
153
|
+
* For example, it may get additional or different Metadata. This should be
|
|
154
|
+
* what is returned when the store() method is called.
|
|
155
|
+
*
|
|
156
|
+
* Although BlobStore extends BaseStore, not all of the methods from
|
|
157
|
+
* BaseStore may be implemented (or even possible). Those that are not
|
|
158
|
+
* implemented should be documented and throw an Error if called.
|
|
159
|
+
*/
|
|
160
|
+
export class BlobStore extends BaseStore {
|
|
161
|
+
constructor(opts) {
|
|
162
|
+
super(opts);
|
|
163
|
+
Object.defineProperty(this, "lc_namespace", {
|
|
164
|
+
enumerable: true,
|
|
165
|
+
configurable: true,
|
|
166
|
+
writable: true,
|
|
167
|
+
value: ["langchain", "google-common"]
|
|
168
|
+
}); // FIXME - What should this be? And why?
|
|
169
|
+
Object.defineProperty(this, "defaultStoreOptions", {
|
|
170
|
+
enumerable: true,
|
|
171
|
+
configurable: true,
|
|
172
|
+
writable: true,
|
|
173
|
+
value: void 0
|
|
174
|
+
});
|
|
175
|
+
Object.defineProperty(this, "defaultFetchOptions", {
|
|
176
|
+
enumerable: true,
|
|
177
|
+
configurable: true,
|
|
178
|
+
writable: true,
|
|
179
|
+
value: void 0
|
|
180
|
+
});
|
|
181
|
+
this.defaultStoreOptions = opts?.defaultStoreOptions ?? {};
|
|
182
|
+
this.defaultFetchOptions = opts?.defaultFetchOptions ?? {};
|
|
183
|
+
}
|
|
184
|
+
async _realKey(key) {
|
|
185
|
+
return typeof key === "string" ? key : await key.asUri();
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Is the path supported by this BlobStore?
|
|
189
|
+
*
|
|
190
|
+
* Although this is async, this is expected to be a relatively fast operation
|
|
191
|
+
* (ie - you shouldn't make network calls).
|
|
192
|
+
*
|
|
193
|
+
* @param path The path to check
|
|
194
|
+
* @param opts Any options (if needed) that may be used to determine if it is valid
|
|
195
|
+
* @return If the path is supported
|
|
196
|
+
*/
|
|
197
|
+
hasValidPath(path, opts) {
|
|
198
|
+
const prefix = opts?.pathPrefix ?? "";
|
|
199
|
+
const isPrefixed = typeof path !== "undefined" && path.startsWith(prefix);
|
|
200
|
+
return Promise.resolve(isPrefixed);
|
|
201
|
+
}
|
|
202
|
+
_blobPathSuffix(blob) {
|
|
203
|
+
// Get the path currently set and make sure we treat it as a string
|
|
204
|
+
const blobPath = `${blob.path}`;
|
|
205
|
+
// Advance past the first set of /
|
|
206
|
+
let pathStart = blobPath.indexOf("/") + 1;
|
|
207
|
+
while (blobPath.charAt(pathStart) === "/") {
|
|
208
|
+
pathStart += 1;
|
|
209
|
+
}
|
|
210
|
+
// We will use the rest as the path for a replacement
|
|
211
|
+
return blobPath.substring(pathStart);
|
|
212
|
+
}
|
|
213
|
+
async _newBlob(oldBlob, newPath) {
|
|
214
|
+
const oldPath = oldBlob.path;
|
|
215
|
+
const metadata = oldBlob?.metadata ?? {};
|
|
216
|
+
metadata.langchainOldPath = oldPath;
|
|
217
|
+
const newBlob = new MediaBlob({
|
|
218
|
+
...oldBlob,
|
|
219
|
+
metadata,
|
|
220
|
+
});
|
|
221
|
+
if (newPath) {
|
|
222
|
+
newBlob.path = newPath;
|
|
223
|
+
}
|
|
224
|
+
else if (newBlob.path) {
|
|
225
|
+
delete newBlob.path;
|
|
226
|
+
}
|
|
227
|
+
return newBlob;
|
|
228
|
+
}
|
|
229
|
+
async _validBlobPrefixPath(blob, opts) {
|
|
230
|
+
const prefix = opts?.pathPrefix ?? "";
|
|
231
|
+
const suffix = this._blobPathSuffix(blob);
|
|
232
|
+
const newPath = `${prefix}${suffix}`;
|
|
233
|
+
return this._newBlob(blob, newPath);
|
|
234
|
+
}
|
|
235
|
+
_validBlobPrefixUuidFunction(name) {
|
|
236
|
+
switch (name) {
|
|
237
|
+
case "prefixUuid1":
|
|
238
|
+
return v1();
|
|
239
|
+
case "prefixUuid4":
|
|
240
|
+
return v4();
|
|
241
|
+
// case "prefixUuid6": return v6();
|
|
242
|
+
// case "prefixUuid7": return v7();
|
|
243
|
+
default:
|
|
244
|
+
throw new Error(`Unknown uuid function: ${name}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
async _validBlobPrefixUuid(blob, opts) {
|
|
248
|
+
const prefix = opts?.pathPrefix ?? "";
|
|
249
|
+
const suffix = this._validBlobPrefixUuidFunction(opts?.actionIfInvalid ?? "prefixUuid4");
|
|
250
|
+
const newPath = `${prefix}${suffix}`;
|
|
251
|
+
return this._newBlob(blob, newPath);
|
|
252
|
+
}
|
|
253
|
+
async _validBlobRemovePath(blob, _opts) {
|
|
254
|
+
return this._newBlob(blob, undefined);
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Based on the blob and options, return a blob that has a valid path
|
|
258
|
+
* that can be saved.
|
|
259
|
+
* @param blob
|
|
260
|
+
* @param opts
|
|
261
|
+
*/
|
|
262
|
+
async _validStoreBlob(blob, opts) {
|
|
263
|
+
if (await this.hasValidPath(blob.path, opts)) {
|
|
264
|
+
return blob;
|
|
265
|
+
}
|
|
266
|
+
switch (opts?.actionIfInvalid) {
|
|
267
|
+
case "ignore":
|
|
268
|
+
return blob;
|
|
269
|
+
case "prefixPath":
|
|
270
|
+
return this._validBlobPrefixPath(blob, opts);
|
|
271
|
+
case "prefixUuid1":
|
|
272
|
+
case "prefixUuid4":
|
|
273
|
+
case "prefixUuid6":
|
|
274
|
+
case "prefixUuid7":
|
|
275
|
+
return this._validBlobPrefixUuid(blob, opts);
|
|
276
|
+
case "removePath":
|
|
277
|
+
return this._validBlobRemovePath(blob, opts);
|
|
278
|
+
default:
|
|
279
|
+
return undefined;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
async store(blob, opts = {}) {
|
|
283
|
+
const allOpts = {
|
|
284
|
+
...this.defaultStoreOptions,
|
|
285
|
+
...opts,
|
|
286
|
+
};
|
|
287
|
+
const validBlob = await this._validStoreBlob(blob, allOpts);
|
|
288
|
+
if (typeof validBlob !== "undefined") {
|
|
289
|
+
const validKey = await validBlob.asUri();
|
|
290
|
+
await this.mset([[validKey, validBlob]]);
|
|
291
|
+
const savedKey = await validBlob.asUri();
|
|
292
|
+
return await this.fetch(savedKey);
|
|
293
|
+
}
|
|
294
|
+
return undefined;
|
|
295
|
+
}
|
|
296
|
+
async _missingFetchBlobEmpty(path, _opts) {
|
|
297
|
+
return new MediaBlob({ path });
|
|
298
|
+
}
|
|
299
|
+
async _missingFetchBlob(path, opts) {
|
|
300
|
+
switch (opts?.actionIfBlobMissing) {
|
|
301
|
+
case "emptyBlob":
|
|
302
|
+
return this._missingFetchBlobEmpty(path, opts);
|
|
303
|
+
default:
|
|
304
|
+
return undefined;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
async fetch(key, opts = {}) {
|
|
308
|
+
const allOpts = {
|
|
309
|
+
...this.defaultFetchOptions,
|
|
310
|
+
...opts,
|
|
311
|
+
};
|
|
312
|
+
const realKey = await this._realKey(key);
|
|
313
|
+
const ret = await this.mget([realKey]);
|
|
314
|
+
return ret?.[0] ?? (await this._missingFetchBlob(realKey, allOpts));
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
export class BackedBlobStore extends BlobStore {
|
|
318
|
+
constructor(opts) {
|
|
319
|
+
super(opts);
|
|
320
|
+
Object.defineProperty(this, "backingStore", {
|
|
321
|
+
enumerable: true,
|
|
322
|
+
configurable: true,
|
|
323
|
+
writable: true,
|
|
324
|
+
value: void 0
|
|
325
|
+
});
|
|
326
|
+
this.backingStore = opts.backingStore;
|
|
327
|
+
}
|
|
328
|
+
mdelete(keys) {
|
|
329
|
+
return this.backingStore.mdelete(keys);
|
|
330
|
+
}
|
|
331
|
+
mget(keys) {
|
|
332
|
+
return this.backingStore.mget(keys);
|
|
333
|
+
}
|
|
334
|
+
mset(keyValuePairs) {
|
|
335
|
+
return this.backingStore.mset(keyValuePairs);
|
|
336
|
+
}
|
|
337
|
+
yieldKeys(prefix) {
|
|
338
|
+
return this.backingStore.yieldKeys(prefix);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
export class ReadThroughBlobStore extends BlobStore {
|
|
342
|
+
constructor(opts) {
|
|
343
|
+
super(opts);
|
|
344
|
+
Object.defineProperty(this, "baseStore", {
|
|
345
|
+
enumerable: true,
|
|
346
|
+
configurable: true,
|
|
347
|
+
writable: true,
|
|
348
|
+
value: void 0
|
|
349
|
+
});
|
|
350
|
+
Object.defineProperty(this, "backingStore", {
|
|
351
|
+
enumerable: true,
|
|
352
|
+
configurable: true,
|
|
353
|
+
writable: true,
|
|
354
|
+
value: void 0
|
|
355
|
+
});
|
|
356
|
+
this.baseStore = opts.baseStore;
|
|
357
|
+
this.backingStore = opts.backingStore;
|
|
358
|
+
}
|
|
359
|
+
async store(blob, opts = {}) {
|
|
360
|
+
const originalUri = await blob.asUri();
|
|
361
|
+
const newBlob = await this.backingStore.store(blob, opts);
|
|
362
|
+
if (newBlob) {
|
|
363
|
+
await this.baseStore.mset([[originalUri, newBlob]]);
|
|
364
|
+
}
|
|
365
|
+
return newBlob;
|
|
366
|
+
}
|
|
367
|
+
mdelete(keys) {
|
|
368
|
+
return this.baseStore.mdelete(keys);
|
|
369
|
+
}
|
|
370
|
+
mget(keys) {
|
|
371
|
+
return this.baseStore.mget(keys);
|
|
372
|
+
}
|
|
373
|
+
mset(_keyValuePairs) {
|
|
374
|
+
throw new Error("Do not call ReadThroughBlobStore.mset directly");
|
|
375
|
+
}
|
|
376
|
+
yieldKeys(prefix) {
|
|
377
|
+
return this.baseStore.yieldKeys(prefix);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
export class SimpleWebBlobStore extends BlobStore {
|
|
381
|
+
_notImplementedException() {
|
|
382
|
+
throw new Error("Not implemented for SimpleWebBlobStore");
|
|
383
|
+
}
|
|
384
|
+
async hasValidPath(path, _opts) {
|
|
385
|
+
return ((await super.hasValidPath(path, { pathPrefix: "https://" })) ||
|
|
386
|
+
(await super.hasValidPath(path, { pathPrefix: "http://" })));
|
|
387
|
+
}
|
|
388
|
+
async _fetch(url) {
|
|
389
|
+
const ret = new MediaBlob({
|
|
390
|
+
path: url,
|
|
391
|
+
});
|
|
392
|
+
const metadata = {};
|
|
393
|
+
const fetchOptions = {
|
|
394
|
+
method: "GET",
|
|
395
|
+
};
|
|
396
|
+
const res = await fetch(url, fetchOptions);
|
|
397
|
+
metadata.status = res.status;
|
|
398
|
+
const headers = {};
|
|
399
|
+
for (const [key, value] of res.headers.entries()) {
|
|
400
|
+
headers[key] = value;
|
|
401
|
+
}
|
|
402
|
+
metadata.headers = headers;
|
|
403
|
+
metadata.ok = res.ok;
|
|
404
|
+
if (res.ok) {
|
|
405
|
+
const resMediaBlob = await MediaBlob.fromBlob(await res.blob());
|
|
406
|
+
ret.data = resMediaBlob.data;
|
|
407
|
+
}
|
|
408
|
+
ret.metadata = metadata;
|
|
409
|
+
return ret;
|
|
410
|
+
}
|
|
411
|
+
async mget(keys) {
|
|
412
|
+
const blobMap = keys.map(this._fetch);
|
|
413
|
+
return await Promise.all(blobMap);
|
|
414
|
+
}
|
|
415
|
+
async mdelete(_keys) {
|
|
416
|
+
this._notImplementedException();
|
|
417
|
+
}
|
|
418
|
+
async mset(_keyValuePairs) {
|
|
419
|
+
this._notImplementedException();
|
|
420
|
+
}
|
|
421
|
+
async *yieldKeys(_prefix) {
|
|
422
|
+
this._notImplementedException();
|
|
423
|
+
yield "";
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* A blob "store" that works with data: URLs that will turn the URL into
|
|
428
|
+
* a blob.
|
|
429
|
+
*/
|
|
430
|
+
export class DataBlobStore extends BlobStore {
|
|
431
|
+
_notImplementedException() {
|
|
432
|
+
throw new Error("Not implemented for DataBlobStore");
|
|
433
|
+
}
|
|
434
|
+
hasValidPath(path, _opts) {
|
|
435
|
+
return super.hasValidPath(path, { pathPrefix: "data:" });
|
|
436
|
+
}
|
|
437
|
+
_fetch(url) {
|
|
438
|
+
return MediaBlob.fromDataUrl(url);
|
|
439
|
+
}
|
|
440
|
+
async mget(keys) {
|
|
441
|
+
const blobMap = keys.map(this._fetch);
|
|
442
|
+
return blobMap;
|
|
443
|
+
}
|
|
444
|
+
async mdelete(_keys) {
|
|
445
|
+
this._notImplementedException();
|
|
446
|
+
}
|
|
447
|
+
async mset(_keyValuePairs) {
|
|
448
|
+
this._notImplementedException();
|
|
449
|
+
}
|
|
450
|
+
async *yieldKeys(_prefix) {
|
|
451
|
+
this._notImplementedException();
|
|
452
|
+
yield "";
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Responsible for converting a URI (typically a web URL) into a MediaBlob.
|
|
457
|
+
* Allows for aliasing / caching of the requested URI and what it resolves to.
|
|
458
|
+
* This MediaBlob is expected to be usable to provide to an LLM, either
|
|
459
|
+
* through the Base64 of the media or through a canonical URI that the LLM
|
|
460
|
+
* supports.
|
|
461
|
+
*/
|
|
462
|
+
export class MediaManager {
|
|
463
|
+
constructor(config) {
|
|
464
|
+
Object.defineProperty(this, "store", {
|
|
465
|
+
enumerable: true,
|
|
466
|
+
configurable: true,
|
|
467
|
+
writable: true,
|
|
468
|
+
value: void 0
|
|
469
|
+
});
|
|
470
|
+
Object.defineProperty(this, "resolvers", {
|
|
471
|
+
enumerable: true,
|
|
472
|
+
configurable: true,
|
|
473
|
+
writable: true,
|
|
474
|
+
value: void 0
|
|
475
|
+
});
|
|
476
|
+
this.store = config.store;
|
|
477
|
+
this.resolvers = config.resolvers;
|
|
478
|
+
}
|
|
479
|
+
defaultResolvers() {
|
|
480
|
+
return [new DataBlobStore({}), new SimpleWebBlobStore({})];
|
|
481
|
+
}
|
|
482
|
+
async _isInvalid(blob) {
|
|
483
|
+
return typeof blob === "undefined";
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Given the public URI, load what is at this URI and save it
|
|
487
|
+
* in the store.
|
|
488
|
+
* @param uri The URI to resolve using the resolver
|
|
489
|
+
* @return A canonical MediaBlob for this URI
|
|
490
|
+
*/
|
|
491
|
+
async _resolveAndSave(uri) {
|
|
492
|
+
let resolvedBlob;
|
|
493
|
+
const resolvers = this.resolvers || this.defaultResolvers();
|
|
494
|
+
for (let co = 0; co < resolvers.length; co += 1) {
|
|
495
|
+
const resolver = resolvers[co];
|
|
496
|
+
if (await resolver.hasValidPath(uri)) {
|
|
497
|
+
resolvedBlob = await resolver.fetch(uri);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
if (resolvedBlob) {
|
|
501
|
+
return await this.store.store(resolvedBlob);
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
504
|
+
return new MediaBlob({});
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
async getMediaBlob(uri) {
|
|
508
|
+
const aliasBlob = await this.store.fetch(uri);
|
|
509
|
+
const ret = (await this._isInvalid(aliasBlob))
|
|
510
|
+
? await this._resolveAndSave(uri)
|
|
511
|
+
: aliasBlob;
|
|
512
|
+
return ret;
|
|
513
|
+
}
|
|
514
|
+
}
|
package/dist/llms.cjs
CHANGED
|
@@ -12,8 +12,8 @@ const auth_js_1 = require("./auth.cjs");
|
|
|
12
12
|
const failed_handler_js_1 = require("./utils/failed_handler.cjs");
|
|
13
13
|
const chat_models_js_1 = require("./chat_models.cjs");
|
|
14
14
|
class GoogleLLMConnection extends connection_js_1.AbstractGoogleLLMConnection {
|
|
15
|
-
formatContents(input, _parameters) {
|
|
16
|
-
const parts =
|
|
15
|
+
async formatContents(input, _parameters) {
|
|
16
|
+
const parts = await this.api.messageContentToParts(input);
|
|
17
17
|
const contents = [
|
|
18
18
|
{
|
|
19
19
|
role: "user",
|
|
@@ -39,6 +39,11 @@ class GoogleBaseLLM extends llms_1.LLM {
|
|
|
39
39
|
static lc_name() {
|
|
40
40
|
return "GoogleLLM";
|
|
41
41
|
}
|
|
42
|
+
get lc_secrets() {
|
|
43
|
+
return {
|
|
44
|
+
authOptions: "GOOGLE_AUTH_OPTIONS",
|
|
45
|
+
};
|
|
46
|
+
}
|
|
42
47
|
constructor(fields) {
|
|
43
48
|
super((0, failed_handler_js_1.ensureParams)(fields));
|
|
44
49
|
Object.defineProperty(this, "originalFields", {
|
|
@@ -170,7 +175,7 @@ class GoogleBaseLLM extends llms_1.LLM {
|
|
|
170
175
|
async _call(prompt, options) {
|
|
171
176
|
const parameters = (0, common_js_1.copyAIModelParams)(this, options);
|
|
172
177
|
const result = await this.connection.request(prompt, parameters, options);
|
|
173
|
-
const ret =
|
|
178
|
+
const ret = this.connection.api.safeResponseToString(result, this.safetyHandler);
|
|
174
179
|
return ret;
|
|
175
180
|
}
|
|
176
181
|
// Normally, you should not override this method and instead should override
|
|
@@ -193,7 +198,7 @@ class GoogleBaseLLM extends llms_1.LLM {
|
|
|
193
198
|
const proxyChat = this.createProxyChat();
|
|
194
199
|
try {
|
|
195
200
|
for await (const chunk of proxyChat._streamIterator(input, options)) {
|
|
196
|
-
const stringValue =
|
|
201
|
+
const stringValue = this.connection.api.chunkToString(chunk);
|
|
197
202
|
const generationChunk = new outputs_1.GenerationChunk({
|
|
198
203
|
text: stringValue,
|
|
199
204
|
});
|
|
@@ -212,7 +217,7 @@ class GoogleBaseLLM extends llms_1.LLM {
|
|
|
212
217
|
async predictMessages(messages, options, _callbacks) {
|
|
213
218
|
const { content } = messages[0];
|
|
214
219
|
const result = await this.connection.request(content, {}, options);
|
|
215
|
-
const ret =
|
|
220
|
+
const ret = this.connection.api.safeResponseToBaseMessage(result, this.safetyHandler);
|
|
216
221
|
return ret;
|
|
217
222
|
}
|
|
218
223
|
/**
|
package/dist/llms.d.ts
CHANGED
|
@@ -9,13 +9,16 @@ import { ChatGoogleBase } from "./chat_models.js";
|
|
|
9
9
|
import type { GoogleBaseLLMInput, GoogleAISafetyHandler } from "./types.js";
|
|
10
10
|
export { GoogleBaseLLMInput };
|
|
11
11
|
declare class GoogleLLMConnection<AuthOptions> extends AbstractGoogleLLMConnection<MessageContent, AuthOptions> {
|
|
12
|
-
formatContents(input: MessageContent, _parameters: GoogleAIModelParams): GeminiContent[]
|
|
12
|
+
formatContents(input: MessageContent, _parameters: GoogleAIModelParams): Promise<GeminiContent[]>;
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
15
|
* Integration with an LLM.
|
|
16
16
|
*/
|
|
17
17
|
export declare abstract class GoogleBaseLLM<AuthOptions> extends LLM<BaseLanguageModelCallOptions> implements GoogleBaseLLMInput<AuthOptions> {
|
|
18
18
|
static lc_name(): string;
|
|
19
|
+
get lc_secrets(): {
|
|
20
|
+
[key: string]: string;
|
|
21
|
+
} | undefined;
|
|
19
22
|
originalFields?: GoogleBaseLLMInput<AuthOptions>;
|
|
20
23
|
lc_serializable: boolean;
|
|
21
24
|
modelName: string;
|
package/dist/llms.js
CHANGED
|
@@ -4,13 +4,13 @@ import { GenerationChunk } from "@langchain/core/outputs";
|
|
|
4
4
|
import { getEnvironmentVariable } from "@langchain/core/utils/env";
|
|
5
5
|
import { AbstractGoogleLLMConnection } from "./connection.js";
|
|
6
6
|
import { copyAIModelParams, copyAndValidateModelParamsInto, } from "./utils/common.js";
|
|
7
|
-
import {
|
|
7
|
+
import { DefaultGeminiSafetyHandler } from "./utils/gemini.js";
|
|
8
8
|
import { ApiKeyGoogleAuth } from "./auth.js";
|
|
9
9
|
import { ensureParams } from "./utils/failed_handler.js";
|
|
10
10
|
import { ChatGoogleBase } from "./chat_models.js";
|
|
11
11
|
class GoogleLLMConnection extends AbstractGoogleLLMConnection {
|
|
12
|
-
formatContents(input, _parameters) {
|
|
13
|
-
const parts = messageContentToParts(input);
|
|
12
|
+
async formatContents(input, _parameters) {
|
|
13
|
+
const parts = await this.api.messageContentToParts(input);
|
|
14
14
|
const contents = [
|
|
15
15
|
{
|
|
16
16
|
role: "user",
|
|
@@ -36,6 +36,11 @@ export class GoogleBaseLLM extends LLM {
|
|
|
36
36
|
static lc_name() {
|
|
37
37
|
return "GoogleLLM";
|
|
38
38
|
}
|
|
39
|
+
get lc_secrets() {
|
|
40
|
+
return {
|
|
41
|
+
authOptions: "GOOGLE_AUTH_OPTIONS",
|
|
42
|
+
};
|
|
43
|
+
}
|
|
39
44
|
constructor(fields) {
|
|
40
45
|
super(ensureParams(fields));
|
|
41
46
|
Object.defineProperty(this, "originalFields", {
|
|
@@ -167,7 +172,7 @@ export class GoogleBaseLLM extends LLM {
|
|
|
167
172
|
async _call(prompt, options) {
|
|
168
173
|
const parameters = copyAIModelParams(this, options);
|
|
169
174
|
const result = await this.connection.request(prompt, parameters, options);
|
|
170
|
-
const ret = safeResponseToString(result, this.safetyHandler);
|
|
175
|
+
const ret = this.connection.api.safeResponseToString(result, this.safetyHandler);
|
|
171
176
|
return ret;
|
|
172
177
|
}
|
|
173
178
|
// Normally, you should not override this method and instead should override
|
|
@@ -190,7 +195,7 @@ export class GoogleBaseLLM extends LLM {
|
|
|
190
195
|
const proxyChat = this.createProxyChat();
|
|
191
196
|
try {
|
|
192
197
|
for await (const chunk of proxyChat._streamIterator(input, options)) {
|
|
193
|
-
const stringValue = chunkToString(chunk);
|
|
198
|
+
const stringValue = this.connection.api.chunkToString(chunk);
|
|
194
199
|
const generationChunk = new GenerationChunk({
|
|
195
200
|
text: stringValue,
|
|
196
201
|
});
|
|
@@ -209,7 +214,7 @@ export class GoogleBaseLLM extends LLM {
|
|
|
209
214
|
async predictMessages(messages, options, _callbacks) {
|
|
210
215
|
const { content } = messages[0];
|
|
211
216
|
const result = await this.connection.request(content, {}, options);
|
|
212
|
-
const ret = safeResponseToBaseMessage(result, this.safetyHandler);
|
|
217
|
+
const ret = this.connection.api.safeResponseToBaseMessage(result, this.safetyHandler);
|
|
213
218
|
return ret;
|
|
214
219
|
}
|
|
215
220
|
/**
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { BaseLLMParams } from "@langchain/core/language_models/llms";
|
|
2
2
|
import type { BaseChatModelCallOptions, BindToolsInput } from "@langchain/core/language_models/chat_models";
|
|
3
3
|
import type { JsonStream } from "./utils/stream.js";
|
|
4
|
+
import { MediaManager } from "./experimental/utils/media_core.js";
|
|
4
5
|
/**
|
|
5
6
|
* Parameters needed to setup the client connection.
|
|
6
7
|
* AuthOptions are something like GoogleAuthOptions (from google-auth-library)
|
|
@@ -116,7 +117,7 @@ export interface GoogleAIModelRequestParams extends GoogleAIModelParams {
|
|
|
116
117
|
*/
|
|
117
118
|
allowed_function_names?: string[];
|
|
118
119
|
}
|
|
119
|
-
export interface GoogleAIBaseLLMInput<AuthOptions> extends BaseLLMParams, GoogleConnectionParams<AuthOptions>, GoogleAIModelParams, GoogleAISafetyParams {
|
|
120
|
+
export interface GoogleAIBaseLLMInput<AuthOptions> extends BaseLLMParams, GoogleConnectionParams<AuthOptions>, GoogleAIModelParams, GoogleAISafetyParams, GeminiAPIConfig {
|
|
120
121
|
}
|
|
121
122
|
export interface GoogleAIBaseLanguageModelCallOptions extends BaseChatModelCallOptions, GoogleAIModelRequestParams, GoogleAISafetyParams {
|
|
122
123
|
/**
|
|
@@ -134,6 +135,9 @@ export interface GoogleBaseLLMInput<AuthOptions> extends GoogleAIBaseLLMInput<Au
|
|
|
134
135
|
export interface GoogleResponse {
|
|
135
136
|
data: any;
|
|
136
137
|
}
|
|
138
|
+
export interface GoogleRawResponse extends GoogleResponse {
|
|
139
|
+
data: Blob;
|
|
140
|
+
}
|
|
137
141
|
export interface GeminiPartText {
|
|
138
142
|
text: string;
|
|
139
143
|
}
|
|
@@ -261,4 +265,7 @@ export interface GeminiJsonSchemaDirty extends GeminiJsonSchema {
|
|
|
261
265
|
properties?: Record<string, GeminiJsonSchemaDirty>;
|
|
262
266
|
additionalProperties?: boolean;
|
|
263
267
|
}
|
|
268
|
+
export interface GeminiAPIConfig {
|
|
269
|
+
mediaManager?: MediaManager;
|
|
270
|
+
}
|
|
264
271
|
export {};
|