intentiai 0.1.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/README.md +156 -0
- package/bin/intentiai.js +39 -0
- package/commands/auth.js +242 -0
- package/commands/deploy.js +153 -0
- package/commands/docs.js +164 -0
- package/commands/intent.js +251 -0
- package/commands/project.js +193 -0
- package/commands/prompt.js +164 -0
- package/commands/route.js +187 -0
- package/commands/test.js +88 -0
- package/commands/train.js +135 -0
- package/lib/api.js +233 -0
- package/lib/config.js +94 -0
- package/package.json +47 -0
package/README.md
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# IntentiAI
|
|
2
|
+
|
|
3
|
+
Intent-aware LLM routing that saves 60-90% on API costs while maintaining quality.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g intentiai
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Login (opens browser for authentication)
|
|
15
|
+
intentiai auth login
|
|
16
|
+
|
|
17
|
+
# Create a project
|
|
18
|
+
intentiai project create "My Chatbot"
|
|
19
|
+
|
|
20
|
+
# Add intents
|
|
21
|
+
intentiai intent add "refund_request" -d "Customer wants a refund"
|
|
22
|
+
intentiai intent add "order_status" -d "Customer checking order status"
|
|
23
|
+
intentiai intent add "product_question" -d "Questions about products"
|
|
24
|
+
|
|
25
|
+
# Set up routing (cheap models for easy queries, GPT-4 for hard ones)
|
|
26
|
+
intentiai route add -i "order_status" -d easy -p groq -m "llama-3.1-8b-instant"
|
|
27
|
+
intentiai route add -i "product_question" -d easy -p groq -m "llama-3.1-8b-instant"
|
|
28
|
+
intentiai route add -i "refund_request" -d hard -p openai -m "gpt-4o"
|
|
29
|
+
|
|
30
|
+
# Set system prompts
|
|
31
|
+
intentiai prompt set -i "refund_request" -s "You are a helpful customer service agent. Help with refunds politely."
|
|
32
|
+
|
|
33
|
+
# Train the intent classifier
|
|
34
|
+
intentiai train start --samples 20 --watch
|
|
35
|
+
|
|
36
|
+
# Test your chatbot
|
|
37
|
+
intentiai test "Where is my order?"
|
|
38
|
+
intentiai test "I want a refund for my purchase"
|
|
39
|
+
|
|
40
|
+
# Get embed code for your website
|
|
41
|
+
intentiai deploy
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## How It Works
|
|
45
|
+
|
|
46
|
+
1. **Intent Classification** - Queries are classified into intents (refund_request, order_status, etc.)
|
|
47
|
+
2. **Difficulty Assessment** - Each query is rated as easy, medium, or hard
|
|
48
|
+
3. **Smart Routing** - Easy queries → fast/cheap models (Groq Llama), Hard queries → powerful models (GPT-4)
|
|
49
|
+
4. **Cost Savings** - 60-90% reduction in LLM API costs
|
|
50
|
+
|
|
51
|
+
## Commands
|
|
52
|
+
|
|
53
|
+
### Authentication
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
intentiai auth login # Browser-based login (recommended)
|
|
57
|
+
intentiai auth login --no-browser # Terminal login with email/password
|
|
58
|
+
intentiai auth whoami # Show current user
|
|
59
|
+
intentiai auth logout # Logout
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Project Management
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
intentiai project create "Name" # Create a new project
|
|
66
|
+
intentiai project list # List all projects
|
|
67
|
+
intentiai project select <id> # Select a project to work with
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Intent Management
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
intentiai intent add "name" -d "description" # Add an intent
|
|
74
|
+
intentiai intent list # List all intents
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Routing Rules
|
|
78
|
+
|
|
79
|
+
Route queries to different models based on intent and difficulty:
|
|
80
|
+
- `easy` → Fast, cheap models (Groq Llama 3.1 8B)
|
|
81
|
+
- `medium` → Balanced models (Groq Llama 3.3 70B)
|
|
82
|
+
- `hard` → Powerful models (GPT-4o)
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
intentiai route add -i "intent_name" -d easy -p groq -m "llama-3.1-8b-instant"
|
|
86
|
+
intentiai route add -i "intent_name" -d medium -p groq -m "llama-3.3-70b-versatile"
|
|
87
|
+
intentiai route add -i "intent_name" -d hard -p openai -m "gpt-4o"
|
|
88
|
+
intentiai route list
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### System Prompts
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
intentiai prompt set -i "intent_name" -s "Your system prompt here"
|
|
95
|
+
intentiai prompt get -i "intent_name"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Training
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
intentiai train start --samples 20 --watch # Train the classifier
|
|
102
|
+
intentiai train status # Check training status
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Testing & Deployment
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
intentiai test "Your test message" # Test a query
|
|
109
|
+
intentiai deploy # Get embed code and API info
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## API Integration
|
|
113
|
+
|
|
114
|
+
### JavaScript/TypeScript
|
|
115
|
+
```javascript
|
|
116
|
+
const response = await fetch('https://api.intentiai.com/v1/chat/completions', {
|
|
117
|
+
method: 'POST',
|
|
118
|
+
headers: {
|
|
119
|
+
'Content-Type': 'application/json',
|
|
120
|
+
'X-Project-Key': 'your_project_key'
|
|
121
|
+
},
|
|
122
|
+
body: JSON.stringify({
|
|
123
|
+
messages: [{ role: 'user', content: 'I want a refund' }]
|
|
124
|
+
})
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
const data = await response.json();
|
|
128
|
+
console.log(data.choices[0].message.content);
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Python (OpenAI SDK Compatible)
|
|
132
|
+
```python
|
|
133
|
+
from openai import OpenAI
|
|
134
|
+
|
|
135
|
+
client = OpenAI(
|
|
136
|
+
base_url='https://api.intentiai.com/v1',
|
|
137
|
+
api_key='your_project_key'
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
response = client.chat.completions.create(
|
|
141
|
+
model='auto', # IntentiAI routes automatically
|
|
142
|
+
messages=[{'role': 'user', 'content': 'I want a refund'}]
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
print(response.choices[0].message.content)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Links
|
|
149
|
+
|
|
150
|
+
- Website: https://www.intentiai.com
|
|
151
|
+
- Documentation: https://www.intentiai.com/docs
|
|
152
|
+
- Dashboard: https://www.intentiai.com/dashboard
|
|
153
|
+
|
|
154
|
+
## License
|
|
155
|
+
|
|
156
|
+
MIT
|
package/bin/intentiai.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { program } = require('commander');
|
|
4
|
+
const packageJson = require('../package.json');
|
|
5
|
+
|
|
6
|
+
// Import command modules
|
|
7
|
+
const authCommands = require('../commands/auth');
|
|
8
|
+
const projectCommands = require('../commands/project');
|
|
9
|
+
const intentCommands = require('../commands/intent');
|
|
10
|
+
const routeCommands = require('../commands/route');
|
|
11
|
+
const promptCommands = require('../commands/prompt');
|
|
12
|
+
const docsCommands = require('../commands/docs');
|
|
13
|
+
const trainCommands = require('../commands/train');
|
|
14
|
+
const testCommands = require('../commands/test');
|
|
15
|
+
const deployCommands = require('../commands/deploy');
|
|
16
|
+
|
|
17
|
+
program
|
|
18
|
+
.name('intentiai')
|
|
19
|
+
.description('IntentiAI CLI - Intelligent LLM routing and orchestration')
|
|
20
|
+
.version(packageJson.version);
|
|
21
|
+
|
|
22
|
+
// Register all commands
|
|
23
|
+
authCommands(program);
|
|
24
|
+
projectCommands(program);
|
|
25
|
+
intentCommands(program);
|
|
26
|
+
routeCommands(program);
|
|
27
|
+
promptCommands(program);
|
|
28
|
+
docsCommands(program);
|
|
29
|
+
trainCommands(program);
|
|
30
|
+
testCommands(program);
|
|
31
|
+
deployCommands(program);
|
|
32
|
+
|
|
33
|
+
// Parse arguments
|
|
34
|
+
program.parse(process.argv);
|
|
35
|
+
|
|
36
|
+
// Show help if no command provided
|
|
37
|
+
if (!process.argv.slice(2).length) {
|
|
38
|
+
program.outputHelp();
|
|
39
|
+
}
|
package/commands/auth.js
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
const inquirer = require('inquirer');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
const ora = require('ora');
|
|
4
|
+
const api = require('../lib/api');
|
|
5
|
+
const config = require('../lib/config');
|
|
6
|
+
|
|
7
|
+
// Generate a random device code
|
|
8
|
+
function generateDeviceCode() {
|
|
9
|
+
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
|
|
10
|
+
let code = '';
|
|
11
|
+
for (let i = 0; i < 8; i++) {
|
|
12
|
+
code += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
13
|
+
}
|
|
14
|
+
return code;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Open URL in browser
|
|
18
|
+
async function openBrowser(url) {
|
|
19
|
+
const { exec } = require('child_process');
|
|
20
|
+
const platform = process.platform;
|
|
21
|
+
|
|
22
|
+
let command;
|
|
23
|
+
if (platform === 'win32') {
|
|
24
|
+
command = `start "" "${url}"`;
|
|
25
|
+
} else if (platform === 'darwin') {
|
|
26
|
+
command = `open "${url}"`;
|
|
27
|
+
} else {
|
|
28
|
+
command = `xdg-open "${url}"`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
exec(command, (error) => {
|
|
33
|
+
if (error) reject(error);
|
|
34
|
+
else resolve();
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Sleep helper
|
|
40
|
+
function sleep(ms) {
|
|
41
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = (program) => {
|
|
45
|
+
const auth = program.command('auth').description('Authentication commands');
|
|
46
|
+
|
|
47
|
+
// Login command - Browser-based by default
|
|
48
|
+
auth
|
|
49
|
+
.command('login')
|
|
50
|
+
.description('Login to IntentiAI via browser')
|
|
51
|
+
.option('--no-browser', 'Use email/password instead of browser')
|
|
52
|
+
.option('-u, --username <username>', 'Username (for --no-browser mode)')
|
|
53
|
+
.option('-p, --password <password>', 'Password (for --no-browser mode)')
|
|
54
|
+
.action(async (options) => {
|
|
55
|
+
try {
|
|
56
|
+
// If --no-browser flag is set, use traditional login
|
|
57
|
+
if (options.browser === false) {
|
|
58
|
+
await traditionalLogin(options);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Browser-based login flow
|
|
63
|
+
const deviceCode = generateDeviceCode();
|
|
64
|
+
const baseUrl = config.getWebUrl();
|
|
65
|
+
const loginUrl = `${baseUrl}/cli-auth?code=${deviceCode}`;
|
|
66
|
+
|
|
67
|
+
console.log();
|
|
68
|
+
console.log(chalk.bold(' IntentiAI CLI Login'));
|
|
69
|
+
console.log();
|
|
70
|
+
console.log(' Opening browser to complete authentication...');
|
|
71
|
+
console.log();
|
|
72
|
+
console.log(chalk.gray(' If browser doesn\'t open, visit:'));
|
|
73
|
+
console.log(chalk.cyan(` ${loginUrl}`));
|
|
74
|
+
console.log();
|
|
75
|
+
console.log(chalk.gray(' Verification code:'), chalk.bold.white(deviceCode));
|
|
76
|
+
console.log();
|
|
77
|
+
|
|
78
|
+
// Try to open browser
|
|
79
|
+
try {
|
|
80
|
+
await openBrowser(loginUrl);
|
|
81
|
+
} catch (e) {
|
|
82
|
+
console.log(chalk.yellow(' Could not open browser automatically.'));
|
|
83
|
+
console.log(chalk.yellow(' Please open the URL above manually.'));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Start polling for auth completion
|
|
87
|
+
const spinner = ora('Waiting for authentication...').start();
|
|
88
|
+
|
|
89
|
+
let attempts = 0;
|
|
90
|
+
const maxAttempts = 120; // 2 minutes timeout (polling every 1 second)
|
|
91
|
+
|
|
92
|
+
while (attempts < maxAttempts) {
|
|
93
|
+
try {
|
|
94
|
+
const result = await api.checkDeviceAuth(deviceCode);
|
|
95
|
+
|
|
96
|
+
if (result.authenticated) {
|
|
97
|
+
config.setAuth(result.username, result.access_token);
|
|
98
|
+
spinner.succeed(chalk.green('Successfully logged in!'));
|
|
99
|
+
console.log();
|
|
100
|
+
console.log(chalk.gray(' Logged in as:'), chalk.white(result.username));
|
|
101
|
+
console.log(chalk.gray(' Email:'), chalk.white(result.email));
|
|
102
|
+
console.log();
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
} catch (e) {
|
|
106
|
+
// Device not authenticated yet, continue polling
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
await sleep(1000);
|
|
110
|
+
attempts++;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
spinner.fail(chalk.red('Authentication timed out'));
|
|
114
|
+
console.log(chalk.gray('Please try again with'), chalk.cyan('intentiai auth login'));
|
|
115
|
+
process.exit(1);
|
|
116
|
+
|
|
117
|
+
} catch (error) {
|
|
118
|
+
console.error(chalk.red('Login failed:'), error.message);
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Traditional username/password login
|
|
124
|
+
async function traditionalLogin(options) {
|
|
125
|
+
let { username, password } = options;
|
|
126
|
+
|
|
127
|
+
// Prompt for credentials if not provided
|
|
128
|
+
if (!username || !password) {
|
|
129
|
+
const answers = await inquirer.prompt([
|
|
130
|
+
{
|
|
131
|
+
type: 'input',
|
|
132
|
+
name: 'username',
|
|
133
|
+
message: 'Email:',
|
|
134
|
+
when: !username
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
type: 'password',
|
|
138
|
+
name: 'password',
|
|
139
|
+
message: 'Password:',
|
|
140
|
+
when: !password
|
|
141
|
+
}
|
|
142
|
+
]);
|
|
143
|
+
|
|
144
|
+
username = username || answers.username;
|
|
145
|
+
password = password || answers.password;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const spinner = ora('Logging in...').start();
|
|
149
|
+
|
|
150
|
+
const response = await api.login(username, password);
|
|
151
|
+
|
|
152
|
+
// Save credentials
|
|
153
|
+
config.setAuth(response.username || username, response.api_key || response.access_token);
|
|
154
|
+
|
|
155
|
+
spinner.succeed(chalk.green('Successfully logged in!'));
|
|
156
|
+
console.log(chalk.gray('Username:'), username);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Register command
|
|
160
|
+
auth
|
|
161
|
+
.command('register')
|
|
162
|
+
.description('Register a new account')
|
|
163
|
+
.option('-u, --username <username>', 'Username')
|
|
164
|
+
.option('-e, --email <email>', 'Email')
|
|
165
|
+
.option('-p, --password <password>', 'Password')
|
|
166
|
+
.action(async (options) => {
|
|
167
|
+
try {
|
|
168
|
+
let { username, email, password } = options;
|
|
169
|
+
|
|
170
|
+
// Prompt for details if not provided
|
|
171
|
+
if (!username || !email || !password) {
|
|
172
|
+
const answers = await inquirer.prompt([
|
|
173
|
+
{
|
|
174
|
+
type: 'input',
|
|
175
|
+
name: 'username',
|
|
176
|
+
message: 'Username:',
|
|
177
|
+
when: !username
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
type: 'input',
|
|
181
|
+
name: 'email',
|
|
182
|
+
message: 'Email:',
|
|
183
|
+
when: !email,
|
|
184
|
+
validate: (input) => {
|
|
185
|
+
return /\S+@\S+\.\S+/.test(input) || 'Please enter a valid email';
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
type: 'password',
|
|
190
|
+
name: 'password',
|
|
191
|
+
message: 'Password:',
|
|
192
|
+
when: !password
|
|
193
|
+
}
|
|
194
|
+
]);
|
|
195
|
+
|
|
196
|
+
username = username || answers.username;
|
|
197
|
+
email = email || answers.email;
|
|
198
|
+
password = password || answers.password;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const spinner = ora('Creating account...').start();
|
|
202
|
+
|
|
203
|
+
const response = await api.register(username, email, password);
|
|
204
|
+
|
|
205
|
+
// Auto-login after registration
|
|
206
|
+
config.setAuth(username, response.api_key || response.access_token);
|
|
207
|
+
|
|
208
|
+
spinner.succeed(chalk.green('Account created successfully!'));
|
|
209
|
+
console.log(chalk.gray('Username:'), username);
|
|
210
|
+
console.log(chalk.gray('Email:'), email);
|
|
211
|
+
} catch (error) {
|
|
212
|
+
console.error(chalk.red('Registration failed:'), error.message);
|
|
213
|
+
process.exit(1);
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// Logout command
|
|
218
|
+
auth
|
|
219
|
+
.command('logout')
|
|
220
|
+
.description('Logout from IntentiAI')
|
|
221
|
+
.action(() => {
|
|
222
|
+
config.clearAuth();
|
|
223
|
+
console.log(chalk.green('Successfully logged out!'));
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
// Whoami command
|
|
227
|
+
auth
|
|
228
|
+
.command('whoami')
|
|
229
|
+
.description('Show current user')
|
|
230
|
+
.action(() => {
|
|
231
|
+
const username = config.getUsername();
|
|
232
|
+
const apiKey = config.getApiKey();
|
|
233
|
+
|
|
234
|
+
if (username) {
|
|
235
|
+
console.log(chalk.green('Logged in as:'), username);
|
|
236
|
+
console.log(chalk.gray('API Key:'), apiKey ? apiKey.substring(0, 20) + '...' : 'Not set');
|
|
237
|
+
} else {
|
|
238
|
+
console.log(chalk.yellow('Not logged in'));
|
|
239
|
+
console.log(chalk.gray('Run'), chalk.cyan('intentiai auth login'), chalk.gray('to login'));
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const ora = require('ora');
|
|
3
|
+
const api = require('../lib/api');
|
|
4
|
+
const config = require('../lib/config');
|
|
5
|
+
|
|
6
|
+
function requireProject() {
|
|
7
|
+
const projectKey = config.getCurrentProject();
|
|
8
|
+
if (!projectKey) {
|
|
9
|
+
console.error(chalk.red('No project selected'));
|
|
10
|
+
console.log(chalk.gray('Select a project with:'), chalk.cyan('gatellm project select'));
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
return projectKey;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
module.exports = (program) => {
|
|
17
|
+
// Deploy command
|
|
18
|
+
program
|
|
19
|
+
.command('deploy')
|
|
20
|
+
.description('Deploy your chatbot (show integration info)')
|
|
21
|
+
.action(async () => {
|
|
22
|
+
const projectKey = requireProject();
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const spinner = ora('Fetching project details...').start();
|
|
26
|
+
|
|
27
|
+
const project = await api.getProject(projectKey);
|
|
28
|
+
const apiUrl = config.getApiUrl();
|
|
29
|
+
|
|
30
|
+
spinner.stop();
|
|
31
|
+
|
|
32
|
+
console.log(chalk.green('\n✓ Your chatbot is ready to deploy!\n'));
|
|
33
|
+
|
|
34
|
+
console.log(chalk.cyan('=== Integration Details ===\n'));
|
|
35
|
+
|
|
36
|
+
console.log(chalk.gray('API Endpoint:'));
|
|
37
|
+
console.log(chalk.white(` ${apiUrl}/v1/chat/completions\n`));
|
|
38
|
+
|
|
39
|
+
console.log(chalk.gray('Project Key (use as API key):'));
|
|
40
|
+
console.log(chalk.white(` ${projectKey}\n`));
|
|
41
|
+
|
|
42
|
+
console.log(chalk.cyan('=== Example Usage ===\n'));
|
|
43
|
+
|
|
44
|
+
console.log(chalk.yellow('cURL:'));
|
|
45
|
+
console.log(chalk.gray(`
|
|
46
|
+
curl ${apiUrl}/v1/chat/completions \\
|
|
47
|
+
-H "Content-Type: application/json" \\
|
|
48
|
+
-H "X-Project-Key: ${projectKey}" \\
|
|
49
|
+
-d '{
|
|
50
|
+
"messages": [
|
|
51
|
+
{"role": "user", "content": "Hello!"}
|
|
52
|
+
]
|
|
53
|
+
}'
|
|
54
|
+
`));
|
|
55
|
+
|
|
56
|
+
console.log(chalk.yellow('JavaScript/Node.js:'));
|
|
57
|
+
console.log(chalk.gray(`
|
|
58
|
+
const response = await fetch('${apiUrl}/v1/chat/completions', {
|
|
59
|
+
method: 'POST',
|
|
60
|
+
headers: {
|
|
61
|
+
'Content-Type': 'application/json',
|
|
62
|
+
'X-Project-Key': '${projectKey}'
|
|
63
|
+
},
|
|
64
|
+
body: JSON.stringify({
|
|
65
|
+
messages: [
|
|
66
|
+
{ role: 'user', content: 'Hello!' }
|
|
67
|
+
]
|
|
68
|
+
})
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const data = await response.json();
|
|
72
|
+
console.log(data.choices[0].message.content);
|
|
73
|
+
`));
|
|
74
|
+
|
|
75
|
+
console.log(chalk.yellow('Python:'));
|
|
76
|
+
console.log(chalk.gray(`
|
|
77
|
+
import requests
|
|
78
|
+
|
|
79
|
+
response = requests.post(
|
|
80
|
+
'${apiUrl}/v1/chat/completions',
|
|
81
|
+
headers={
|
|
82
|
+
'Content-Type': 'application/json',
|
|
83
|
+
'X-Project-Key': '${projectKey}'
|
|
84
|
+
},
|
|
85
|
+
json={
|
|
86
|
+
'messages': [
|
|
87
|
+
{'role': 'user', 'content': 'Hello!'}
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
print(response.json()['choices'][0]['message']['content'])
|
|
93
|
+
`));
|
|
94
|
+
|
|
95
|
+
console.log(chalk.yellow('OpenAI SDK (Python):'));
|
|
96
|
+
console.log(chalk.gray(`
|
|
97
|
+
from openai import OpenAI
|
|
98
|
+
|
|
99
|
+
client = OpenAI(
|
|
100
|
+
base_url='${apiUrl}/v1',
|
|
101
|
+
api_key='${projectKey}'
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
response = client.chat.completions.create(
|
|
105
|
+
model='gpt-4o', # Will be routed by GateLLM
|
|
106
|
+
messages=[
|
|
107
|
+
{'role': 'user', 'content': 'Hello!'}
|
|
108
|
+
]
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
print(response.choices[0].message.content)
|
|
112
|
+
`));
|
|
113
|
+
|
|
114
|
+
console.log(chalk.cyan('\n=== Next Steps ===\n'));
|
|
115
|
+
console.log(chalk.gray('1. Test your deployment:'));
|
|
116
|
+
console.log(chalk.white(` gatellm test "Hello, how are you?"\n`));
|
|
117
|
+
console.log(chalk.gray('2. View project details:'));
|
|
118
|
+
console.log(chalk.white(` gatellm project current\n`));
|
|
119
|
+
console.log(chalk.gray('3. Monitor in production:'));
|
|
120
|
+
console.log(chalk.white(` Check logs at: ${apiUrl}/logs (coming soon)\n`));
|
|
121
|
+
|
|
122
|
+
} catch (error) {
|
|
123
|
+
console.error(chalk.red('Failed to get deployment info:'), error.message);
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// Status command
|
|
129
|
+
program
|
|
130
|
+
.command('status')
|
|
131
|
+
.description('Check API server status')
|
|
132
|
+
.action(async () => {
|
|
133
|
+
try {
|
|
134
|
+
const apiUrl = config.getApiUrl();
|
|
135
|
+
const spinner = ora(`Checking API status at ${apiUrl}...`).start();
|
|
136
|
+
|
|
137
|
+
const health = await api.health();
|
|
138
|
+
|
|
139
|
+
spinner.succeed(chalk.green('API server is healthy!'));
|
|
140
|
+
console.log(chalk.gray('Status:'), health.status);
|
|
141
|
+
console.log(chalk.gray('API URL:'), apiUrl);
|
|
142
|
+
|
|
143
|
+
if (health.version) {
|
|
144
|
+
console.log(chalk.gray('Version:'), health.version);
|
|
145
|
+
}
|
|
146
|
+
} catch (error) {
|
|
147
|
+
console.error(chalk.red('API server is not reachable:'), error.message);
|
|
148
|
+
console.log(chalk.gray('\nMake sure the GateLLM API server is running'));
|
|
149
|
+
console.log(chalk.gray('Default URL:'), 'http://localhost:8000');
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
};
|