utilitas 1995.3.21 → 1995.3.23
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/README.md +4 -1
- package/dist/utilitas.lite.mjs +1 -1
- package/dist/utilitas.lite.mjs.map +1 -1
- package/lib/alan.mjs +15 -11
- package/lib/bot.mjs +49 -57
- package/lib/manifest.mjs +1 -1
- package/package.json +1 -1
package/lib/alan.mjs
CHANGED
|
@@ -53,7 +53,7 @@ const trimTailing = text => text.replace(/[\.\s]*$/, '');
|
|
|
53
53
|
const newSessionId = () => createUoid({ type: sessionType });
|
|
54
54
|
const renderText = (t, o) => _renderText(t, { extraCodeBlock: 0, ...o || {} });
|
|
55
55
|
const log = (cnt, opt) => _log(cnt, import.meta.url, { time: 1, ...opt || {} });
|
|
56
|
-
const buildGeminiParts = (text,
|
|
56
|
+
const buildGeminiParts = (text, atcmts) => [{ text }, ...atcmts || []];
|
|
57
57
|
|
|
58
58
|
const [
|
|
59
59
|
png, jpeg, mov, mpeg, mp4, mpg, avi, wmv, mpegps, flv, gif, webp, pdf, aac,
|
|
@@ -108,6 +108,7 @@ const MODELS = {
|
|
|
108
108
|
},
|
|
109
109
|
[GPT_4O]: {
|
|
110
110
|
contextWindow: 128000,
|
|
111
|
+
imageCostTokens: 1105,
|
|
111
112
|
maxOutputTokens: 4096,
|
|
112
113
|
requestLimitsRPM: 5000,
|
|
113
114
|
tokenLimitsTPD: 40000000,
|
|
@@ -127,7 +128,7 @@ const MODELS = {
|
|
|
127
128
|
// https://ai.google.dev/gemini-api/docs/models/gemini
|
|
128
129
|
// https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/send-multimodal-prompts?hl=en#gemini-send-multimodal-samples-pdf-nodejs
|
|
129
130
|
contextWindow: 1048576,
|
|
130
|
-
|
|
131
|
+
imageCostTokens: 258,
|
|
131
132
|
maxAudioLength: 60 * 60 * 9.5, // 9.5 hours
|
|
132
133
|
maxAudioPerPrompt: 1,
|
|
133
134
|
maxFileSize: 20 * 1024 * 1024, // 20 MB
|
|
@@ -201,6 +202,9 @@ for (const n in MODELS) {
|
|
|
201
202
|
}
|
|
202
203
|
}
|
|
203
204
|
|
|
205
|
+
const MAX_INPUT_TOKENS = MODELS[GPT_35_TURBO].maxInputTokens;
|
|
206
|
+
const ATTACHMENT_TOKEN_COST = MODELS[GPT_4O].imageCostTokens;
|
|
207
|
+
|
|
204
208
|
const unifyType = (type, name) => {
|
|
205
209
|
const TYPE = ensureString(type, { case: 'UP' });
|
|
206
210
|
assert(TYPE, `${name} is required.`);
|
|
@@ -313,23 +317,20 @@ const buildGptMessage = (content, options) => {
|
|
|
313
317
|
|
|
314
318
|
const buildVertexMessage = (text, options) => {
|
|
315
319
|
assert(text, 'Text is required.');
|
|
316
|
-
|
|
317
|
-
const attachment = (options?.attachments || []).map(x => ({
|
|
320
|
+
const attachments = (options?.attachments || []).map(x => ({
|
|
318
321
|
inline_data: { mime_type: x.mime_type, data: x.data }
|
|
319
|
-
}))
|
|
322
|
+
}));
|
|
320
323
|
return String.isString(text) ? {
|
|
321
|
-
role: options?.role || user, parts: buildGeminiParts(text,
|
|
324
|
+
role: options?.role || user, parts: buildGeminiParts(text, attachments),
|
|
322
325
|
} : text;
|
|
323
326
|
};
|
|
324
327
|
|
|
325
328
|
const buildGeminiMessage = (text, options) => {
|
|
326
329
|
assert(text, 'Text is required.');
|
|
327
|
-
|
|
328
|
-
// only 1 attachment is allowed while using inline_data?
|
|
329
|
-
const attachment = (options?.attachments || []).map(x => ({
|
|
330
|
+
const attachments = (options?.attachments || []).map(x => ({
|
|
330
331
|
inlineData: { mimeType: x.mime_type, data: x.data }
|
|
331
332
|
}))?.[0];
|
|
332
|
-
return String.isString(text) ? buildGeminiParts(text,
|
|
333
|
+
return String.isString(text) ? buildGeminiParts(text, attachments) : text;
|
|
333
334
|
};
|
|
334
335
|
|
|
335
336
|
const [getOpenAIClient, getVertexClient, getGeminiClient, getOllamaClient]
|
|
@@ -947,12 +948,13 @@ const getMaxChatPromptLimit = (options) => {
|
|
|
947
948
|
resp = resp ? Math.min(resp, maxInputTokens) : maxInputTokens;
|
|
948
949
|
}
|
|
949
950
|
assert(resp > 0, 'Chat engine has not been initialized.');
|
|
950
|
-
return resp;
|
|
951
|
+
return options?.raw ? resp : Math.min(resp, MAX_INPUT_TOKENS);
|
|
951
952
|
};
|
|
952
953
|
|
|
953
954
|
export default init;
|
|
954
955
|
export {
|
|
955
956
|
_NEED,
|
|
957
|
+
ATTACHMENT_TOKEN_COST,
|
|
956
958
|
CODE_INTERPRETER,
|
|
957
959
|
DEFAULT_MODELS,
|
|
958
960
|
EMBEDDING_001,
|
|
@@ -963,6 +965,8 @@ export {
|
|
|
963
965
|
GEMINI_15_FLASH_VERTEX,
|
|
964
966
|
GEMINI_15_FLASH,
|
|
965
967
|
GPT_35_TURBO,
|
|
968
|
+
GPT_4O,
|
|
969
|
+
MAX_INPUT_TOKENS,
|
|
966
970
|
MISTRAL,
|
|
967
971
|
MODELS,
|
|
968
972
|
RETRIEVAL,
|
package/lib/bot.mjs
CHANGED
|
@@ -612,67 +612,59 @@ const subconscious = [{
|
|
|
612
612
|
},
|
|
613
613
|
}, {
|
|
614
614
|
run: true, priority: -8860, name: 'vision', func: async (ctx, next) => {
|
|
615
|
-
|
|
616
|
-
if (
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
fileId = ctx.m.document.file_id;
|
|
632
|
-
file_name = ctx.m.document.file_name;
|
|
633
|
-
mime_type = ctx.m.document.mime_type;
|
|
634
|
-
type = 'DOCUMENT';
|
|
635
|
-
} else if (ctx.m.document) {
|
|
636
|
-
ocrFunc = async file => (await isTextFile(file)) && file.toString();
|
|
637
|
-
fileId = ctx.m.document.file_id;
|
|
638
|
-
file_name = ctx.m.document.file_name;
|
|
639
|
-
mime_type = ctx.m.document.mime_type;
|
|
640
|
-
type = 'FILE';
|
|
641
|
-
} else if (ctx.m.photo) {
|
|
642
|
-
asPrompt = true;
|
|
643
|
-
ocrFunc = ctx._.vision?.see;
|
|
644
|
-
fileId = ctx.m.photo[ctx.m.photo.length - 1]?.file_id;
|
|
645
|
-
mime_type = 'image';
|
|
646
|
-
type = 'PHOTO';
|
|
615
|
+
const files = [];
|
|
616
|
+
if (ctx.m.document) {
|
|
617
|
+
let file = {
|
|
618
|
+
asPrompt: bot._.supportedMimeTypes.has(ctx.m.document.mime_type),
|
|
619
|
+
file_name: ctx.m.document.file_name, fileId: ctx.m.document.file_id,
|
|
620
|
+
mime_type: ctx.m.document.mime_type, type: 'FILE',
|
|
621
|
+
ocrFunc: async f => (await isTextFile(f)) && f.toString(),
|
|
622
|
+
};
|
|
623
|
+
if ('application/pdf' === ctx.m.document?.mime_type) {
|
|
624
|
+
file = { ...file, ocrFunc: ctx._.vision?.read, type: 'DOCUMENT' };
|
|
625
|
+
} else if (/^image\/.*$/ig.test(ctx.m.document?.mime_type)) {
|
|
626
|
+
file = { ...file, ocrFunc: ctx._.vision?.see, type: 'IMAGE' };
|
|
627
|
+
} else if (/^.*\.(docx|xlsx|pptx)$/.test(ctx.m.document?.file_name)) {
|
|
628
|
+
file = { ...file, ocrFunc: officeParser, type: 'DOCUMENT' };
|
|
629
|
+
}
|
|
630
|
+
files.push(file);
|
|
647
631
|
}
|
|
648
|
-
|
|
632
|
+
ctx.m.photo?.map(p => files.push({
|
|
633
|
+
asPrompt: true, file_name: `${p.file_id}.jpg`, fileId: p.file_id,
|
|
634
|
+
mime_type: 'image/jpeg', type: 'PHOTO', ocrFunc: ctx._.vision?.see,
|
|
635
|
+
}));
|
|
636
|
+
if (files.length) {
|
|
649
637
|
await ctx.ok(EMOJI_LOOK);
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
mime_type: mime_type === 'image' ? 'image/jpeg' : mime_type,
|
|
657
|
-
image_url, data: base64Encode(file, true),
|
|
658
|
-
}, 'PROMPT');
|
|
659
|
-
}
|
|
660
|
-
if (ocrFunc) {
|
|
661
|
-
const content = trim(ensureArray(
|
|
662
|
-
await ignoreErrFunc(async () => await ocrFunc(
|
|
663
|
-
file, BUFFER_ENCODE
|
|
664
|
-
), logOptions)
|
|
665
|
-
).filter(x => x).join('\n'));
|
|
666
|
-
if (content) {
|
|
638
|
+
for (const f of files) {
|
|
639
|
+
if (!f.asPrompt && !f.ocrFunc) { continue; }
|
|
640
|
+
try {
|
|
641
|
+
const image_url = await getFileUrl(f.fileId);
|
|
642
|
+
const file = (await get(image_url, BUFFER_ENCODE)).content;
|
|
643
|
+
if (f.asPrompt) {
|
|
667
644
|
ctx.collect(ctx.m.caption || '');
|
|
668
|
-
ctx.collect(
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
]), 'VISION');
|
|
645
|
+
ctx.collect({
|
|
646
|
+
mime_type: f.mime_type, image_url,
|
|
647
|
+
data: base64Encode(file, true),
|
|
648
|
+
}, 'PROMPT');
|
|
673
649
|
}
|
|
674
|
-
|
|
675
|
-
|
|
650
|
+
if (f.ocrFunc) {
|
|
651
|
+
const content = trim(ensureArray(
|
|
652
|
+
await ignoreErrFunc(async () => await f.ocrFunc(
|
|
653
|
+
file, BUFFER_ENCODE
|
|
654
|
+
), logOptions)
|
|
655
|
+
).filter(x => x).join('\n'));
|
|
656
|
+
if (content) {
|
|
657
|
+
ctx.collect(ctx.m.caption || '');
|
|
658
|
+
ctx.collect(lines([
|
|
659
|
+
'---', `file_name: ${f.file_name}`,
|
|
660
|
+
`mime_type: ${f.mime_type}`, `type: ${f.type}`,
|
|
661
|
+
'---',
|
|
662
|
+
content
|
|
663
|
+
]), 'VISION');
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
} catch (err) { return await ctx.er(err); }
|
|
667
|
+
}
|
|
676
668
|
}
|
|
677
669
|
await next();
|
|
678
670
|
},
|
package/lib/manifest.mjs
CHANGED