modelmix 3.5.8 → 3.6.2
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/index.js +64 -54
- package/package.json +2 -2
package/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const axios = require('axios');
|
|
2
2
|
const fs = require('fs');
|
|
3
|
-
const {
|
|
3
|
+
const { fromBuffer } = require('file-type');
|
|
4
4
|
const log = require('lemonlog')('ModelMix');
|
|
5
5
|
const Bottleneck = require('bottleneck');
|
|
6
6
|
const path = require('path');
|
|
@@ -13,6 +13,7 @@ class ModelMix {
|
|
|
13
13
|
constructor({ options = {}, config = {} } = {}) {
|
|
14
14
|
this.models = [];
|
|
15
15
|
this.messages = [];
|
|
16
|
+
this.imagesToProcess = [];
|
|
16
17
|
this.tools = {};
|
|
17
18
|
this.toolClient = {};
|
|
18
19
|
this.mcp = {};
|
|
@@ -203,80 +204,89 @@ class ModelMix {
|
|
|
203
204
|
}
|
|
204
205
|
|
|
205
206
|
addImageFromBuffer(buffer, { role = "user" } = {}) {
|
|
206
|
-
|
|
207
|
-
const fileType = fileTypeFromBuffer(buffer);
|
|
208
|
-
if (!fileType || !fileType.mime.startsWith('image/')) {
|
|
209
|
-
throw new Error('Invalid image buffer - unable to detect valid image format');
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
const data = buffer.toString('base64');
|
|
213
|
-
|
|
214
|
-
const imageMessage = {
|
|
215
|
-
...{ role },
|
|
216
|
-
content: [
|
|
217
|
-
{
|
|
218
|
-
type: "image",
|
|
219
|
-
"source": {
|
|
220
|
-
type: "base64",
|
|
221
|
-
media_type: fileType.mime,
|
|
222
|
-
data
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
]
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
this.messages.push(imageMessage);
|
|
207
|
+
this.imagesToProcess.push({ type: 'buffer', buffer, config: { role } });
|
|
229
208
|
return this;
|
|
230
209
|
}
|
|
231
210
|
|
|
232
211
|
addImage(filePath, { role = "user" } = {}) {
|
|
233
|
-
|
|
234
|
-
return this
|
|
212
|
+
this.imagesToProcess.push({ type: 'file', filePath, config: { role } });
|
|
213
|
+
return this;
|
|
235
214
|
}
|
|
236
215
|
|
|
237
216
|
addImageFromUrl(url, config = { role: "user" }) {
|
|
238
|
-
|
|
239
|
-
this.imagesToProcess = [];
|
|
240
|
-
}
|
|
241
|
-
this.imagesToProcess.push({ url, config });
|
|
217
|
+
this.imagesToProcess.push({ type: 'url', url, config });
|
|
242
218
|
return this;
|
|
243
219
|
}
|
|
244
220
|
|
|
245
|
-
async
|
|
246
|
-
if (
|
|
221
|
+
async processImages() {
|
|
222
|
+
if (this.imagesToProcess.length === 0) return;
|
|
223
|
+
|
|
224
|
+
const imageProcessors = {
|
|
225
|
+
url: async (image) => {
|
|
226
|
+
const response = await axios.get(image.url, { responseType: 'arraybuffer' });
|
|
227
|
+
return {
|
|
228
|
+
buffer: Buffer.from(response.data),
|
|
229
|
+
mimeType: response.headers['content-type']
|
|
230
|
+
};
|
|
231
|
+
},
|
|
232
|
+
file: (image) => {
|
|
233
|
+
const buffer = this.readFile(image.filePath, { encoding: null });
|
|
234
|
+
return { buffer, source: `file: ${image.filePath}` };
|
|
235
|
+
},
|
|
236
|
+
buffer: (image) => ({
|
|
237
|
+
buffer: image.buffer,
|
|
238
|
+
source: 'buffer'
|
|
239
|
+
})
|
|
240
|
+
};
|
|
247
241
|
|
|
248
242
|
const imageContents = await Promise.all(
|
|
249
243
|
this.imagesToProcess.map(async (image) => {
|
|
250
244
|
try {
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
245
|
+
const processor = imageProcessors[image.type];
|
|
246
|
+
if (!processor) {
|
|
247
|
+
throw new Error(`Unknown image type: ${image.type}`);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const { buffer, mimeType: providedMimeType, source } = await processor(image);
|
|
251
|
+
|
|
252
|
+
// Detect mimeType from buffer if not provided (for file and buffer types)
|
|
253
|
+
let mimeType = providedMimeType;
|
|
254
|
+
if (!mimeType) {
|
|
255
|
+
const fileType = await fromBuffer(buffer);
|
|
256
|
+
if (!fileType || !fileType.mime.startsWith('image/')) {
|
|
257
|
+
throw new Error(`Invalid image ${source || image.type} - unable to detect valid image format`);
|
|
258
|
+
}
|
|
259
|
+
mimeType = fileType.mime;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return {
|
|
263
|
+
base64: buffer.toString('base64'),
|
|
264
|
+
mimeType,
|
|
265
|
+
config: image.config
|
|
266
|
+
};
|
|
267
|
+
|
|
255
268
|
} catch (error) {
|
|
256
|
-
console.error(`Error
|
|
269
|
+
console.error(`Error processing image:`, error);
|
|
257
270
|
return null;
|
|
258
271
|
}
|
|
259
272
|
})
|
|
260
273
|
);
|
|
261
274
|
|
|
262
|
-
imageContents
|
|
263
|
-
|
|
264
|
-
|
|
275
|
+
imageContents
|
|
276
|
+
.filter(Boolean)
|
|
277
|
+
.forEach((image) => {
|
|
278
|
+
this.messages.push({
|
|
265
279
|
...image.config,
|
|
266
|
-
content: [
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
"
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
data: image.base64
|
|
273
|
-
}
|
|
280
|
+
content: [{
|
|
281
|
+
type: "image",
|
|
282
|
+
source: {
|
|
283
|
+
type: "base64",
|
|
284
|
+
media_type: image.mimeType,
|
|
285
|
+
data: image.base64
|
|
274
286
|
}
|
|
275
|
-
]
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
});
|
|
287
|
+
}]
|
|
288
|
+
});
|
|
289
|
+
});
|
|
280
290
|
}
|
|
281
291
|
|
|
282
292
|
async message() {
|
|
@@ -376,7 +386,7 @@ class ModelMix {
|
|
|
376
386
|
}
|
|
377
387
|
|
|
378
388
|
async prepareMessages() {
|
|
379
|
-
await this.
|
|
389
|
+
await this.processImages();
|
|
380
390
|
this.applyTemplate();
|
|
381
391
|
this.messages = this.messages.slice(-this.config.max_history);
|
|
382
392
|
this.messages = this.groupByRoles(this.messages);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "modelmix",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.2",
|
|
4
4
|
"description": "🧬 ModelMix - Unified API for Diverse AI LLM.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"@modelcontextprotocol/sdk": "^1.11.2",
|
|
54
54
|
"axios": "^1.8.4",
|
|
55
55
|
"bottleneck": "^2.19.5",
|
|
56
|
-
"file-type": "^
|
|
56
|
+
"file-type": "^16.5.4",
|
|
57
57
|
"lemonlog": "^1.1.2"
|
|
58
58
|
}
|
|
59
59
|
}
|