@orchestra-research/ai-research-skills 1.0.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/src/prompts.js ADDED
@@ -0,0 +1,436 @@
1
+ import inquirer from 'inquirer';
2
+ import chalk from 'chalk';
3
+
4
+ /**
5
+ * Skill categories with their skill counts and example skills
6
+ */
7
+ export const CATEGORIES = [
8
+ { id: '01-model-architecture', name: 'Model Architecture', skills: 6, examples: 'LitGPT, Mamba, TorchTitan, Megatron' },
9
+ { id: '02-tokenization', name: 'Tokenization', skills: 2, examples: 'HuggingFace Tokenizers, SentencePiece' },
10
+ { id: '03-fine-tuning', name: 'Fine-Tuning', skills: 5, examples: 'Axolotl, Unsloth, Torchtune, PEFT' },
11
+ { id: '04-mechanistic-interpretability', name: 'Mechanistic Interp.', skills: 4, examples: 'TransformerLens, SAELens, NNsight' },
12
+ { id: '05-data-processing', name: 'Data Processing', skills: 2, examples: 'NeMo Curator, Ray Data' },
13
+ { id: '06-post-training', name: 'Post-Training', skills: 8, examples: 'GRPO, verl, slime, miles, torchforge' },
14
+ { id: '07-safety-alignment', name: 'Safety & Alignment', skills: 3, examples: 'Constitutional AI, LlamaGuard' },
15
+ { id: '08-distributed-training', name: 'Distributed Training', skills: 6, examples: 'DeepSpeed, FSDP, Megatron, Accelerate' },
16
+ { id: '09-infrastructure', name: 'Infrastructure', skills: 3, examples: 'Modal, SkyPilot, Lambda Labs' },
17
+ { id: '10-optimization', name: 'Optimization', skills: 6, examples: 'Flash Attention, GPTQ, AWQ, bitsandbytes' },
18
+ { id: '11-evaluation', name: 'Evaluation', skills: 3, examples: 'lm-eval-harness, Inspect AI' },
19
+ { id: '12-inference-serving', name: 'Inference Serving', skills: 4, examples: 'vLLM, TensorRT-LLM, SGLang, llama.cpp' },
20
+ { id: '13-mlops', name: 'MLOps', skills: 3, examples: 'Weights & Biases, MLflow, TensorBoard' },
21
+ { id: '14-agents', name: 'Agents', skills: 4, examples: 'LangChain, LlamaIndex, Smolagents' },
22
+ { id: '15-rag', name: 'RAG', skills: 5, examples: 'Chroma, FAISS, Pinecone, Milvus' },
23
+ { id: '16-prompt-engineering', name: 'Prompt Engineering', skills: 4, examples: 'DSPy, Instructor, Outlines, Guidance' },
24
+ { id: '17-observability', name: 'Observability', skills: 2, examples: 'LangSmith, Phoenix' },
25
+ { id: '18-multimodal', name: 'Multimodal', skills: 7, examples: 'CLIP, Whisper, LLaVA, Qwen2-VL' },
26
+ { id: '19-emerging-techniques', name: 'Emerging Techniques', skills: 6, examples: 'MoE, Model Merging, Speculative Decoding' },
27
+ { id: '20-ml-paper-writing', name: 'ML Paper Writing', skills: 1, examples: 'NeurIPS/ICML paper writing' },
28
+ ];
29
+
30
+ /**
31
+ * Individual skills for selection
32
+ */
33
+ export const INDIVIDUAL_SKILLS = [
34
+ // Post-Training
35
+ { id: '06-post-training/grpo-rl-training', name: 'GRPO Training', category: 'Post-Training' },
36
+ { id: '06-post-training/verl', name: 'verl', category: 'Post-Training' },
37
+ { id: '06-post-training/slime', name: 'slime', category: 'Post-Training' },
38
+ { id: '06-post-training/miles', name: 'miles', category: 'Post-Training' },
39
+ { id: '06-post-training/torchforge', name: 'torchforge', category: 'Post-Training' },
40
+ { id: '06-post-training/trl-fine-tuning', name: 'TRL', category: 'Post-Training' },
41
+ { id: '06-post-training/openrlhf', name: 'OpenRLHF', category: 'Post-Training' },
42
+ { id: '06-post-training/simpo', name: 'SimPO', category: 'Post-Training' },
43
+ // Fine-Tuning
44
+ { id: '03-fine-tuning/axolotl', name: 'Axolotl', category: 'Fine-Tuning' },
45
+ { id: '03-fine-tuning/unsloth', name: 'Unsloth', category: 'Fine-Tuning' },
46
+ { id: '03-fine-tuning/torchtune', name: 'Torchtune', category: 'Fine-Tuning' },
47
+ // Inference
48
+ { id: '12-inference-serving/vllm', name: 'vLLM', category: 'Inference' },
49
+ { id: '12-inference-serving/sglang', name: 'SGLang', category: 'Inference' },
50
+ { id: '12-inference-serving/tensorrt-llm', name: 'TensorRT-LLM', category: 'Inference' },
51
+ // Training
52
+ { id: '08-distributed-training/deepspeed', name: 'DeepSpeed', category: 'Training' },
53
+ { id: '08-distributed-training/fsdp', name: 'FSDP', category: 'Training' },
54
+ { id: '01-model-architecture/torchtitan', name: 'TorchTitan', category: 'Architecture' },
55
+ // Optimization
56
+ { id: '10-optimization/flash-attention', name: 'Flash Attention', category: 'Optimization' },
57
+ { id: '10-optimization/gptq', name: 'GPTQ', category: 'Optimization' },
58
+ // Tools
59
+ { id: '13-mlops/wandb', name: 'Weights & Biases', category: 'MLOps' },
60
+ { id: '11-evaluation/lm-eval-harness', name: 'lm-eval-harness', category: 'Evaluation' },
61
+ { id: '16-prompt-engineering/dspy', name: 'DSPy', category: 'Prompting' },
62
+ { id: '15-rag/chroma', name: 'Chroma', category: 'RAG' },
63
+ // Paper Writing
64
+ { id: '20-ml-paper-writing', name: 'ML Paper Writing', category: 'Writing' },
65
+ ];
66
+
67
+ /**
68
+ * Quick start bundle - essential skills including paper writing
69
+ */
70
+ export const QUICK_START_SKILLS = [
71
+ '06-post-training/grpo-rl-training',
72
+ '06-post-training/verl',
73
+ '06-post-training/trl-fine-tuning',
74
+ '03-fine-tuning/axolotl',
75
+ '03-fine-tuning/unsloth',
76
+ '12-inference-serving/vllm',
77
+ '12-inference-serving/sglang',
78
+ '08-distributed-training/deepspeed',
79
+ '10-optimization/flash-attention',
80
+ '13-mlops/wandb',
81
+ '11-evaluation/lm-eval-harness',
82
+ '16-prompt-engineering/dspy',
83
+ '15-rag/chroma',
84
+ '20-ml-paper-writing',
85
+ ];
86
+
87
+ /**
88
+ * Get total skill count
89
+ */
90
+ export function getTotalSkillCount() {
91
+ return CATEGORIES.reduce((sum, cat) => sum + cat.skills, 0);
92
+ }
93
+
94
+ /**
95
+ * Ask main menu action after agent detection
96
+ */
97
+ export async function askMainMenuAction() {
98
+ console.log();
99
+ const { action } = await inquirer.prompt([
100
+ {
101
+ type: 'list',
102
+ name: 'action',
103
+ message: ' ',
104
+ choices: [
105
+ { name: 'Install new skills', value: 'install' },
106
+ { name: 'View installed skills', value: 'view' },
107
+ { name: 'Update all skills', value: 'update' },
108
+ new inquirer.Separator(' '),
109
+ { name: chalk.dim('Exit'), value: 'exit' },
110
+ ],
111
+ prefix: ' ',
112
+ },
113
+ ]);
114
+ return action;
115
+ }
116
+
117
+ /**
118
+ * Ask what to install
119
+ */
120
+ export async function askInstallChoice() {
121
+ const totalSkills = getTotalSkillCount();
122
+
123
+ console.log();
124
+ console.log(chalk.dim(' What would you like to install?'));
125
+ console.log();
126
+
127
+ const { choice } = await inquirer.prompt([
128
+ {
129
+ type: 'list',
130
+ name: 'choice',
131
+ message: ' ',
132
+ choices: [
133
+ {
134
+ name: `Everything ${chalk.dim(totalSkills + ' skills')}`,
135
+ value: 'everything',
136
+ },
137
+ {
138
+ name: `Quick start ${chalk.dim(QUICK_START_SKILLS.length + ' essential skills')}`,
139
+ value: 'quickstart',
140
+ },
141
+ {
142
+ name: `Select categories ${chalk.dim('Choose by category')}`,
143
+ value: 'categories',
144
+ },
145
+ {
146
+ name: `Select individual skills ${chalk.dim('Pick specific skills')}`,
147
+ value: 'individual',
148
+ },
149
+ new inquirer.Separator(' '),
150
+ {
151
+ name: chalk.dim('← Back'),
152
+ value: 'back',
153
+ },
154
+ ],
155
+ prefix: ' ',
156
+ },
157
+ ]);
158
+
159
+ return choice;
160
+ }
161
+
162
+ /**
163
+ * Ask which categories to install
164
+ */
165
+ export async function askCategories() {
166
+ console.log();
167
+ console.log(chalk.dim(' Select categories:'));
168
+ console.log(chalk.dim(' (Space to select, Enter to confirm)'));
169
+ console.log();
170
+
171
+ const { categories } = await inquirer.prompt([
172
+ {
173
+ type: 'checkbox',
174
+ name: 'categories',
175
+ message: ' ',
176
+ choices: CATEGORIES.map(cat => ({
177
+ name: `${cat.name.padEnd(22)} ${chalk.dim((cat.skills + '').padStart(2) + ' skills')}`,
178
+ value: cat.id,
179
+ short: cat.name,
180
+ })),
181
+ prefix: ' ',
182
+ pageSize: 12,
183
+ },
184
+ ]);
185
+
186
+ if (categories.length === 0) {
187
+ console.log();
188
+ const { action } = await inquirer.prompt([
189
+ {
190
+ type: 'list',
191
+ name: 'action',
192
+ message: chalk.yellow('No categories selected'),
193
+ choices: [
194
+ { name: 'Try again', value: 'retry' },
195
+ { name: chalk.dim('← Back'), value: 'back' },
196
+ ],
197
+ prefix: ' ',
198
+ },
199
+ ]);
200
+ return { categories: [], action };
201
+ }
202
+
203
+ return { categories, action: 'confirm' };
204
+ }
205
+
206
+ /**
207
+ * Ask which individual skills to install
208
+ */
209
+ export async function askIndividualSkills() {
210
+ console.log();
211
+ console.log(chalk.dim(' Select skills:'));
212
+ console.log(chalk.dim(' (Space to select, Enter to confirm)'));
213
+ console.log();
214
+
215
+ const { skills } = await inquirer.prompt([
216
+ {
217
+ type: 'checkbox',
218
+ name: 'skills',
219
+ message: ' ',
220
+ choices: INDIVIDUAL_SKILLS.map(skill => ({
221
+ name: `${skill.name.padEnd(20)} ${chalk.dim(skill.category)}`,
222
+ value: skill.id,
223
+ short: skill.name,
224
+ })),
225
+ prefix: ' ',
226
+ pageSize: 15,
227
+ },
228
+ ]);
229
+
230
+ if (skills.length === 0) {
231
+ console.log();
232
+ const { action } = await inquirer.prompt([
233
+ {
234
+ type: 'list',
235
+ name: 'action',
236
+ message: chalk.yellow('No skills selected'),
237
+ choices: [
238
+ { name: 'Try again', value: 'retry' },
239
+ { name: chalk.dim('← Back'), value: 'back' },
240
+ ],
241
+ prefix: ' ',
242
+ },
243
+ ]);
244
+ return { skills: [], action };
245
+ }
246
+
247
+ return { skills, action: 'confirm' };
248
+ }
249
+
250
+ /**
251
+ * Ask for confirmation with description
252
+ */
253
+ export async function askConfirmation(skillCount, agents, selectedCategories, selectedSkills, installType) {
254
+ console.log();
255
+ console.log(chalk.white(' Installation Summary'));
256
+ console.log(chalk.dim(' ─────────────────────────────────────────────────────'));
257
+ console.log();
258
+
259
+ // What's being installed
260
+ console.log(` ${chalk.white('Skills:')} ${skillCount} skills`);
261
+ console.log(` ${chalk.white('Agents:')} ${agents.map(a => a.name).join(', ')}`);
262
+ console.log();
263
+
264
+ // Description based on install type
265
+ if (installType === 'everything') {
266
+ console.log(chalk.dim(' All 20 categories including:'));
267
+ console.log(chalk.dim(' Post-Training, Fine-Tuning, Inference, Distributed Training,'));
268
+ console.log(chalk.dim(' Optimization, Evaluation, MLOps, RAG, Agents, Paper Writing...'));
269
+ } else if (installType === 'quickstart') {
270
+ console.log(chalk.dim(' Essential skills for AI research:'));
271
+ console.log(chalk.dim(' • GRPO, verl, TRL for post-training'));
272
+ console.log(chalk.dim(' • Axolotl, Unsloth for fine-tuning'));
273
+ console.log(chalk.dim(' • vLLM, SGLang for inference'));
274
+ console.log(chalk.dim(' • DeepSpeed, Flash Attention for training'));
275
+ console.log(chalk.dim(' • W&B, lm-eval, DSPy, Chroma'));
276
+ console.log(chalk.dim(' • ML Paper Writing for NeurIPS/ICML'));
277
+ } else if (selectedCategories && selectedCategories.length > 0) {
278
+ const catNames = CATEGORIES
279
+ .filter(c => selectedCategories.includes(c.id))
280
+ .map(c => c.name);
281
+ console.log(chalk.dim(' Selected categories:'));
282
+ catNames.forEach(name => console.log(chalk.dim(` • ${name}`)));
283
+ } else if (selectedSkills && selectedSkills.length > 0) {
284
+ console.log(chalk.dim(' Selected skills:'));
285
+ const skillNames = INDIVIDUAL_SKILLS
286
+ .filter(s => selectedSkills.includes(s.id))
287
+ .map(s => s.name)
288
+ .slice(0, 8);
289
+ skillNames.forEach(name => console.log(chalk.dim(` • ${name}`)));
290
+ if (selectedSkills.length > 8) {
291
+ console.log(chalk.dim(` • ...and ${selectedSkills.length - 8} more`));
292
+ }
293
+ }
294
+
295
+ console.log();
296
+ console.log(chalk.dim(' ─────────────────────────────────────────────────────'));
297
+ console.log();
298
+
299
+ const { action } = await inquirer.prompt([
300
+ {
301
+ type: 'list',
302
+ name: 'action',
303
+ message: ' ',
304
+ choices: [
305
+ { name: chalk.green('Install'), value: 'confirm' },
306
+ { name: chalk.dim('← Back'), value: 'back' },
307
+ { name: chalk.dim('Exit'), value: 'exit' },
308
+ ],
309
+ prefix: ' ',
310
+ },
311
+ ]);
312
+
313
+ return action;
314
+ }
315
+
316
+ /**
317
+ * Ask which agents to install to
318
+ */
319
+ export async function askSelectAgents(agents) {
320
+ console.log();
321
+ console.log(chalk.dim(' Install to which agents?'));
322
+ console.log();
323
+
324
+ const { selection } = await inquirer.prompt([
325
+ {
326
+ type: 'list',
327
+ name: 'selection',
328
+ message: ' ',
329
+ choices: [
330
+ { name: `All detected agents (${agents.length})`, value: 'all' },
331
+ { name: 'Select specific agents', value: 'select' },
332
+ new inquirer.Separator(' '),
333
+ { name: chalk.dim('← Back'), value: 'back' },
334
+ ],
335
+ prefix: ' ',
336
+ },
337
+ ]);
338
+
339
+ if (selection === 'back') {
340
+ return { agents: [], action: 'back' };
341
+ }
342
+
343
+ if (selection === 'all') {
344
+ return { agents, action: 'confirm' };
345
+ }
346
+
347
+ // Select specific agents
348
+ console.log();
349
+ const { selectedAgents } = await inquirer.prompt([
350
+ {
351
+ type: 'checkbox',
352
+ name: 'selectedAgents',
353
+ message: ' ',
354
+ choices: agents.map(agent => ({
355
+ name: `${agent.name.padEnd(14)} ${chalk.dim(agent.path)}`,
356
+ value: agent,
357
+ checked: true,
358
+ })),
359
+ prefix: ' ',
360
+ },
361
+ ]);
362
+
363
+ if (selectedAgents.length === 0) {
364
+ console.log();
365
+ const { action } = await inquirer.prompt([
366
+ {
367
+ type: 'list',
368
+ name: 'action',
369
+ message: chalk.yellow('No agents selected'),
370
+ choices: [
371
+ { name: 'Try again', value: 'retry' },
372
+ { name: chalk.dim('← Back'), value: 'back' },
373
+ ],
374
+ prefix: ' ',
375
+ },
376
+ ]);
377
+ return { agents: [], action };
378
+ }
379
+
380
+ return { agents: selectedAgents, action: 'confirm' };
381
+ }
382
+
383
+ /**
384
+ * Ask what to do after viewing/updating
385
+ */
386
+ export async function askAfterAction() {
387
+ console.log();
388
+ const { action } = await inquirer.prompt([
389
+ {
390
+ type: 'list',
391
+ name: 'action',
392
+ message: ' ',
393
+ choices: [
394
+ { name: '← Back to main menu', value: 'back' },
395
+ { name: chalk.dim('Exit'), value: 'exit' },
396
+ ],
397
+ prefix: ' ',
398
+ },
399
+ ]);
400
+ return action;
401
+ }
402
+
403
+ /**
404
+ * Parse command line arguments
405
+ */
406
+ export function parseArgs(args) {
407
+ const options = {
408
+ command: null,
409
+ all: false,
410
+ category: null,
411
+ skill: null,
412
+ agent: null,
413
+ };
414
+
415
+ for (let i = 0; i < args.length; i++) {
416
+ const arg = args[i];
417
+
418
+ if (arg === 'install') {
419
+ options.command = 'install';
420
+ } else if (arg === 'list') {
421
+ options.command = 'list';
422
+ } else if (arg === 'update') {
423
+ options.command = 'update';
424
+ } else if (arg === '--all' || arg === '-a') {
425
+ options.all = true;
426
+ } else if (arg === '--agent' && args[i + 1]) {
427
+ options.agent = args[++i];
428
+ } else if (arg === '--category' && args[i + 1]) {
429
+ options.category = args[++i];
430
+ } else if (!arg.startsWith('-') && !options.command) {
431
+ options.skill = arg;
432
+ }
433
+ }
434
+
435
+ return options;
436
+ }