llmjs2 1.1.1 → 1.3.0
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/CONFIG_README.md +98 -0
- package/README.md +382 -357
- package/cli.js +195 -0
- package/config.yaml +149 -0
- package/docs/BASIC_USAGE.md +296 -0
- package/docs/CLI.md +455 -0
- package/docs/GET_STARTED.md +129 -0
- package/docs/GUARDRAILS_GUIDE.md +734 -0
- package/docs/README.md +47 -0
- package/docs/ROUTER_GUIDE.md +397 -0
- package/docs/SERVER_MODE.md +350 -0
- package/index.js +199 -246
- package/package.json +43 -34
- package/providers/ollama.js +120 -88
- package/providers/openai.js +104 -0
- package/providers/openrouter.js +113 -79
- package/router.js +248 -0
- package/server.js +186 -0
- package/test.js +246 -0
- package/validate-config.js +87 -0
- package/LICENSE +0 -21
package/README.md
CHANGED
|
@@ -1,357 +1,382 @@
|
|
|
1
|
-
# llmjs2
|
|
2
|
-
|
|
3
|
-
A
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
- **
|
|
8
|
-
- **
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
{ role: 'user', content: 'What is
|
|
207
|
-
]
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
##
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
```javascript
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
1
|
+
# llmjs2
|
|
2
|
+
|
|
3
|
+
A unified, enterprise-grade Node.js library for connecting to multiple Large Language Model (LLM) providers: OpenAI, Ollama, and OpenRouter.
|
|
4
|
+
|
|
5
|
+
**Features:**
|
|
6
|
+
- **Unified API**: Single interface for OpenAI, Ollama, and OpenRouter
|
|
7
|
+
- **Intelligent Router**: Load balancing and multiple routing strategies
|
|
8
|
+
- **Guardrails System**: Content filtering, logging, rate limiting, and custom processing
|
|
9
|
+
- **OpenAI-Compatible Server**: Drop-in replacement for OpenAI API clients
|
|
10
|
+
- **CLI Interface**: Command-line server management with configuration files
|
|
11
|
+
- **Enterprise Security**: Input validation, error sanitization, and safe defaults
|
|
12
|
+
- **Zero External Dependencies**: Pure Node.js implementation
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
|
|
16
|
+
- **Unified API**: Single interface for OpenAI, Ollama, and OpenRouter
|
|
17
|
+
- **Auto-detection**: Automatically chooses available providers based on API keys
|
|
18
|
+
- **Enterprise-grade**: Robust error handling, input validation, and security measures
|
|
19
|
+
- **Zero dependencies**: Uses only Node.js built-in modules
|
|
20
|
+
- **TypeScript-free**: Pure JavaScript, no compilation required
|
|
21
|
+
- **Production-ready**: Comprehensive testing and security auditing
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install llmjs2
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Or for global CLI usage:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install -g llmjs2
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Quick Test
|
|
36
|
+
|
|
37
|
+
Try the sample configuration:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Validate configuration
|
|
41
|
+
node validate-config.js
|
|
42
|
+
|
|
43
|
+
# Start server with sample config
|
|
44
|
+
node cli.js --config config.yaml --port 3001
|
|
45
|
+
|
|
46
|
+
# Test the API
|
|
47
|
+
curl -X POST http://localhost:3001/v1/chat/completions \
|
|
48
|
+
-H "Content-Type: application/json" \
|
|
49
|
+
-d '{"messages":[{"role":"user","content":"Hello!"}]}'
|
|
50
|
+
|
|
51
|
+
# Response format:
|
|
52
|
+
# {
|
|
53
|
+
# "id": "chatcmpl-123456",
|
|
54
|
+
# "object": "chat.completion",
|
|
55
|
+
# "created": 1640995200,
|
|
56
|
+
# "model": "ollama/minimax-m2.5:cloud",
|
|
57
|
+
# "messages": [
|
|
58
|
+
# {"role": "user", "content": "Hello!"},
|
|
59
|
+
# {"role": "assistant", "content": "Hi there!"}
|
|
60
|
+
# ]
|
|
61
|
+
# }
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
See `CONFIG_README.md` for detailed configuration examples.
|
|
65
|
+
|
|
66
|
+
## Quick Start
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
import { completion } from 'llmjs2';
|
|
70
|
+
|
|
71
|
+
// Set API keys
|
|
72
|
+
process.env.OPENAI_API_KEY = 'your-openai-key';
|
|
73
|
+
process.env.OLLAMA_API_KEY = 'your-ollama-key';
|
|
74
|
+
process.env.OPEN_ROUTER_API_KEY = 'your-openrouter-key';
|
|
75
|
+
|
|
76
|
+
// Simple completion
|
|
77
|
+
const response = await completion('Hello, how are you?');
|
|
78
|
+
console.log(response);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## API Keys Setup
|
|
82
|
+
|
|
83
|
+
Set your API keys as environment variables:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
export OPENAI_API_KEY=your_openai_api_key
|
|
87
|
+
export OLLAMA_API_KEY=your_ollama_api_key
|
|
88
|
+
export OPEN_ROUTER_API_KEY=your_openrouter_api_key
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Usage Patterns
|
|
92
|
+
|
|
93
|
+
### 1. Simple API (Auto-detection)
|
|
94
|
+
|
|
95
|
+
```javascript
|
|
96
|
+
import { completion } from 'llmjs2';
|
|
97
|
+
|
|
98
|
+
const response = await completion('Explain quantum physics simply');
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 2. Provider-Specific Model
|
|
102
|
+
|
|
103
|
+
```javascript
|
|
104
|
+
// OpenAI
|
|
105
|
+
const openaiResponse = await completion('openai/gpt-4', 'Write a haiku about coding');
|
|
106
|
+
|
|
107
|
+
// Ollama
|
|
108
|
+
const ollamaResponse = await completion('ollama/minimax-m2.5:cloud', 'What is AI?');
|
|
109
|
+
|
|
110
|
+
// OpenRouter
|
|
111
|
+
const openrouterResponse = await completion('openrouter/openrouter/free', 'Tell me a joke');
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### 3. Advanced Object API
|
|
115
|
+
|
|
116
|
+
```javascript
|
|
117
|
+
const response = await completion({
|
|
118
|
+
model: 'openai/gpt-3.5-turbo',
|
|
119
|
+
messages: [
|
|
120
|
+
{ role: 'system', content: 'You are a helpful assistant.' },
|
|
121
|
+
{ role: 'user', content: 'What is the capital of France?' }
|
|
122
|
+
],
|
|
123
|
+
temperature: 0.7,
|
|
124
|
+
maxTokens: 100
|
|
125
|
+
});
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Configuration
|
|
129
|
+
|
|
130
|
+
### Default Models
|
|
131
|
+
|
|
132
|
+
Set default models for each provider:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
export OPENAI_DEFAULT_MODEL=gpt-4
|
|
136
|
+
export OLLAMA_DEFAULT_MODEL=minimax-m2.5:cloud
|
|
137
|
+
export OPEN_ROUTER_DEFAULT_MODEL=openrouter/free
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Base URLs
|
|
141
|
+
|
|
142
|
+
Customize API endpoints:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
export OPENAI_BASE_URL=https://api.openai.com/v1
|
|
146
|
+
export OLLAMA_BASE_URL=https://ollama.com/api/chat
|
|
147
|
+
export OPEN_ROUTER_BASE_URL=https://openrouter.ai/api/v1/chat/completions
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Error Handling
|
|
151
|
+
|
|
152
|
+
```javascript
|
|
153
|
+
import { completion } from 'llmjs2';
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
const response = await completion('Tell me a joke');
|
|
157
|
+
console.log(response);
|
|
158
|
+
} catch (error) {
|
|
159
|
+
console.error('Error:', error.message);
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Conversations
|
|
164
|
+
|
|
165
|
+
```javascript
|
|
166
|
+
import { completion } from 'llmjs2';
|
|
167
|
+
|
|
168
|
+
const messages = [
|
|
169
|
+
{ role: 'system', content: 'You are a helpful coding assistant.' },
|
|
170
|
+
{ role: 'user', content: 'How do I reverse a string in JavaScript?' }
|
|
171
|
+
];
|
|
172
|
+
|
|
173
|
+
let response = await completion({ model: 'openai/gpt-4', messages });
|
|
174
|
+
console.log('Assistant:', response);
|
|
175
|
+
|
|
176
|
+
// Continue conversation
|
|
177
|
+
messages.push({ role: 'assistant', content: response });
|
|
178
|
+
messages.push({ role: 'user', content: 'Can you show me with an example?' });
|
|
179
|
+
|
|
180
|
+
response = await completion({ model: 'openai/gpt-4', messages });
|
|
181
|
+
console.log('Assistant:', response);
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Function Calling (Tools)
|
|
185
|
+
|
|
186
|
+
```javascript
|
|
187
|
+
import { completion } from 'llmjs2';
|
|
188
|
+
|
|
189
|
+
const weatherTool = {
|
|
190
|
+
type: 'function',
|
|
191
|
+
function: {
|
|
192
|
+
name: 'get_weather',
|
|
193
|
+
description: 'Get current weather for a location',
|
|
194
|
+
parameters: {
|
|
195
|
+
type: 'object',
|
|
196
|
+
properties: {
|
|
197
|
+
location: { type: 'string', description: 'City name' }
|
|
198
|
+
},
|
|
199
|
+
required: ['location']
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const response = await completion({
|
|
205
|
+
model: 'openai/gpt-4',
|
|
206
|
+
messages: [{ role: 'user', content: 'What is the weather in Paris?' }],
|
|
207
|
+
tools: [weatherTool]
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
if (response.tool_calls) {
|
|
211
|
+
console.log('Tool calls:', response.tool_calls);
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Router System
|
|
216
|
+
|
|
217
|
+
Intelligent model routing with load balancing and multiple strategies:
|
|
218
|
+
|
|
219
|
+
```javascript
|
|
220
|
+
import { router } from 'llmjs2';
|
|
221
|
+
|
|
222
|
+
const modelList = [
|
|
223
|
+
{
|
|
224
|
+
model_name: 'gpt-3.5-turbo',
|
|
225
|
+
llm_params: {
|
|
226
|
+
model: 'ollama/chatgpt-v-2',
|
|
227
|
+
api_key: process.env.OLLAMA_API_KEY
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
model_name: 'gpt-3.5-turbo',
|
|
232
|
+
llm_params: {
|
|
233
|
+
model: 'openai/gpt-3.5-turbo',
|
|
234
|
+
api_key: process.env.OPENAI_API_KEY
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
];
|
|
238
|
+
|
|
239
|
+
// Load balancing across models with same name
|
|
240
|
+
const route = router(modelList, 'random');
|
|
241
|
+
const response = await route.completion({
|
|
242
|
+
model: 'gpt-3.5-turbo',
|
|
243
|
+
messages: [{ role: 'user', content: 'Hello!' }]
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
// Auto-routing with different strategies
|
|
247
|
+
const randomRouter = router(modelList, 'random');
|
|
248
|
+
const sequentialRouter = router(modelList, 'sequential');
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**Routing Strategies:**
|
|
252
|
+
- `default`: Load balance across models with same name
|
|
253
|
+
- `random`: Randomly select from all models
|
|
254
|
+
- `sequential`: Cycle through models in order
|
|
255
|
+
|
|
256
|
+
## Guardrails System
|
|
257
|
+
|
|
258
|
+
Add custom logic before and after LLM calls for content filtering, logging, and processing:
|
|
259
|
+
|
|
260
|
+
```javascript
|
|
261
|
+
import { router } from 'llmjs2';
|
|
262
|
+
|
|
263
|
+
const route = router(modelList);
|
|
264
|
+
|
|
265
|
+
route.setGuardrails([
|
|
266
|
+
{
|
|
267
|
+
name: 'content_filter',
|
|
268
|
+
mode: 'pre_call',
|
|
269
|
+
code: (processId, input) => {
|
|
270
|
+
// Filter inappropriate content
|
|
271
|
+
const filteredMessages = input.messages.map(msg => ({
|
|
272
|
+
...msg,
|
|
273
|
+
content: msg.content.replace(/badword/gi, '****')
|
|
274
|
+
}));
|
|
275
|
+
return { ...input, messages: filteredMessages };
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
name: 'response_logger',
|
|
280
|
+
mode: 'post_call',
|
|
281
|
+
code: (processId, result) => {
|
|
282
|
+
console.log(`[${processId}] Response:`, result);
|
|
283
|
+
return result;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
]);
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Server Mode
|
|
290
|
+
|
|
291
|
+
Run an API server that returns responses with metadata and message arrays:
|
|
292
|
+
|
|
293
|
+
```javascript
|
|
294
|
+
import { router, app } from 'llmjs2';
|
|
295
|
+
|
|
296
|
+
const route = router(modelList);
|
|
297
|
+
app.use(route);
|
|
298
|
+
app.listen(3000);
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Or use the CLI:
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
llmjs2 --config config.yaml --port 3000
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## CLI Interface
|
|
308
|
+
|
|
309
|
+
Manage servers from the command line:
|
|
310
|
+
|
|
311
|
+
```bash
|
|
312
|
+
# Start server with defaults
|
|
313
|
+
llmjs2
|
|
314
|
+
|
|
315
|
+
# Use configuration file
|
|
316
|
+
llmjs2 --config config.yaml
|
|
317
|
+
|
|
318
|
+
# Custom port and host
|
|
319
|
+
llmjs2 --port 8080 --host 0.0.0.0
|
|
320
|
+
|
|
321
|
+
# Get help
|
|
322
|
+
llmjs2 --help
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
## Configuration Files
|
|
326
|
+
|
|
327
|
+
Use YAML for advanced configuration:
|
|
328
|
+
|
|
329
|
+
```yaml
|
|
330
|
+
model_list:
|
|
331
|
+
- model_name: premium
|
|
332
|
+
llm_params:
|
|
333
|
+
model: openrouter/openai/gpt-4
|
|
334
|
+
api_key: os.environ/OPEN_ROUTER_API_KEY
|
|
335
|
+
|
|
336
|
+
- model_name: standard
|
|
337
|
+
llm_params:
|
|
338
|
+
model: ollama/minimax-m2.5:cloud
|
|
339
|
+
api_key: os.environ/OLLAMA_API_KEY
|
|
340
|
+
|
|
341
|
+
guardrails:
|
|
342
|
+
- name: content_filter
|
|
343
|
+
mode: pre_call
|
|
344
|
+
code: |
|
|
345
|
+
(processId, input) => {
|
|
346
|
+
// Content filtering logic
|
|
347
|
+
return input;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
router_settings:
|
|
351
|
+
routing_strategy: random
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
**Note**: Model names in the configuration use the format `[provider]/[actual-model-name]` (e.g., `openai/gpt-4`, `ollama/minimax-m2.5:cloud`). The `[provider]/` prefix is used for routing and is automatically stripped when sending requests to LLM providers.
|
|
355
|
+
|
|
356
|
+
## Security Features
|
|
357
|
+
|
|
358
|
+
- **No API key logging**: Sensitive information is never logged
|
|
359
|
+
- **Input validation**: All inputs are validated and sanitized
|
|
360
|
+
- **Error sanitization**: Error messages don't leak sensitive data
|
|
361
|
+
- **Timeout protection**: Requests timeout to prevent hanging
|
|
362
|
+
- **HTTPS only**: All communications use HTTPS
|
|
363
|
+
|
|
364
|
+
## Testing
|
|
365
|
+
|
|
366
|
+
Run the test suite:
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
npm test
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
## License
|
|
373
|
+
|
|
374
|
+
MIT
|
|
375
|
+
|
|
376
|
+
## Contributing
|
|
377
|
+
|
|
378
|
+
Contributions welcome! Please ensure all tests pass and add tests for new features.
|
|
379
|
+
|
|
380
|
+
## Support
|
|
381
|
+
|
|
382
|
+
For issues and questions, please create an issue on GitHub.
|