modelmix 2.6.2 → 2.6.6

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.
Files changed (3) hide show
  1. package/README.md +7 -10
  2. package/index.js +47 -54
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -210,11 +210,8 @@ ModelMix now uses Bottleneck for efficient rate limiting of API requests. This i
210
210
  const mmix = new ModelMix({
211
211
  config: {
212
212
  bottleneck: {
213
- maxConcurrent: 5, // Maximum number of concurrent requests
214
- minTime: 200, // Minimum time between requests (in ms)
215
- reservoir: 60, // Number of requests allowed in the reservoir period
216
- reservoirRefreshAmount: 60, // How many requests are added when the reservoir refreshes
217
- reservoirRefreshInterval: 60 * 1000 // Reservoir refresh interval (60 seconds)
213
+ maxConcurrent: 8, // Maximum number of concurrent requests
214
+ minTime: 500 // Minimum time between requests (in ms)
218
215
  }
219
216
  }
220
217
  });
@@ -242,11 +239,11 @@ new ModelMix(args = { options: {}, config: {} })
242
239
  - `system`: Sets the default system message for the model, e.g., "You are an assistant."
243
240
  - `max_history`: Limits the number of historical messages to retain, e.g., 5.
244
241
  - `bottleneck`: Configures the rate limiting behavior using Bottleneck. For example:
245
- - `maxConcurrent`: 5 Maximum number of concurrent requests
246
- - `minTime`: 200 Minimum time between requests (in ms)
247
- - `reservoir`: 60 Number of requests allowed in the reservoir period
248
- - `reservoirRefreshAmount`: 60 How many requests are added when the reservoir refreshes
249
- - `reservoirRefreshInterval`: 60 * 1000 // Reservoir refresh interval (60 seconds)
242
+ - `maxConcurrent`: Maximum number of concurrent requests
243
+ - `minTime`: Minimum time between requests (in ms)
244
+ - `reservoir`: Number of requests allowed in the reservoir period
245
+ - `reservoirRefreshAmount`: How many requests are added when the reservoir refreshes
246
+ - `reservoirRefreshInterval`: Reservoir refresh interval
250
247
  - ...(Additional configuration parameters can be added as needed)
251
248
 
252
249
  **Methods**
package/index.js CHANGED
@@ -3,6 +3,7 @@ const fs = require('fs');
3
3
  const mime = require('mime-types');
4
4
  const log = require('lemonlog')('ModelMix');
5
5
  const Bottleneck = require('bottleneck');
6
+ const path = require('path');
6
7
 
7
8
  class ModelMix {
8
9
  constructor(args = { options: {}, config: {} }) {
@@ -16,12 +17,9 @@ class ModelMix {
16
17
 
17
18
  // Standard Bottleneck configuration
18
19
  const defaultBottleneckConfig = {
19
- maxConcurrent: 5, // Maximum number of concurrent requests
20
- minTime: 200, // Minimum time between requests (in ms)
21
- reservoir: 60, // Number of requests allowed in the reservoir period
22
- reservoirRefreshAmount: 60, // How many requests are added when the reservoir refreshes
23
- reservoirRefreshInterval: 60 * 1000 // Reservoir refresh interval (60 seconds)
24
- };
20
+ maxConcurrent: 8, // Maximum number of concurrent requests
21
+ minTime: 500, // Minimum time between requests (in ms)
22
+ };
25
23
 
26
24
  this.config = {
27
25
  system: 'You are an assistant.',
@@ -76,14 +74,25 @@ class ModelMix {
76
74
  }
77
75
 
78
76
  setSystemFromFile(filePath) {
77
+ const content = this.readFile(filePath);
78
+ this.setSystem(content);
79
+ return this;
80
+ }
81
+
82
+ readFile(filePath, options = { encoding: 'utf8' }) {
79
83
  try {
80
- const content = fs.readFileSync(filePath, { encoding: 'utf8' });
81
- this.setSystem(content);
84
+ const absolutePath = path.resolve(process.cwd(), filePath);
85
+ return fs.readFileSync(absolutePath, options);
82
86
  } catch (error) {
83
- console.error(`Error reading system message file ${filePath}:`, error);
87
+ if (error.code === 'ENOENT') {
88
+ throw new Error(`File not found: ${filePath}`);
89
+ } else if (error.code === 'EACCES') {
90
+ throw new Error(`Permission denied: ${filePath}`);
91
+ } else {
92
+ throw new Error(`Error reading file ${filePath}: ${error.message}`);
93
+ }
84
94
  }
85
- return this;
86
- }
95
+ }
87
96
  }
88
97
 
89
98
  class MessageHandler {
@@ -113,12 +122,8 @@ class MessageHandler {
113
122
  }
114
123
 
115
124
  addTextFromFile(filePath, config = { role: "user" }) {
116
- try {
117
- const content = fs.readFileSync(filePath, { encoding: 'utf8' });
118
- this.addText(content, config);
119
- } catch (error) {
120
- console.error(`Error reading file ${filePath}:`, error);
121
- }
125
+ const content = this.mix.readFile(filePath);
126
+ this.addText(content, config);
122
127
  return this;
123
128
  }
124
129
 
@@ -128,44 +133,36 @@ class MessageHandler {
128
133
  }
129
134
 
130
135
  setSystemFromFile(filePath) {
131
- try {
132
- const content = fs.readFileSync(filePath, { encoding: 'utf8' });
133
- this.setSystem(content);
134
- } catch (error) {
135
- console.error(`Error reading system message file ${filePath}:`, error);
136
- }
136
+ const content = this.mix.readFile(filePath);
137
+ this.setSystem(content);
137
138
  return this;
138
139
  }
139
140
 
140
141
  addImage(filePath, config = { role: "user" }) {
141
- try {
142
- const imageBuffer = fs.readFileSync(filePath);
143
- const mimeType = mime.lookup(filePath);
142
+ const imageBuffer = this.mix.readFile(filePath, { encoding: null });
143
+ const mimeType = mime.lookup(filePath);
144
144
 
145
- if (!mimeType || !mimeType.startsWith('image/')) {
146
- throw new Error('Invalid image file type');
147
- }
145
+ if (!mimeType || !mimeType.startsWith('image/')) {
146
+ throw new Error('Invalid image file type');
147
+ }
148
148
 
149
- const data = imageBuffer.toString('base64');
150
-
151
- const imageMessage = {
152
- ...config,
153
- content: [
154
- {
155
- type: "image",
156
- "source": {
157
- type: "base64",
158
- media_type: mimeType,
159
- data
160
- }
149
+ const data = imageBuffer.toString('base64');
150
+
151
+ const imageMessage = {
152
+ ...config,
153
+ content: [
154
+ {
155
+ type: "image",
156
+ "source": {
157
+ type: "base64",
158
+ media_type: mimeType,
159
+ data
161
160
  }
162
- ]
163
- };
161
+ }
162
+ ]
163
+ };
164
164
 
165
- this.messages.push(imageMessage);
166
- } catch (error) {
167
- console.error('Error reading the image file:', error);
168
- }
165
+ this.messages.push(imageMessage);
169
166
 
170
167
  return this;
171
168
  }
@@ -233,17 +230,13 @@ class MessageHandler {
233
230
  }
234
231
 
235
232
  replaceKeyFromFile(key, filePath) {
236
- try {
237
- const content = fs.readFileSync(filePath, { encoding: 'utf8' });
238
- this.replace({ [key]: this.template(content, this.config.replace) });
239
- } catch (error) {
240
- console.error(`Error reading file ${filePath}:`, error);
241
- }
233
+ const content = this.mix.readFile(filePath);
234
+ this.replace({ [key]: this.template(content, this.config.replace) });
242
235
  return this;
243
236
  }
244
237
 
245
238
  template(input, replace) {
246
- return input.split(/([¿?¡!,"';:\.\s])/).map(x => x in replace ? replace[x] : x).join("");
239
+ return input.split(/([¿?¡!,"';:\(\)\.\s])/).map(x => x in replace ? replace[x] : x).join("");
247
240
  }
248
241
 
249
242
  groupByRoles(messages) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "modelmix",
3
- "version": "2.6.2",
3
+ "version": "2.6.6",
4
4
  "description": "🧬 ModelMix - Unified API for Diverse AI LLM.",
5
5
  "main": "index.js",
6
6
  "repository": {