llmjs2 1.7.1 → 2.0.1
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 +116 -18
- package/dist/index.d.mts +146 -0
- package/dist/index.d.ts +146 -0
- package/dist/index.js +1242 -0
- package/dist/index.mjs +1211 -0
- package/package.json +32 -58
- package/chain/AGENT_STEP_README.md +0 -102
- package/chain/README.md +0 -257
- package/chain/WORKFLOW_README.md +0 -85
- package/chain/agent-step-example.js +0 -232
- package/chain/docs/AGENT.md +0 -126
- package/chain/docs/GRAPH.md +0 -490
- package/chain/examples.js +0 -314
- package/chain/index.js +0 -31
- package/chain/lib/agent.js +0 -338
- package/chain/lib/flow/agent-step.js +0 -119
- package/chain/lib/flow/edge.js +0 -24
- package/chain/lib/flow/flow.js +0 -76
- package/chain/lib/flow/graph.js +0 -331
- package/chain/lib/flow/index.js +0 -7
- package/chain/lib/flow/step.js +0 -63
- package/chain/lib/memory/in-memory.js +0 -117
- package/chain/lib/memory/index.js +0 -36
- package/chain/lib/memory/lance-memory.js +0 -225
- package/chain/lib/memory/sqlite-memory.js +0 -309
- package/chain/simple-agent-step-example.js +0 -168
- package/chain/workflow-example-usage.js +0 -70
- package/chain/workflow-example.json +0 -59
- package/core/README.md +0 -485
- package/core/cli.js +0 -275
- package/core/config.yaml +0 -149
- package/core/docs/BASIC_USAGE.md +0 -62
- package/core/docs/CLI.md +0 -104
- package/core/docs/GET_STARTED.md +0 -129
- package/core/docs/GUARDRAILS_GUIDE.md +0 -734
- package/core/docs/README.md +0 -47
- package/core/docs/ROUTER_GUIDE.md +0 -199
- package/core/docs/SERVER_MODE.md +0 -358
- package/core/index.js +0 -115
- package/core/logger.js +0 -115
- package/core/providers/ollama.js +0 -128
- package/core/providers/openai.js +0 -112
- package/core/providers/openrouter.js +0 -206
- package/core/router.js +0 -252
- package/core/server.js +0 -203
package/core/docs/README.md
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# llmjs2 Documentation
|
|
2
|
-
|
|
3
|
-
Welcome to the llmjs2 documentation! This folder contains all the documentation for using and understanding the llmjs2 library.
|
|
4
|
-
|
|
5
|
-
## Documentation Overview
|
|
6
|
-
|
|
7
|
-
### 📖 Getting Started
|
|
8
|
-
|
|
9
|
-
- **[GET_STARTED.md](GET_STARTED.md)** - Quick setup guide for new users (5 minutes to first completion)
|
|
10
|
-
|
|
11
|
-
### 🔧 Usage Guides
|
|
12
|
-
|
|
13
|
-
- **[BASIC_USAGE.md](BASIC_USAGE.md)** - Core API patterns, configuration, and common use cases
|
|
14
|
-
- **[ROUTER_GUIDE.md](ROUTER_GUIDE.md)** - Model routing and load balancing
|
|
15
|
-
- **[GUARDRAILS_GUIDE.md](GUARDRAILS_GUIDE.md)** - Content filtering and request processing
|
|
16
|
-
- **[SERVER_MODE.md](SERVER_MODE.md)** - Run llmjs2 as an OpenAI-compatible API server with routing
|
|
17
|
-
- **[CLI.md](CLI.md)** - Command-line interface for server management
|
|
18
|
-
|
|
19
|
-
## Quick Navigation
|
|
20
|
-
|
|
21
|
-
### New to llmjs2?
|
|
22
|
-
|
|
23
|
-
Start with **[GET_STARTED.md](GET_STARTED.md)** to get up and running quickly.
|
|
24
|
-
|
|
25
|
-
### Want to use the API directly?
|
|
26
|
-
|
|
27
|
-
Check out **[BASIC_USAGE.md](BASIC_USAGE.md)** for different API patterns and examples.
|
|
28
|
-
|
|
29
|
-
### Need routing and load balancing?
|
|
30
|
-
|
|
31
|
-
See **[ROUTER_GUIDE.md](ROUTER_GUIDE.md)** for intelligent model routing.
|
|
32
|
-
|
|
33
|
-
### Need content filtering or custom processing?
|
|
34
|
-
|
|
35
|
-
See **[GUARDRAILS_GUIDE.md](GUARDRAILS_GUIDE.md)** for guardrails and request processing.
|
|
36
|
-
|
|
37
|
-
### Need to set up a server?
|
|
38
|
-
|
|
39
|
-
See **[SERVER_MODE.md](SERVER_MODE.md)** for OpenAI-compatible server setup.
|
|
40
|
-
|
|
41
|
-
### Prefer command-line tools?
|
|
42
|
-
|
|
43
|
-
**[CLI.md](CLI.md)** covers the command-line interface and configuration files.
|
|
44
|
-
|
|
45
|
-
## Contributing
|
|
46
|
-
|
|
47
|
-
Documentation improvements are welcome! Please ensure any changes maintain consistency across all documentation files.
|
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
# llmjs2 Router Usage Guide
|
|
2
|
-
|
|
3
|
-
The llmjs2 router provides intelligent model routing and load balancing capabilities, allowing you to distribute requests across multiple model deployments with different strategies.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
The router system enables:
|
|
8
|
-
|
|
9
|
-
- **Load balancing** across models with the same name
|
|
10
|
-
- **Multiple routing strategies** (default, random, sequential)
|
|
11
|
-
- **Provider-agnostic routing** with unified API
|
|
12
|
-
- **Flexible model configuration** for different providers
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
## Quick Start
|
|
16
|
-
|
|
17
|
-
### Basic Setup
|
|
18
|
-
|
|
19
|
-
```javascript
|
|
20
|
-
import { router } from 'llmjs2';
|
|
21
|
-
|
|
22
|
-
// Define your model deployments
|
|
23
|
-
const modelList = [
|
|
24
|
-
{
|
|
25
|
-
"model_name": "gpt-3.5-turbo",
|
|
26
|
-
"llm_params": {
|
|
27
|
-
"model": "ollama/chatgpt-v-2",
|
|
28
|
-
"api_key": process.env.OLLAMA_API_KEY,
|
|
29
|
-
"api_base": process.env.OLLAMA_API_BASE
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
"model_name": "openai-turbo",
|
|
34
|
-
"llm_params": {
|
|
35
|
-
"model": "gpt-3.5-turbo",
|
|
36
|
-
"api_key": process.env.OPENAI_API_KEY
|
|
37
|
-
}
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
"model_name": "gpt-4",
|
|
41
|
-
"llm_params": {
|
|
42
|
-
"model": "ollama/gpt-4",
|
|
43
|
-
"api_key": process.env.OLLAMA_API_KEY,
|
|
44
|
-
"api_base": process.env.OLLAMA_API_BASE
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
];
|
|
48
|
-
|
|
49
|
-
// Create routers with different strategies
|
|
50
|
-
const defaultRouter = router(modelList);
|
|
51
|
-
const randomRouter = router(modelList, 'random');
|
|
52
|
-
const sequentialRouter = router(modelList, 'sequential');
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### Basic Usage
|
|
56
|
-
|
|
57
|
-
```javascript
|
|
58
|
-
// Route to specific model
|
|
59
|
-
const response = await defaultRouter.completion({
|
|
60
|
-
model: "gpt-3.5-turbo",
|
|
61
|
-
messages: [{"role": "user", "content": "Hey, how's it going?"}]
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
// Auto-route with random strategy
|
|
65
|
-
const randomResponse = await randomRouter.completion({
|
|
66
|
-
messages: [{"role": "user", "content": "Hey, how's it going?"}]
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
// Auto-route with sequential strategy
|
|
70
|
-
const seqResponse = await sequentialRouter.completion({
|
|
71
|
-
messages: [{"role": "user", "content": "Hey, how's it going?"}]
|
|
72
|
-
});
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
## Model Configuration
|
|
76
|
-
|
|
77
|
-
### Model List Format
|
|
78
|
-
|
|
79
|
-
Each model in the list is defined with:
|
|
80
|
-
|
|
81
|
-
```javascript
|
|
82
|
-
{
|
|
83
|
-
"model_name": "string", // Alias for routing (can have multiple providers)
|
|
84
|
-
"llm_params": { // Provider-specific parameters
|
|
85
|
-
"model": "string", // Actual model identifier for the provider
|
|
86
|
-
"api_key": "string", // API key (can use environment variables)
|
|
87
|
-
"api_base": "string?", // Custom API base URL (optional)
|
|
88
|
-
// ... other provider-specific params
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
### Supported Providers
|
|
94
|
-
|
|
95
|
-
#### Ollama
|
|
96
|
-
|
|
97
|
-
```javascript
|
|
98
|
-
{
|
|
99
|
-
"model_name": "my-ollama-model",
|
|
100
|
-
"llm_params": {
|
|
101
|
-
"model": "ollama/llama2",
|
|
102
|
-
"api_key": process.env.OLLAMA_API_KEY,
|
|
103
|
-
"api_base": process.env.OLLAMA_API_BASE
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
#### OpenRouter
|
|
109
|
-
|
|
110
|
-
```javascript
|
|
111
|
-
{
|
|
112
|
-
"model_name": "my-openrouter-model",
|
|
113
|
-
"llm_params": {
|
|
114
|
-
"model": "openrouter/free-model",
|
|
115
|
-
"api_key": process.env.OPEN_ROUTER_API_KEY
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
#### OpenAI
|
|
121
|
-
|
|
122
|
-
```javascript
|
|
123
|
-
{
|
|
124
|
-
"model_name": "my-openai-model",
|
|
125
|
-
"llm_params": {
|
|
126
|
-
"model": "openai/gpt-4",
|
|
127
|
-
"api_key": process.env.OPENAI_API_KEY
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
## Routing Strategies
|
|
133
|
-
|
|
134
|
-
### Default Strategy
|
|
135
|
-
|
|
136
|
-
When no strategy is specified, uses sequential selection across all available models for auto-routing (when no specific model is requested).
|
|
137
|
-
|
|
138
|
-
```javascript
|
|
139
|
-
const route = router(modelList); // or router(modelList, 'default')
|
|
140
|
-
|
|
141
|
-
// Auto-route with sequential selection (cycles through all models)
|
|
142
|
-
const response = await route.completion({
|
|
143
|
-
messages: [...]
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
// Routes to one of the models with model_name="gpt-3.5-turbo" (load balancing)
|
|
147
|
-
const response = await route.completion({
|
|
148
|
-
model: "gpt-3.5-turbo",
|
|
149
|
-
messages: [...]
|
|
150
|
-
});
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
### Random Strategy
|
|
154
|
-
|
|
155
|
-
Randomly selects from available models when no specific model is requested.
|
|
156
|
-
|
|
157
|
-
```javascript
|
|
158
|
-
const route = router(modelList, 'random');
|
|
159
|
-
|
|
160
|
-
// Randomly selects from ALL models in the list
|
|
161
|
-
const response = await route.completion({
|
|
162
|
-
messages: [...]
|
|
163
|
-
});
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### Sequential Strategy
|
|
167
|
-
|
|
168
|
-
Cycles through models in order for each request.
|
|
169
|
-
|
|
170
|
-
```javascript
|
|
171
|
-
const route = router(modelList, 'sequential');
|
|
172
|
-
|
|
173
|
-
// Uses first model, then second, then third, etc.
|
|
174
|
-
const response1 = await route.completion({ messages: [...] }); // model 1
|
|
175
|
-
const response2 = await route.completion({ messages: [...] }); // model 2
|
|
176
|
-
const response3 = await route.completion({ messages: [...] }); // model 3
|
|
177
|
-
// ... cycles back to model 1
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
## Error Handling
|
|
181
|
-
|
|
182
|
-
```javascript
|
|
183
|
-
try {
|
|
184
|
-
const response = await route.completion({
|
|
185
|
-
model: "non-existent-model",
|
|
186
|
-
messages: [{"role": "user", "content": "Hello"}]
|
|
187
|
-
});
|
|
188
|
-
} catch (error) {
|
|
189
|
-
if (error.message.includes('Model not found')) {
|
|
190
|
-
console.log('Model not configured in router');
|
|
191
|
-
} else if (error.message.includes('API key')) {
|
|
192
|
-
console.log('Provider API key missing');
|
|
193
|
-
} else {
|
|
194
|
-
console.log('Routing error:', error.message);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
##
|
package/core/docs/SERVER_MODE.md
DELETED
|
@@ -1,358 +0,0 @@
|
|
|
1
|
-
# Server Mode Guide
|
|
2
|
-
|
|
3
|
-
Run llmjs2 as an OpenAI-compatible API server with intelligent routing and load balancing capabilities to integrate with existing OpenAI clients and applications.
|
|
4
|
-
|
|
5
|
-
## Quick Start Server
|
|
6
|
-
|
|
7
|
-
### Method 1: Simple JavaScript Server
|
|
8
|
-
|
|
9
|
-
Create a server file:
|
|
10
|
-
|
|
11
|
-
```javascript
|
|
12
|
-
// server.js
|
|
13
|
-
import { app } from 'llmjs2';
|
|
14
|
-
|
|
15
|
-
// Start the server
|
|
16
|
-
app.listen(3000, () => {
|
|
17
|
-
console.log('🚀 llmjs2 server running on http://localhost:3000');
|
|
18
|
-
});
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
Run it:
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
node server.js
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
#
|
|
28
|
-
|
|
29
|
-
## API Endpoints
|
|
30
|
-
|
|
31
|
-
### Chat Completions
|
|
32
|
-
|
|
33
|
-
**Endpoint:** `POST /v1/chat/completions`
|
|
34
|
-
|
|
35
|
-
**Content-Type:** `application/json`
|
|
36
|
-
|
|
37
|
-
**Request Format:**
|
|
38
|
-
|
|
39
|
-
```json
|
|
40
|
-
{
|
|
41
|
-
"model": "ollama/minimax-m2.5:cloud",
|
|
42
|
-
"messages": [
|
|
43
|
-
{
|
|
44
|
-
"role": "user",
|
|
45
|
-
"content": "Hello! How are you?"
|
|
46
|
-
}
|
|
47
|
-
],
|
|
48
|
-
"tools": [] // optional
|
|
49
|
-
}
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
**Response Format:**
|
|
53
|
-
|
|
54
|
-
The server returns an OpenAI-style chat completion response. A legacy `messages` array is also included for backward compatibility:
|
|
55
|
-
|
|
56
|
-
```json
|
|
57
|
-
{
|
|
58
|
-
"id": "chatcmpl-123456",
|
|
59
|
-
"object": "chat.completion",
|
|
60
|
-
"created": 1640995200,
|
|
61
|
-
"model": "ollama/minimax-m2.5:cloud",
|
|
62
|
-
"choices": [
|
|
63
|
-
{
|
|
64
|
-
"index": 0,
|
|
65
|
-
"message": {
|
|
66
|
-
"role": "assistant",
|
|
67
|
-
"content": "Hello! I'm doing well, thank you for asking!"
|
|
68
|
-
},
|
|
69
|
-
"finish_reason": "stop"
|
|
70
|
-
}
|
|
71
|
-
],
|
|
72
|
-
"messages": [
|
|
73
|
-
{
|
|
74
|
-
"role": "user",
|
|
75
|
-
"content": "Hello! How are you?"
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
"role": "assistant",
|
|
79
|
-
"content": "Hello! I'm doing well, thank you for asking!"
|
|
80
|
-
}
|
|
81
|
-
]
|
|
82
|
-
}
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
## Using with OpenAI Clients
|
|
86
|
-
|
|
87
|
-
### Direct HTTP Requests
|
|
88
|
-
|
|
89
|
-
You can consume the response like a normal OpenAI chat completion:
|
|
90
|
-
|
|
91
|
-
```python
|
|
92
|
-
import requests
|
|
93
|
-
|
|
94
|
-
response = requests.post(
|
|
95
|
-
"http://localhost:3000/v1/chat/completions",
|
|
96
|
-
json={
|
|
97
|
-
"messages": [{"role": "user", "content": "Hello!"}]
|
|
98
|
-
}
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
data = response.json()
|
|
102
|
-
assistant_message = data["choices"][0]["message"]
|
|
103
|
-
print(f"Model used: {data['model']}")
|
|
104
|
-
print(f"Assistant: {assistant_message['content']}")
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### Node.js with fetch
|
|
108
|
-
|
|
109
|
-
```javascript
|
|
110
|
-
const response = await fetch('http://localhost:3000/v1/chat/completions', {
|
|
111
|
-
method: 'POST',
|
|
112
|
-
headers: {
|
|
113
|
-
'Content-Type': 'application/json'
|
|
114
|
-
},
|
|
115
|
-
body: JSON.stringify({
|
|
116
|
-
messages: [{ role: 'user', content: 'Hello!' }]
|
|
117
|
-
})
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
const data = await response.json();
|
|
121
|
-
const assistantMessage = data.choices[0].message;
|
|
122
|
-
console.log(`Model used: ${data.model}`);
|
|
123
|
-
console.log(`Assistant: ${assistantMessage.content}`);
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
### cURL
|
|
127
|
-
|
|
128
|
-
```bash
|
|
129
|
-
curl -X POST http://localhost:3000/v1/chat/completions \
|
|
130
|
-
-H "Content-Type: application/json" \
|
|
131
|
-
-H "Authorization: Bearer your-api-key" \
|
|
132
|
-
-d '{
|
|
133
|
-
"model": "ollama/minimax-m2.5:cloud",
|
|
134
|
-
"messages": [
|
|
135
|
-
{
|
|
136
|
-
"role": "user",
|
|
137
|
-
"content": "Hello! How are you?"
|
|
138
|
-
}
|
|
139
|
-
]
|
|
140
|
-
}'
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
## Router Integration
|
|
144
|
-
|
|
145
|
-
Add intelligent routing and load balancing to your server:
|
|
146
|
-
|
|
147
|
-
### Basic Router Setup
|
|
148
|
-
|
|
149
|
-
```javascript
|
|
150
|
-
import { router, app } from 'llmjs2';
|
|
151
|
-
|
|
152
|
-
const costOptimizedModels = [
|
|
153
|
-
{
|
|
154
|
-
"model_name": "text-davinci-001",
|
|
155
|
-
"llm_params": {
|
|
156
|
-
"model": "ollama/text-davinci-003",
|
|
157
|
-
"api_key": process.env.OLLAMA_API_KEY
|
|
158
|
-
}
|
|
159
|
-
},
|
|
160
|
-
{
|
|
161
|
-
"model_name": "text-davinci-002",
|
|
162
|
-
"llm_params": {
|
|
163
|
-
"model": "openrouter/text-davinci-003",
|
|
164
|
-
"api_key": process.env.OPEN_ROUTER_API_KEY
|
|
165
|
-
}
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
"model_name": "text-davinci-003",
|
|
169
|
-
"llm_params": {
|
|
170
|
-
"model": "openai/gpt-3.5-turbo",
|
|
171
|
-
"api_key": process.env.OPENAI_API_KEY
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
];
|
|
175
|
-
|
|
176
|
-
// Create router with random strategy for load balancing
|
|
177
|
-
const route = router(costOptimizedModels, 'random');
|
|
178
|
-
|
|
179
|
-
// Apply router to server
|
|
180
|
-
app.use(route);
|
|
181
|
-
|
|
182
|
-
// Start the server
|
|
183
|
-
app.listen(3000, () => {
|
|
184
|
-
console.log('🚀 llmjs2 server with routing running on http://localhost:3000');
|
|
185
|
-
});
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
### Router Strategies
|
|
189
|
-
|
|
190
|
-
- **`'random'`**: Randomly selects from available models
|
|
191
|
-
- **`'sequential'`**: Cycles through models in order
|
|
192
|
-
- **`'default'`** or none: Load balances across models with same `model_name`
|
|
193
|
-
|
|
194
|
-
### API Usage with Routing
|
|
195
|
-
|
|
196
|
-
```bash
|
|
197
|
-
# Automatic routing (uses router strategy)
|
|
198
|
-
curl -X POST http://localhost:3000/v1/chat/completions \
|
|
199
|
-
-H "Content-Type: application/json" \
|
|
200
|
-
-d '{
|
|
201
|
-
"messages": [{"role": "user", "content": "Hello!"}]
|
|
202
|
-
}'
|
|
203
|
-
|
|
204
|
-
# Direct model routing (bypasses router)
|
|
205
|
-
curl -X POST http://localhost:3000/v1/chat/completions \
|
|
206
|
-
-H "Content-Type: application/json" \
|
|
207
|
-
-d '{
|
|
208
|
-
"model": "openai/gpt-3.5-turbo",
|
|
209
|
-
"messages": [{"role": "user", "content": "Hello!"}]
|
|
210
|
-
}'
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
### Advanced Routing Examples
|
|
214
|
-
|
|
215
|
-
**Multi-Provider Fallback:**
|
|
216
|
-
|
|
217
|
-
```javascript
|
|
218
|
-
const fallbackModels = [
|
|
219
|
-
{ "model_name": "gpt-4", "llm_params": { "model": "openai/gpt-4", "api_key": process.env.OPENAI_API_KEY } },
|
|
220
|
-
{ "model_name": "gpt-4", "llm_params": { "model": "ollama/gpt-4", "api_key": process.env.OLLAMA_API_KEY } },
|
|
221
|
-
{ "model_name": "gpt-4", "llm_params": { "model": "openrouter/gpt-4", "api_key": process.env.OPEN_ROUTER_API_KEY } }
|
|
222
|
-
];
|
|
223
|
-
|
|
224
|
-
const route = router(fallbackModels, 'random');
|
|
225
|
-
app.use(route);
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
**Cost Optimization:**
|
|
229
|
-
|
|
230
|
-
```javascript
|
|
231
|
-
const costModels = [
|
|
232
|
-
{ "model_name": "completion", "llm_params": { "model": "ollama/llama2", "api_key": process.env.OLLAMA_API_KEY } },
|
|
233
|
-
{ "model_name": "completion", "llm_params": { "model": "openrouter/free", "api_key": process.env.OPEN_ROUTER_API_KEY } },
|
|
234
|
-
{ "model_name": "completion", "llm_params": { "model": "openai/gpt-3.5-turbo", "api_key": process.env.OPENAI_API_KEY } }
|
|
235
|
-
];
|
|
236
|
-
|
|
237
|
-
const route = router(costModels, 'sequential'); // Try cheaper models first
|
|
238
|
-
app.use(route);
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
## Function Calling (Tools) Support
|
|
242
|
-
|
|
243
|
-
The server supports OpenAI-compatible function calling:
|
|
244
|
-
|
|
245
|
-
```bash
|
|
246
|
-
curl -X POST http://localhost:3000/v1/chat/completions \
|
|
247
|
-
-H "Content-Type: application/json" \
|
|
248
|
-
-H "Authorization: Bearer your-api-key" \
|
|
249
|
-
-d '{
|
|
250
|
-
"model": "openrouter/openrouter/free",
|
|
251
|
-
"messages": [
|
|
252
|
-
{
|
|
253
|
-
"role": "user",
|
|
254
|
-
"content": "What is the weather like in Paris?"
|
|
255
|
-
}
|
|
256
|
-
],
|
|
257
|
-
"tools": [
|
|
258
|
-
{
|
|
259
|
-
"type": "function",
|
|
260
|
-
"function": {
|
|
261
|
-
"name": "get_weather",
|
|
262
|
-
"description": "Get the current weather in a given location",
|
|
263
|
-
"parameters": {
|
|
264
|
-
"type": "object",
|
|
265
|
-
"properties": {
|
|
266
|
-
"location": {
|
|
267
|
-
"type": "string",
|
|
268
|
-
"description": "The city and state, e.g. San Francisco, CA"
|
|
269
|
-
}
|
|
270
|
-
},
|
|
271
|
-
"required": ["location"]
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
]
|
|
276
|
-
}'
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
#### Error Handling
|
|
280
|
-
|
|
281
|
-
The server returns proper HTTP status codes and JSON error responses:
|
|
282
|
-
|
|
283
|
-
```json
|
|
284
|
-
{
|
|
285
|
-
"error": {
|
|
286
|
-
"message": "model is required",
|
|
287
|
-
"type": "invalid_request_error"
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
Common status codes:
|
|
293
|
-
|
|
294
|
-
- `400` - Bad Request (missing parameters)
|
|
295
|
-
- `404` - Not Found (invalid endpoint)
|
|
296
|
-
- `500` - Internal Server Error (API failures)
|
|
297
|
-
|
|
298
|
-
### Environment Variables for Production
|
|
299
|
-
|
|
300
|
-
```bash
|
|
301
|
-
# Server configuration
|
|
302
|
-
PORT=3000
|
|
303
|
-
HOST=0.0.0.0
|
|
304
|
-
|
|
305
|
-
# API Keys
|
|
306
|
-
OLLAMA_API_KEY=your_production_key
|
|
307
|
-
OPEN_ROUTER_API_KEY=your_production_key
|
|
308
|
-
|
|
309
|
-
# Default models
|
|
310
|
-
OLLAMA_DEFAULT_MODEL=minimax-m2.5:cloud
|
|
311
|
-
OPEN_ROUTER_DEFAULT_MODEL=openrouter/free
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
## Monitoring and Logging
|
|
315
|
-
|
|
316
|
-
The server includes comprehensive logging:
|
|
317
|
-
|
|
318
|
-
```
|
|
319
|
-
[2024-01-15T10:30:45.123Z] POST /v1/chat/completions
|
|
320
|
-
Headers: {"content-type":"application/json",...}
|
|
321
|
-
Body parsing completed successfully
|
|
322
|
-
Starting completion with model: ollama/minimax-m2.5:cloud
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
### API Request Issues
|
|
326
|
-
|
|
327
|
-
**400 Bad Request:**
|
|
328
|
-
|
|
329
|
-
- Check that `model` and `messages` are provided
|
|
330
|
-
- Ensure messages have `role` and `content` properties
|
|
331
|
-
|
|
332
|
-
**500 Internal Server Error:**
|
|
333
|
-
|
|
334
|
-
- Check API keys are valid
|
|
335
|
-
- Verify internet connection
|
|
336
|
-
- Check provider API status
|
|
337
|
-
|
|
338
|
-
### CORS Issues
|
|
339
|
-
|
|
340
|
-
If you're getting CORS errors in the browser:
|
|
341
|
-
|
|
342
|
-
```javascript
|
|
343
|
-
// The server includes CORS headers by default
|
|
344
|
-
// If you need custom CORS, modify the server code
|
|
345
|
-
res.writeHead(statusCode, {
|
|
346
|
-
'Content-Type': 'application/json',
|
|
347
|
-
'Access-Control-Allow-Origin': '*', // Change this for production
|
|
348
|
-
// ... other headers
|
|
349
|
-
});
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
## Next Steps
|
|
353
|
-
|
|
354
|
-
- **[CLI Guide](CLI.md)** - Use the command-line interface
|
|
355
|
-
- **[Basic Usage](BASIC_USAGE.md)** - Learn different API patterns
|
|
356
|
-
- **[Technical Specification](TECHNICAL_SPECIFICATION.md)** - Detailed technical information
|
|
357
|
-
|
|
358
|
-
The server mode makes llmjs2 compatible with any OpenAI-compatible client or application!
|
package/core/index.js
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
const OpenAIProvider = require('./providers/openai');
|
|
2
|
-
const OllamaProvider = require('./providers/ollama');
|
|
3
|
-
const OpenRouterProvider = require('./providers/openrouter');
|
|
4
|
-
const { completion } = require('./completion');
|
|
5
|
-
const { router } = require('./router');
|
|
6
|
-
const { app } = require('./server');
|
|
7
|
-
|
|
8
|
-
class LLMJS2 {
|
|
9
|
-
constructor(config = {}) {
|
|
10
|
-
this.defaultProvider = config.defaultProvider;
|
|
11
|
-
this.providers = {
|
|
12
|
-
openai: new OpenAIProvider(config.openai || {}),
|
|
13
|
-
ollama: new OllamaProvider(config.ollama || {}),
|
|
14
|
-
openrouter: new OpenRouterProvider(config.openrouter || {})
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
parseModel(modelString) {
|
|
19
|
-
if (!modelString || typeof modelString !== 'string') {
|
|
20
|
-
return { provider: null, model: null };
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const firstSlashIndex = modelString.indexOf('/');
|
|
24
|
-
if (firstSlashIndex !== -1) {
|
|
25
|
-
return {
|
|
26
|
-
provider: modelString.substring(0, firstSlashIndex),
|
|
27
|
-
model: modelString.substring(firstSlashIndex + 1)
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return { provider: null, model: modelString };
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
getAvailableProviders() {
|
|
35
|
-
const available = [];
|
|
36
|
-
|
|
37
|
-
const openaiKey = process.env.OPENAI_API_KEY || this.providers.openai.apiKey;
|
|
38
|
-
const ollamaKey = process.env.OLLAMA_API_KEY || this.providers.ollama.apiKey;
|
|
39
|
-
const openrouterKey = process.env.OPEN_ROUTER_API_KEY || this.providers.openrouter.apiKey;
|
|
40
|
-
|
|
41
|
-
if (openaiKey && typeof openaiKey === 'string' && openaiKey.trim() && !openaiKey.startsWith(':')) {
|
|
42
|
-
available.push('openai');
|
|
43
|
-
}
|
|
44
|
-
if (ollamaKey && typeof ollamaKey === 'string' && ollamaKey.trim() && !ollamaKey.startsWith(':')) {
|
|
45
|
-
available.push('ollama');
|
|
46
|
-
}
|
|
47
|
-
if (openrouterKey && typeof openrouterKey === 'string' && openrouterKey.trim() && !openrouterKey.startsWith(':')) {
|
|
48
|
-
available.push('openrouter');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return available;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
getAutoProvider() {
|
|
55
|
-
const availableProviders = this.getAvailableProviders();
|
|
56
|
-
if (availableProviders.length === 0) {
|
|
57
|
-
throw new Error('No API keys found. Set OLLAMA_API_KEY, OPEN_ROUTER_API_KEY, or OPENAI_API_KEY environment variables.');
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const randomIndex = Math.floor(Math.random() * availableProviders.length);
|
|
61
|
-
const providerName = availableProviders[randomIndex];
|
|
62
|
-
const provider = this.providers[providerName];
|
|
63
|
-
|
|
64
|
-
return {
|
|
65
|
-
provider,
|
|
66
|
-
model: provider.defaultModel
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
getProvider(modelString) {
|
|
71
|
-
const { provider: specifiedProvider, model } = this.parseModel(modelString);
|
|
72
|
-
|
|
73
|
-
if (specifiedProvider) {
|
|
74
|
-
const provider = this.providers[specifiedProvider];
|
|
75
|
-
if (!provider) {
|
|
76
|
-
throw new Error(`Unknown provider: ${specifiedProvider}`);
|
|
77
|
-
}
|
|
78
|
-
return { provider, model };
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const availableProviders = this.getAvailableProviders();
|
|
82
|
-
if (availableProviders.length === 0) {
|
|
83
|
-
throw new Error('No API keys configured. Set OPENAI_API_KEY, OLLAMA_API_KEY, or OPEN_ROUTER_API_KEY environment variables.');
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const providerName = this.defaultProvider && availableProviders.includes(this.defaultProvider)
|
|
87
|
-
? this.defaultProvider
|
|
88
|
-
: availableProviders[0];
|
|
89
|
-
const provider = this.providers[providerName];
|
|
90
|
-
|
|
91
|
-
return {
|
|
92
|
-
provider,
|
|
93
|
-
model: model || provider.defaultModel
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
completion(input) {
|
|
98
|
-
return completion(input, {
|
|
99
|
-
defaultProvider: this.defaultProvider,
|
|
100
|
-
openai: { apiKey: this.providers.openai.apiKey, baseURL: this.providers.openai.baseURL, timeout: this.providers.openai.timeout },
|
|
101
|
-
ollama: { apiKey: this.providers.ollama.apiKey, baseURL: this.providers.ollama.baseURL, timeout: this.providers.ollama.timeout },
|
|
102
|
-
openrouter: { apiKey: this.providers.openrouter.apiKey, baseURL: this.providers.openrouter.baseURL, timeout: this.providers.openrouter.timeout }
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
module.exports = {
|
|
108
|
-
completion,
|
|
109
|
-
LLMJS2,
|
|
110
|
-
router,
|
|
111
|
-
app,
|
|
112
|
-
OpenAIProvider,
|
|
113
|
-
OllamaProvider,
|
|
114
|
-
OpenRouterProvider
|
|
115
|
-
};
|