utilitas 1998.2.18 → 1998.2.19

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/lib/alan.mjs CHANGED
@@ -1,37 +1,42 @@
1
+ import { fileTypeFromBuffer } from 'file-type';
2
+ import { end, loop } from './event.mjs';
3
+ import { createWavHeader } from './media.mjs';
1
4
  import { BASE64, BUFFER, DATAURL, MIME_BINARY, STREAM, convert } from './storage.mjs';
2
5
  import { create as createUoid } from './uoid.mjs';
3
- import { createWavHeader } from './media.mjs';
4
- import { end, loop } from './event.mjs';
5
- import { fileTypeFromBuffer } from 'file-type';
6
6
 
7
7
  import {
8
+ log as _log,
9
+ renderText as _renderText,
8
10
  base64Encode, ensureArray, ensureString, extract, ignoreErrFunc,
9
- log as _log, need, parseJson, renderText as _renderText, throwError,
11
+ need, parseJson,
12
+ throwError,
10
13
  } from './utilitas.mjs';
11
14
 
12
15
  const _NEED = [
13
- '@anthropic-ai/sdk', '@google/generative-ai', 'js-tiktoken', 'ollama',
14
- 'OpenAI',
16
+ '@anthropic-ai/sdk', '@anthropic-ai/vertex-sdk', '@google/generative-ai',
17
+ 'js-tiktoken', 'ollama', 'OpenAI',
15
18
  ];
16
19
 
17
20
  const [
18
21
  OPENAI, GEMINI, CHATGPT, OPENAI_EMBEDDING, GEMINI_EMEDDING, OPENAI_TRAINING,
19
22
  OLLAMA, CLAUDE, GPT_4O_MINI, GPT_4O, GPT_O1, GPT_O3_MINI, GEMINI_20_FLASH,
20
23
  GEMINI_20_FLASH_THINKING, GEMINI_20_PRO, NOVA, EMBEDDING_001, DEEPSEEK_R1,
21
- DEEPSEEK_R1_32B, MD_CODE, CHATGPT_REASONING, TEXT_EMBEDDING_3_SMALL,
22
- TEXT_EMBEDDING_3_LARGE, CLAUDE_35_SONNET, CLAUDE_35_HAIKU, AUDIO, WAV,
23
- CHATGPT_MINI, ATTACHMENTS, CHAT, OPENAI_VOICE, MEDIUM, LOW, HIGH,
24
- GPT_REASONING_EFFORT, THINK, THINK_STR, THINK_END,
24
+ DEEPSEEK_R1_32B, DEEPSEEK_R1_70B, MD_CODE, CHATGPT_REASONING,
25
+ TEXT_EMBEDDING_3_SMALL, TEXT_EMBEDDING_3_LARGE, CLAUDE_35_SONNET,
26
+ CLAUDE_35_HAIKU, CLOUD_37_SONNET, AUDIO, WAV, CHATGPT_MINI, ATTACHMENTS,
27
+ CHAT, OPENAI_VOICE, MEDIUM, LOW, HIGH, GPT_REASONING_EFFORT, THINK,
28
+ THINK_STR, THINK_END, AZURE,
25
29
  ] = [
26
30
  'OPENAI', 'GEMINI', 'CHATGPT', 'OPENAI_EMBEDDING', 'GEMINI_EMEDDING',
27
31
  'OPENAI_TRAINING', 'OLLAMA', 'CLAUDE', 'gpt-4o-mini', 'gpt-4o', 'o1',
28
32
  'o3-mini', 'gemini-2.0-flash', 'gemini-2.0-flash-thinking-exp',
29
33
  'gemini-2.0-pro-exp', 'nova', 'embedding-001', 'deepseek-r1',
30
- 'deepseek-r1:32b', '```', 'CHATGPT_REASONING', 'text-embedding-3-small',
31
- 'text-embedding-3-large', 'claude-3-5-sonnet-latest',
32
- 'claude-3-5-haiku-latest', 'audio', 'wav', 'CHATGPT_MINI',
34
+ 'deepseek-r1:32b', 'deepseek-r1:70b', '```', 'CHATGPT_REASONING',
35
+ 'text-embedding-3-small', 'text-embedding-3-large',
36
+ 'claude-3-5-sonnet-latest', 'claude-3-5-haiku-latest',
37
+ 'claude-3-7-sonnet@20250219', 'audio', 'wav', 'CHATGPT_MINI',
33
38
  '[ATTACHMENTS]', 'CHAT', 'OPENAI_VOICE', 'medium', 'low', 'high',
34
- 'medium', 'think', '<think>', '</think>',
39
+ 'medium', 'think', '<think>', '</think>', 'AZURE',
35
40
  ];
36
41
 
37
42
  const [
@@ -81,10 +86,11 @@ const DEFAULT_MODELS = {
81
86
  [CHATGPT_MINI]: GPT_4O_MINI,
82
87
  [CHATGPT_REASONING]: GPT_O3_MINI,
83
88
  [CHATGPT]: GPT_4O,
84
- [CLAUDE]: CLAUDE_35_SONNET,
89
+ [CLAUDE]: CLOUD_37_SONNET,
85
90
  [GEMINI_EMEDDING]: EMBEDDING_001,
86
91
  [GEMINI]: GEMINI_20_FLASH,
87
92
  [OLLAMA]: DEEPSEEK_R1,
93
+ [AZURE]: DEEPSEEK_R1,
88
94
  [OPENAI_EMBEDDING]: TEXT_EMBEDDING_3_SMALL,
89
95
  [OPENAI_TRAINING]: GPT_4O_MINI, // https://platform.openai.com/docs/guides/fine-tuning
90
96
  [OPENAI_VOICE]: NOVA,
@@ -252,7 +258,7 @@ const MODELS = {
252
258
  ],
253
259
  },
254
260
  [DEEPSEEK_R1]: {
255
- contextWindow: 128000,
261
+ contextWindow: 128 * 1000,
256
262
  maxOutputTokens: 32768,
257
263
  requestLimitsRPM: Infinity,
258
264
  tokenLimitsTPM: Infinity,
@@ -298,10 +304,29 @@ const MODELS = {
298
304
  png, jpeg, gif, webp, pdf,
299
305
  ],
300
306
  },
307
+ // https://console.cloud.google.com/vertex-ai/publishers/anthropic/model-garden/claude-3-7-sonnet?authuser=5&inv=1&invt=Abqftg&project=backend-alpha-97077
308
+ [CLOUD_37_SONNET]: {
309
+ contextWindow: 200 * 1000,
310
+ maxOutputTokens: 64 * 1000, // Should be 128 * 1000, but Anthropic SDK limits it to 64 * 1000
311
+ imageCostTokens: size8k / 750,
312
+ documentCostTokens: 3000 * 100, // 100 pages: https://docs.anthropic.com/en/docs/build-with-claude/pdf-support
313
+ maxImagePerPrompt: 5, // https://docs.anthropic.com/en/docs/build-with-claude/vision
314
+ maxImageSize: 1092, // by pixels
315
+ maxDocumentPages: 100,
316
+ maxDocumentFile: 1024 * 1024 * 32, // 32MB
317
+ requestLimitsRPM: 50,
318
+ tokenLimitsITPM: 40000,
319
+ tokenLimitsOTPM: 8000,
320
+ trainingData: 'Apr 2024', // ?
321
+ supportedMimeTypes: [
322
+ png, jpeg, gif, webp, pdf,
323
+ ],
324
+ },
301
325
  };
302
326
 
303
327
  MODELS[CLAUDE_35_HAIKU] = MODELS[CLAUDE_35_SONNET];
304
328
  MODELS[DEEPSEEK_R1_32B] = MODELS[DEEPSEEK_R1];
329
+ MODELS[DEEPSEEK_R1_70B] = MODELS[DEEPSEEK_R1];
305
330
 
306
331
  for (const n in MODELS) {
307
332
  MODELS[n]['name'] = n;
@@ -340,10 +365,14 @@ const unifyType = (type, name) => {
340
365
  const init = async (options) => {
341
366
  const provider = unifyProvider(options);
342
367
  switch (provider) {
343
- case OPENAI:
368
+ case OPENAI: case AZURE:
344
369
  if (options?.apiKey) {
345
- const OpenAI = await need('openai');
346
- const openai = new OpenAI(options);
370
+ provider === AZURE && assert(
371
+ options?.baseURL, 'Azure api endpoint is required.'
372
+ );
373
+ const libOpenAI = await need('openai', { raw: true });
374
+ const openai = new (options?.endpoint && options?.deployment
375
+ ? libOpenAI.AzureOpenAI : libOpenAI.OpenAI)(options);
347
376
  clients[provider] = { client: openai, clientBeta: openai.beta };
348
377
  }
349
378
  break;
@@ -373,9 +402,20 @@ const init = async (options) => {
373
402
  }
374
403
  break;
375
404
  case CLAUDE:
376
- if (options?.apiKey) {
377
- const Anthropic = await need('@anthropic-ai/sdk');
378
- const anthropic = new Anthropic({ apiKey: options?.apiKey });
405
+ if (options?.apiKey || (options?.credentials && options?.projectId)) {
406
+ // https://github.com/anthropics/anthropic-sdk-typescript/tree/main/packages/vertex-sdk
407
+ const Anthropic = (await need(options?.credentials
408
+ ? '@anthropic-ai/vertex-sdk' : '@anthropic-ai/sdk', { raw: true }))[
409
+ options?.credentials ? 'AnthropicVertex' : 'Anthropic'
410
+ ];
411
+ if (options?.credentials) {
412
+ process.env['GOOGLE_APPLICATION_CREDENTIALS'] = options.credentials;
413
+ process.env['ANTHROPIC_VERTEX_PROJECT_ID'] = options.projectId;
414
+ }
415
+ const anthropic = new Anthropic({
416
+ ...options?.apiKey ? { apiKey: options.apiKey } : {},
417
+ ...options?.credentials ? { region: options?.region || 'us-east5' } : {},
418
+ });
379
419
  clients[provider] = { client: anthropic };
380
420
  }
381
421
  break;
@@ -611,7 +651,9 @@ const promptChatGPT = async (content, options = {}) => {
611
651
  // Structured Outputs: https://openai.com/index/introducing-structured-outputs-in-the-api/
612
652
  client.baseURL !== OPENAI_BASE_URL
613
653
  && options?.attachments?.length && (options.attachments = []);
614
- if (options?.model) { } else if (options?.reasoning) {
654
+ if (options?.model) { } else if (options?.provider === AZURE) {
655
+ options.model = DEFAULT_MODELS[AZURE];
656
+ } else if (options?.reasoning) {
615
657
  options.model = DEFAULT_MODELS[CHATGPT_REASONING];
616
658
  } else {
617
659
  options.model = DEFAULT_MODELS[CHATGPT];
@@ -671,6 +713,10 @@ const promptChatGPT = async (content, options = {}) => {
671
713
  return await packGptResp(chunk, options);
672
714
  };
673
715
 
716
+ const promptAzure = async (content, options = {}) => await promptChatGPT(
717
+ content, { ...options, provider: AZURE }
718
+ );
719
+
674
720
  const promptOllama = async (content, options = {}) => {
675
721
  const { client, model } = await getOllamaClient(options);
676
722
  // https://github.com/ollama/ollama-js
@@ -939,7 +985,6 @@ const initChat = async (options) => {
939
985
  assert(model, `Invalid chat model: '${i}'.`);
940
986
  chatConfig.engines[key] = options.engines[i];
941
987
  chatConfig.engines[key].model = chatConfig.engines[key].model || model;
942
- print(chatConfig.engines[key].model);
943
988
  const mxPmpt = MODELS[chatConfig.engines[key].model].maxInputTokens / 2;
944
989
  const pmptTokens = await countTokens([buildGeminiHistory(
945
990
  chatConfig.systemPrompt, { role: system }
@@ -1006,7 +1051,7 @@ const talk = async (input, options) => {
1006
1051
  const session = await getSession(sessionId, { engine, ...options });
1007
1052
  let [resp, sys, messages, msgBuilder] = [null, [], [], null];
1008
1053
  switch (engine) {
1009
- case CHATGPT:
1054
+ case CHATGPT: case AZURE:
1010
1055
  sys.push(buildGptMessage(session.systemPrompt, { role: system }));
1011
1056
  msgBuilder = () => {
1012
1057
  messages = [];
@@ -1088,6 +1133,9 @@ const talk = async (input, options) => {
1088
1133
  case OLLAMA:
1089
1134
  resp = await promptOllama(input, { messages, model, ...options });
1090
1135
  break;
1136
+ case AZURE:
1137
+ resp = await promptAzure(input, { messages, model, ...options });
1138
+ break;
1091
1139
  }
1092
1140
  chat.response = resp.text;
1093
1141
  chat?.request && chat?.response && session.messages.push(chat);
@@ -1208,39 +1256,27 @@ const analyzeSessions = async (sessionIds, options) => {
1208
1256
  };
1209
1257
 
1210
1258
  const PREFERRED_ENGINES = [
1211
- { client: OPENAI, func: promptChatGPT, multimodal: 1 },
1212
- { client: GEMINI, func: promptGemini, multimodal: 0 },
1259
+ { client: OPENAI, func: promptChatGPT, multimodal: 0 },
1260
+ { client: GEMINI, func: promptGemini, multimodal: 1 },
1213
1261
  { client: CLAUDE, func: promptClaude, multimodal: 2 },
1262
+ { client: AZURE, func: promptAzure, multimodal: 3 },
1214
1263
  { client: OLLAMA, func: promptOllama, multimodal: 99 },
1215
1264
  ]; // keep gpt first to avoid gemini grounding by default
1216
1265
 
1217
1266
  export default init;
1218
1267
  export {
1219
- _NEED,
1220
- ATTACHMENT_TOKEN_COST,
1221
- CODE_INTERPRETER,
1222
- DEFAULT_MODELS,
1268
+ ATTACHMENT_TOKEN_COST, CLOUD_37_SONNET, CODE_INTERPRETER, DEEPSEEK_R1,
1269
+ DEEPSEEK_R1_32B, DEEPSEEK_R1_70B, DEFAULT_MODELS,
1223
1270
  EMBEDDING_001,
1224
- FUNCTION,
1225
- GEMINI_20_FLASH_THINKING,
1226
- GEMINI_20_FLASH,
1227
- GPT_4O_MINI,
1228
- GPT_4O,
1229
- GPT_O3_MINI,
1230
- GPT_O1,
1231
- DEEPSEEK_R1,
1232
- DEEPSEEK_R1_32B,
1233
- MODELS,
1271
+ FUNCTION, GEMINI_20_FLASH, GEMINI_20_FLASH_THINKING, GPT_4O, GPT_4O_MINI, GPT_O1, GPT_O3_MINI, MODELS,
1234
1272
  OPENAI_VOICE,
1235
1273
  RETRIEVAL,
1236
- TEXT_EMBEDDING_3_SMALL,
1237
- analyzeSessions,
1274
+ TEXT_EMBEDDING_3_SMALL, _NEED, analyzeSessions,
1238
1275
  buildGptTrainingCase,
1239
1276
  buildGptTrainingCases,
1240
1277
  cancelGptFineTuningJob,
1241
1278
  countTokens,
1242
- createGeminiEmbedding,
1243
- createGptFineTuningJob,
1279
+ createGeminiEmbedding, createGptFineTuningJob,
1244
1280
  createOpenAIEmbedding,
1245
1281
  deleteFile,
1246
1282
  distillFile,
@@ -1255,8 +1291,7 @@ export {
1255
1291
  listGptFineTuningJobs,
1256
1292
  listOpenAIModels,
1257
1293
  ogg,
1258
- prompt,
1259
- promptChatGPT,
1294
+ prompt, promptAzure, promptChatGPT,
1260
1295
  promptClaude,
1261
1296
  promptGemini,
1262
1297
  promptOllama,
@@ -1266,5 +1301,5 @@ export {
1266
1301
  trimPrompt,
1267
1302
  uploadFile,
1268
1303
  uploadFileForFineTuning,
1269
- wav,
1304
+ wav
1270
1305
  };
package/lib/manifest.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  const manifest = {
2
2
  "name": "utilitas",
3
3
  "description": "Just another common utility for JavaScript.",
4
- "version": "1998.2.18",
4
+ "version": "1998.2.19",
5
5
  "private": false,
6
6
  "homepage": "https://github.com/Leask/utilitas",
7
7
  "main": "index.mjs",
@@ -25,6 +25,7 @@ const manifest = {
25
25
  },
26
26
  "devDependencies": {
27
27
  "@anthropic-ai/sdk": "^0.36.3",
28
+ "@anthropic-ai/vertex-sdk": "^0.7.0",
28
29
  "@ffmpeg-installer/ffmpeg": "^1.1.0",
29
30
  "@ffprobe-installer/ffprobe": "^2.1.2",
30
31
  "@google-cloud/speech": "^6.7.0",
package/lib/storage.mjs CHANGED
@@ -1,16 +1,17 @@
1
1
  import {
2
+ log as _log,
2
3
  base64Decode, base64Encode, ensureString, extract, ignoreErrFunc,
3
- log as _log, mergeAtoB, need, throwError, trim, voidFunc, which,
4
+ mergeAtoB, need, throwError, trim, voidFunc, which,
4
5
  } from './utilitas.mjs';
5
6
 
6
- import { basename, extname, join } from 'path';
7
- import { constants as consts, createReadStream, promises as fs, readSync } from 'fs';
8
- import { defaultAlgorithm, hash } from './encryption.mjs';
9
- import { deflate as __zip, unzip as __unzip } from 'zlib';
10
7
  import { fileTypeFromBuffer } from 'file-type';
8
+ import { constants as consts, createReadStream, promises as fs, readSync } from 'fs';
11
9
  import { homedir, tmpdir } from 'os';
10
+ import { basename, extname, join } from 'path';
12
11
  import { promisify } from 'util';
13
12
  import { v4 as uuidv4 } from 'uuid';
13
+ import { unzip as __unzip, deflate as __zip } from 'zlib';
14
+ import { defaultAlgorithm, hash } from './encryption.mjs';
14
15
 
15
16
  const _NEED = ['file-type', 'mime-types', '@google-cloud/storage'];
16
17
  const errorMessage = 'Invalid file.';
@@ -467,26 +468,15 @@ const deleteOnCloud = async (path, options) => {
467
468
  };
468
469
 
469
470
  export {
470
- _NEED,
471
- BASE64,
472
- BUFFER,
473
- DATAURL,
474
- FILE,
475
- MIME_BINARY,
476
- STREAM,
477
- analyzeFile,
478
- assertPath,
479
- blobToBuffer,
480
- convert,
481
- decodeBase64DataURL,
471
+ _NEED, analyzeFile,
472
+ assertPath, BASE64, blobToBuffer, BUFFER, convert, DATAURL, decodeBase64DataURL,
482
473
  deleteFileOnCloud,
483
474
  deleteOnCloud,
484
475
  downloadFileFromCloud,
485
476
  downloadFromCloud,
486
477
  encodeBase64DataURL,
487
478
  exists,
488
- existsOnCloud,
489
- getConfig,
479
+ existsOnCloud, FILE, getConfig,
490
480
  getConfigFilename,
491
481
  getGcUrlByBucket,
492
482
  getIdByGs,
@@ -497,18 +487,16 @@ export {
497
487
  legalFilename,
498
488
  lsOnCloud,
499
489
  mapFilename,
500
- mergeFile,
501
- readFile,
490
+ mergeFile, MIME_BINARY, readFile,
502
491
  readJson,
503
492
  sanitizeFilename,
504
493
  setConfig,
505
- sliceFile,
506
- touchPath,
494
+ sliceFile, STREAM, touchPath,
507
495
  tryRm,
508
496
  unzip,
509
497
  uploadToCloud,
510
498
  writeFile,
511
499
  writeJson,
512
500
  writeTempFile,
513
- zip,
501
+ zip
514
502
  };
package/lib/vision.mjs CHANGED
@@ -3,14 +3,16 @@ import {
3
3
  } from './storage.mjs';
4
4
 
5
5
  import {
6
- ensureArray, ensureString, ignoreErrFunc, log as _log, need, throwError,
6
+ log as _log,
7
+ ensureArray, ensureString, ignoreErrFunc,
8
+ need, throwError,
7
9
  trim,
8
10
  } from './utilitas.mjs';
9
11
 
10
- import { v4 as uuidv4 } from 'uuid';
11
- import { getApiKeyCredentials } from './encryption.mjs';
12
12
  import fs from 'node:fs';
13
13
  import path from 'node:path';
14
+ import { v4 as uuidv4 } from 'uuid';
15
+ import { getApiKeyCredentials } from './encryption.mjs';
14
16
 
15
17
  const _NEED = [
16
18
  '@google-cloud/vision', 'office-text-extractor', 'pdfjs-dist',
@@ -268,5 +270,5 @@ export {
268
270
  parseOfficeFile,
269
271
  read,
270
272
  readAll,
271
- see,
273
+ see
272
274
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "utilitas",
3
3
  "description": "Just another common utility for JavaScript.",
4
- "version": "1998.2.18",
4
+ "version": "1998.2.19",
5
5
  "private": false,
6
6
  "homepage": "https://github.com/Leask/utilitas",
7
7
  "main": "index.mjs",
@@ -36,6 +36,7 @@
36
36
  },
37
37
  "devDependencies": {
38
38
  "@anthropic-ai/sdk": "^0.36.3",
39
+ "@anthropic-ai/vertex-sdk": "^0.7.0",
39
40
  "@ffmpeg-installer/ffmpeg": "^1.1.0",
40
41
  "@ffprobe-installer/ffprobe": "^2.1.2",
41
42
  "@google-cloud/speech": "^6.7.0",