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 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
@@ -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
+ }
@@ -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
+ };