aitelier 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.
Files changed (97) hide show
  1. package/dist/commands/add.d.ts +3 -0
  2. package/dist/commands/add.d.ts.map +1 -0
  3. package/dist/commands/add.js +141 -0
  4. package/dist/commands/add.js.map +1 -0
  5. package/dist/commands/add.test.d.ts +2 -0
  6. package/dist/commands/add.test.d.ts.map +1 -0
  7. package/dist/commands/add.test.js +203 -0
  8. package/dist/commands/add.test.js.map +1 -0
  9. package/dist/commands/eval.d.ts +3 -0
  10. package/dist/commands/eval.d.ts.map +1 -0
  11. package/dist/commands/eval.js +505 -0
  12. package/dist/commands/eval.js.map +1 -0
  13. package/dist/commands/eval.test.d.ts +2 -0
  14. package/dist/commands/eval.test.d.ts.map +1 -0
  15. package/dist/commands/eval.test.js +804 -0
  16. package/dist/commands/eval.test.js.map +1 -0
  17. package/dist/commands/format.d.ts +3 -0
  18. package/dist/commands/format.d.ts.map +1 -0
  19. package/dist/commands/format.js +198 -0
  20. package/dist/commands/format.js.map +1 -0
  21. package/dist/commands/format.test.d.ts +2 -0
  22. package/dist/commands/format.test.d.ts.map +1 -0
  23. package/dist/commands/format.test.js +568 -0
  24. package/dist/commands/format.test.js.map +1 -0
  25. package/dist/commands/init.d.ts +3 -0
  26. package/dist/commands/init.d.ts.map +1 -0
  27. package/dist/commands/init.js +94 -0
  28. package/dist/commands/init.js.map +1 -0
  29. package/dist/commands/init.test.d.ts +2 -0
  30. package/dist/commands/init.test.d.ts.map +1 -0
  31. package/dist/commands/init.test.js +123 -0
  32. package/dist/commands/init.test.js.map +1 -0
  33. package/dist/commands/rate.d.ts +3 -0
  34. package/dist/commands/rate.d.ts.map +1 -0
  35. package/dist/commands/rate.js +209 -0
  36. package/dist/commands/rate.js.map +1 -0
  37. package/dist/commands/rate.test.d.ts +2 -0
  38. package/dist/commands/rate.test.d.ts.map +1 -0
  39. package/dist/commands/rate.test.js +393 -0
  40. package/dist/commands/rate.test.js.map +1 -0
  41. package/dist/commands/split.d.ts +3 -0
  42. package/dist/commands/split.d.ts.map +1 -0
  43. package/dist/commands/split.js +210 -0
  44. package/dist/commands/split.js.map +1 -0
  45. package/dist/commands/split.test.d.ts +2 -0
  46. package/dist/commands/split.test.d.ts.map +1 -0
  47. package/dist/commands/split.test.js +503 -0
  48. package/dist/commands/split.test.js.map +1 -0
  49. package/dist/commands/stats.d.ts +3 -0
  50. package/dist/commands/stats.d.ts.map +1 -0
  51. package/dist/commands/stats.js +209 -0
  52. package/dist/commands/stats.js.map +1 -0
  53. package/dist/commands/stats.test.d.ts +2 -0
  54. package/dist/commands/stats.test.d.ts.map +1 -0
  55. package/dist/commands/stats.test.js +476 -0
  56. package/dist/commands/stats.test.js.map +1 -0
  57. package/dist/commands/status.d.ts +3 -0
  58. package/dist/commands/status.d.ts.map +1 -0
  59. package/dist/commands/status.js +132 -0
  60. package/dist/commands/status.js.map +1 -0
  61. package/dist/commands/status.test.d.ts +2 -0
  62. package/dist/commands/status.test.d.ts.map +1 -0
  63. package/dist/commands/status.test.js +443 -0
  64. package/dist/commands/status.test.js.map +1 -0
  65. package/dist/commands/train.d.ts +3 -0
  66. package/dist/commands/train.d.ts.map +1 -0
  67. package/dist/commands/train.js +139 -0
  68. package/dist/commands/train.js.map +1 -0
  69. package/dist/commands/train.test.d.ts +2 -0
  70. package/dist/commands/train.test.d.ts.map +1 -0
  71. package/dist/commands/train.test.js +288 -0
  72. package/dist/commands/train.test.js.map +1 -0
  73. package/dist/index.d.ts +3 -0
  74. package/dist/index.d.ts.map +1 -0
  75. package/dist/index.js +27 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/providers/openai.d.ts +9 -0
  78. package/dist/providers/openai.d.ts.map +1 -0
  79. package/dist/providers/openai.js +20 -0
  80. package/dist/providers/openai.js.map +1 -0
  81. package/dist/providers/together.d.ts +11 -0
  82. package/dist/providers/together.d.ts.map +1 -0
  83. package/dist/providers/together.js +118 -0
  84. package/dist/providers/together.js.map +1 -0
  85. package/dist/providers/types.d.ts +28 -0
  86. package/dist/providers/types.d.ts.map +1 -0
  87. package/dist/providers/types.js +2 -0
  88. package/dist/providers/types.js.map +1 -0
  89. package/dist/storage/config.d.ts +24 -0
  90. package/dist/storage/config.d.ts.map +1 -0
  91. package/dist/storage/config.js +11 -0
  92. package/dist/storage/config.js.map +1 -0
  93. package/dist/storage/dataset.d.ts +14 -0
  94. package/dist/storage/dataset.d.ts.map +1 -0
  95. package/dist/storage/dataset.js +18 -0
  96. package/dist/storage/dataset.js.map +1 -0
  97. package/package.json +58 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=status.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.test.d.ts","sourceRoot":"","sources":["../../src/commands/status.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,443 @@
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
+ import { writeFile, readFile, mkdtemp, rm } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { tmpdir } from 'node:os';
5
+ import { Command } from 'commander';
6
+ import { registerStatus } from './status.js';
7
+ describe('ft status', () => {
8
+ let testDir;
9
+ let originalCwd;
10
+ let originalFetch;
11
+ beforeEach(async () => {
12
+ // Create a temporary directory for each test
13
+ testDir = await mkdtemp(join(tmpdir(), 'ft-status-test-'));
14
+ originalCwd = process.cwd();
15
+ process.chdir(testDir);
16
+ // Mock TOGETHER_API_KEY
17
+ process.env.TOGETHER_API_KEY = 'test-api-key';
18
+ // Mock fetch
19
+ originalFetch = globalThis.fetch;
20
+ });
21
+ afterEach(async () => {
22
+ process.chdir(originalCwd);
23
+ await rm(testDir, { recursive: true, force: true });
24
+ vi.restoreAllMocks();
25
+ globalThis.fetch = originalFetch;
26
+ delete process.env.TOGETHER_API_KEY;
27
+ });
28
+ it('should show latest job status by default', async () => {
29
+ // Create config with one job
30
+ const config = {
31
+ name: 'test-project',
32
+ provider: 'together',
33
+ model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo',
34
+ qualityThreshold: 8,
35
+ runs: [
36
+ {
37
+ jobId: 'ft-job-123',
38
+ provider: 'together',
39
+ startedAt: '2025-01-01T00:00:00.000Z',
40
+ status: 'pending',
41
+ hyperparameters: {
42
+ epochs: 3,
43
+ batchSize: 4,
44
+ learningRate: 1e-5,
45
+ loraR: 16,
46
+ loraAlpha: 32,
47
+ },
48
+ },
49
+ ],
50
+ };
51
+ await writeFile('.ftpipeline.json', JSON.stringify(config, null, 2));
52
+ // Mock API response for running job
53
+ globalThis.fetch = vi.fn(async (url) => {
54
+ const urlString = typeof url === 'string' ? url : url.toString();
55
+ if (urlString.includes('/fine-tunes/ft-job-123')) {
56
+ return {
57
+ ok: true,
58
+ json: async () => ({
59
+ id: 'ft-job-123',
60
+ status: 'running',
61
+ }),
62
+ text: async () => '',
63
+ };
64
+ }
65
+ throw new Error(`Unexpected fetch call: ${urlString}`);
66
+ });
67
+ const consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
68
+ const program = new Command();
69
+ registerStatus(program);
70
+ await program.parseAsync(['node', 'test', 'status']);
71
+ // Verify API was called
72
+ expect(globalThis.fetch).toHaveBeenCalledWith(expect.stringContaining('/fine-tunes/ft-job-123'), expect.any(Object));
73
+ // Verify output shows the job
74
+ const logOutput = consoleLogSpy.mock.calls.map((call) => call.join(' ')).join('\n');
75
+ expect(logOutput).toContain('Latest Training Job');
76
+ expect(logOutput).toContain('ft-job-123');
77
+ expect(logOutput).toContain('running');
78
+ // Verify config was updated with new status
79
+ const configContent = await readFile('.ftpipeline.json', 'utf-8');
80
+ const updatedConfig = JSON.parse(configContent);
81
+ expect(updatedConfig.runs[0].status).toBe('running');
82
+ consoleLogSpy.mockRestore();
83
+ });
84
+ it('should show all jobs with --all flag', async () => {
85
+ // Create config with multiple jobs
86
+ const config = {
87
+ name: 'test-project',
88
+ provider: 'together',
89
+ model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo',
90
+ qualityThreshold: 8,
91
+ runs: [
92
+ {
93
+ jobId: 'ft-job-001',
94
+ provider: 'together',
95
+ startedAt: '2025-01-01T00:00:00.000Z',
96
+ status: 'completed',
97
+ modelId: 'model-001',
98
+ hyperparameters: {
99
+ epochs: 3,
100
+ batchSize: 4,
101
+ learningRate: 1e-5,
102
+ loraR: 16,
103
+ loraAlpha: 32,
104
+ },
105
+ },
106
+ {
107
+ jobId: 'ft-job-002',
108
+ provider: 'together',
109
+ startedAt: '2025-01-02T00:00:00.000Z',
110
+ status: 'running',
111
+ hyperparameters: {
112
+ epochs: 5,
113
+ batchSize: 8,
114
+ learningRate: 2e-5,
115
+ loraR: 32,
116
+ loraAlpha: 64,
117
+ },
118
+ },
119
+ ],
120
+ };
121
+ await writeFile('.ftpipeline.json', JSON.stringify(config, null, 2));
122
+ // Mock API responses for both jobs
123
+ globalThis.fetch = vi.fn(async (url) => {
124
+ const urlString = typeof url === 'string' ? url : url.toString();
125
+ if (urlString.includes('/fine-tunes/ft-job-001')) {
126
+ return {
127
+ ok: true,
128
+ json: async () => ({
129
+ id: 'ft-job-001',
130
+ status: 'succeeded',
131
+ fine_tuned_model: 'model-001',
132
+ }),
133
+ text: async () => '',
134
+ };
135
+ }
136
+ if (urlString.includes('/fine-tunes/ft-job-002')) {
137
+ return {
138
+ ok: true,
139
+ json: async () => ({
140
+ id: 'ft-job-002',
141
+ status: 'running',
142
+ }),
143
+ text: async () => '',
144
+ };
145
+ }
146
+ throw new Error(`Unexpected fetch call: ${urlString}`);
147
+ });
148
+ const consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
149
+ const program = new Command();
150
+ registerStatus(program);
151
+ await program.parseAsync(['node', 'test', 'status', '--all']);
152
+ // Verify both APIs were called
153
+ expect(globalThis.fetch).toHaveBeenCalledTimes(2);
154
+ // Verify output shows both jobs
155
+ const logOutput = consoleLogSpy.mock.calls.map((call) => call.join(' ')).join('\n');
156
+ expect(logOutput).toContain('All Training Jobs');
157
+ expect(logOutput).toContain('ft-job-001');
158
+ expect(logOutput).toContain('ft-job-002');
159
+ expect(logOutput).toContain('model-001');
160
+ consoleLogSpy.mockRestore();
161
+ });
162
+ it('should update config when job completes', async () => {
163
+ // Create config with pending job
164
+ const config = {
165
+ name: 'test-project',
166
+ provider: 'together',
167
+ model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo',
168
+ qualityThreshold: 8,
169
+ runs: [
170
+ {
171
+ jobId: 'ft-job-123',
172
+ provider: 'together',
173
+ startedAt: '2025-01-01T00:00:00.000Z',
174
+ status: 'running',
175
+ },
176
+ ],
177
+ };
178
+ await writeFile('.ftpipeline.json', JSON.stringify(config, null, 2));
179
+ // Mock API response for completed job
180
+ globalThis.fetch = vi.fn(async (url) => {
181
+ const urlString = typeof url === 'string' ? url : url.toString();
182
+ if (urlString.includes('/fine-tunes/ft-job-123')) {
183
+ return {
184
+ ok: true,
185
+ json: async () => ({
186
+ id: 'ft-job-123',
187
+ status: 'succeeded',
188
+ fine_tuned_model: 'model-abc-123',
189
+ }),
190
+ text: async () => '',
191
+ };
192
+ }
193
+ throw new Error(`Unexpected fetch call: ${urlString}`);
194
+ });
195
+ const consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
196
+ const program = new Command();
197
+ registerStatus(program);
198
+ await program.parseAsync(['node', 'test', 'status']);
199
+ // Verify config was updated with completed status and model ID
200
+ const configContent = await readFile('.ftpipeline.json', 'utf-8');
201
+ const updatedConfig = JSON.parse(configContent);
202
+ expect(updatedConfig.runs[0].status).toBe('completed');
203
+ expect(updatedConfig.runs[0].modelId).toBe('model-abc-123');
204
+ // Verify output shows next steps for completed job
205
+ const logOutput = consoleLogSpy.mock.calls.map((call) => call.join(' ')).join('\n');
206
+ expect(logOutput).toContain('completed');
207
+ expect(logOutput).toContain('model-abc-123');
208
+ expect(logOutput).toContain('ft eval');
209
+ consoleLogSpy.mockRestore();
210
+ });
211
+ it('should handle failed jobs', async () => {
212
+ // Create config with running job
213
+ const config = {
214
+ name: 'test-project',
215
+ provider: 'together',
216
+ model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo',
217
+ qualityThreshold: 8,
218
+ runs: [
219
+ {
220
+ jobId: 'ft-job-fail',
221
+ provider: 'together',
222
+ startedAt: '2025-01-01T00:00:00.000Z',
223
+ status: 'running',
224
+ },
225
+ ],
226
+ };
227
+ await writeFile('.ftpipeline.json', JSON.stringify(config, null, 2));
228
+ // Mock API response for failed job
229
+ globalThis.fetch = vi.fn(async (url) => {
230
+ const urlString = typeof url === 'string' ? url : url.toString();
231
+ if (urlString.includes('/fine-tunes/ft-job-fail')) {
232
+ return {
233
+ ok: true,
234
+ json: async () => ({
235
+ id: 'ft-job-fail',
236
+ status: 'failed',
237
+ error: 'Insufficient training data',
238
+ }),
239
+ text: async () => '',
240
+ };
241
+ }
242
+ throw new Error(`Unexpected fetch call: ${urlString}`);
243
+ });
244
+ const consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
245
+ const program = new Command();
246
+ registerStatus(program);
247
+ await program.parseAsync(['node', 'test', 'status']);
248
+ // Verify output shows error
249
+ const logOutput = consoleLogSpy.mock.calls.map((call) => call.join(' ')).join('\n');
250
+ expect(logOutput).toContain('failed');
251
+ expect(logOutput).toContain('Insufficient training data');
252
+ // Verify config was updated
253
+ const configContent = await readFile('.ftpipeline.json', 'utf-8');
254
+ const updatedConfig = JSON.parse(configContent);
255
+ expect(updatedConfig.runs[0].status).toBe('failed');
256
+ consoleLogSpy.mockRestore();
257
+ });
258
+ it('should handle no jobs scenario', async () => {
259
+ // Create config with no runs
260
+ const config = {
261
+ name: 'test-project',
262
+ provider: 'together',
263
+ model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo',
264
+ qualityThreshold: 8,
265
+ runs: [],
266
+ };
267
+ await writeFile('.ftpipeline.json', JSON.stringify(config, null, 2));
268
+ const consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
269
+ const program = new Command();
270
+ registerStatus(program);
271
+ await program.parseAsync(['node', 'test', 'status']);
272
+ // Verify output shows no jobs message
273
+ const logOutput = consoleLogSpy.mock.calls.map((call) => call.join(' ')).join('\n');
274
+ expect(logOutput).toContain('No Training Jobs Found');
275
+ expect(logOutput).toContain('ft train');
276
+ consoleLogSpy.mockRestore();
277
+ });
278
+ it('should fail if project not initialized', async () => {
279
+ const mockExit = vi.spyOn(process, 'exit').mockImplementation(() => {
280
+ throw new Error('process.exit called');
281
+ });
282
+ const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
283
+ const program = new Command();
284
+ registerStatus(program);
285
+ await expect(program.parseAsync(['node', 'test', 'status'])).rejects.toThrow('process.exit called');
286
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Project not initialized'));
287
+ mockExit.mockRestore();
288
+ consoleErrorSpy.mockRestore();
289
+ });
290
+ it('should handle API errors gracefully', async () => {
291
+ // Create config with one job
292
+ const config = {
293
+ name: 'test-project',
294
+ provider: 'together',
295
+ model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo',
296
+ qualityThreshold: 8,
297
+ runs: [
298
+ {
299
+ jobId: 'ft-job-123',
300
+ provider: 'together',
301
+ startedAt: '2025-01-01T00:00:00.000Z',
302
+ status: 'pending',
303
+ },
304
+ ],
305
+ };
306
+ await writeFile('.ftpipeline.json', JSON.stringify(config, null, 2));
307
+ // Mock API error
308
+ globalThis.fetch = vi.fn(async () => {
309
+ return {
310
+ ok: false,
311
+ text: async () => 'Job not found',
312
+ };
313
+ });
314
+ const mockExit = vi.spyOn(process, 'exit').mockImplementation(() => {
315
+ throw new Error('process.exit called');
316
+ });
317
+ const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
318
+ const program = new Command();
319
+ registerStatus(program);
320
+ await expect(program.parseAsync(['node', 'test', 'status'])).rejects.toThrow('process.exit called');
321
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Failed to get job status'));
322
+ mockExit.mockRestore();
323
+ consoleErrorSpy.mockRestore();
324
+ });
325
+ it('should handle cancelled jobs', async () => {
326
+ // Create config with cancelled job
327
+ const config = {
328
+ name: 'test-project',
329
+ provider: 'together',
330
+ model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo',
331
+ qualityThreshold: 8,
332
+ runs: [
333
+ {
334
+ jobId: 'ft-job-cancelled',
335
+ provider: 'together',
336
+ startedAt: '2025-01-01T00:00:00.000Z',
337
+ status: 'running',
338
+ },
339
+ ],
340
+ };
341
+ await writeFile('.ftpipeline.json', JSON.stringify(config, null, 2));
342
+ // Mock API response for cancelled job
343
+ globalThis.fetch = vi.fn(async (url) => {
344
+ const urlString = typeof url === 'string' ? url : url.toString();
345
+ if (urlString.includes('/fine-tunes/ft-job-cancelled')) {
346
+ return {
347
+ ok: true,
348
+ json: async () => ({
349
+ id: 'ft-job-cancelled',
350
+ status: 'cancelled',
351
+ }),
352
+ text: async () => '',
353
+ };
354
+ }
355
+ throw new Error(`Unexpected fetch call: ${urlString}`);
356
+ });
357
+ const consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
358
+ const program = new Command();
359
+ registerStatus(program);
360
+ await program.parseAsync(['node', 'test', 'status']);
361
+ // Verify output shows cancelled status
362
+ const logOutput = consoleLogSpy.mock.calls.map((call) => call.join(' ')).join('\n');
363
+ expect(logOutput).toContain('cancelled');
364
+ // Verify config was updated
365
+ const configContent = await readFile('.ftpipeline.json', 'utf-8');
366
+ const updatedConfig = JSON.parse(configContent);
367
+ expect(updatedConfig.runs[0].status).toBe('cancelled');
368
+ consoleLogSpy.mockRestore();
369
+ });
370
+ it('should not update config if status has not changed', async () => {
371
+ // Create config with running job
372
+ const config = {
373
+ name: 'test-project',
374
+ provider: 'together',
375
+ model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo',
376
+ qualityThreshold: 8,
377
+ runs: [
378
+ {
379
+ jobId: 'ft-job-123',
380
+ provider: 'together',
381
+ startedAt: '2025-01-01T00:00:00.000Z',
382
+ status: 'running',
383
+ },
384
+ ],
385
+ };
386
+ await writeFile('.ftpipeline.json', JSON.stringify(config, null, 2));
387
+ // Store original modification time
388
+ const originalContent = await readFile('.ftpipeline.json', 'utf-8');
389
+ // Mock API response with same status
390
+ globalThis.fetch = vi.fn(async (url) => {
391
+ const urlString = typeof url === 'string' ? url : url.toString();
392
+ if (urlString.includes('/fine-tunes/ft-job-123')) {
393
+ return {
394
+ ok: true,
395
+ json: async () => ({
396
+ id: 'ft-job-123',
397
+ status: 'running',
398
+ }),
399
+ text: async () => '',
400
+ };
401
+ }
402
+ throw new Error(`Unexpected fetch call: ${urlString}`);
403
+ });
404
+ const consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
405
+ const program = new Command();
406
+ registerStatus(program);
407
+ await program.parseAsync(['node', 'test', 'status']);
408
+ // Verify config content is unchanged
409
+ const newContent = await readFile('.ftpipeline.json', 'utf-8');
410
+ expect(newContent).toBe(originalContent);
411
+ consoleLogSpy.mockRestore();
412
+ });
413
+ it('should fail if API key not set', async () => {
414
+ delete process.env.TOGETHER_API_KEY;
415
+ // Create config with one job
416
+ const config = {
417
+ name: 'test-project',
418
+ provider: 'together',
419
+ model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo',
420
+ qualityThreshold: 8,
421
+ runs: [
422
+ {
423
+ jobId: 'ft-job-123',
424
+ provider: 'together',
425
+ startedAt: '2025-01-01T00:00:00.000Z',
426
+ status: 'pending',
427
+ },
428
+ ],
429
+ };
430
+ await writeFile('.ftpipeline.json', JSON.stringify(config, null, 2));
431
+ const mockExit = vi.spyOn(process, 'exit').mockImplementation(() => {
432
+ throw new Error('process.exit called');
433
+ });
434
+ const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
435
+ const program = new Command();
436
+ registerStatus(program);
437
+ await expect(program.parseAsync(['node', 'test', 'status'])).rejects.toThrow('process.exit called');
438
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('TOGETHER_API_KEY environment variable is required'));
439
+ mockExit.mockRestore();
440
+ consoleErrorSpy.mockRestore();
441
+ });
442
+ });
443
+ //# sourceMappingURL=status.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.test.js","sourceRoot":"","sources":["../../src/commands/status.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerTrain(program: Command): void;
3
+ //# sourceMappingURL=train.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"train.d.ts","sourceRoot":"","sources":["../../src/commands/train.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBzC,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiBpD"}
@@ -0,0 +1,139 @@
1
+ import { access, stat } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { loadConfig, saveConfig } from '../storage/config.js';
4
+ import { TogetherProvider } from '../providers/together.js';
5
+ const CONFIG_FILE = '.ftpipeline.json';
6
+ const TRAIN_FILE = 'data/train.jsonl';
7
+ const VAL_FILE = 'data/val.jsonl';
8
+ export function registerTrain(program) {
9
+ program
10
+ .command('train')
11
+ .description('Start a fine-tuning job')
12
+ .option('--epochs <n>', 'Number of training epochs', '3')
13
+ .option('--batch-size <n>', 'Batch size', '4')
14
+ .option('--learning-rate <rate>', 'Learning rate', '1e-5')
15
+ .option('--lora-r <rank>', 'LoRA rank', '16')
16
+ .option('--lora-alpha <alpha>', 'LoRA alpha', '32')
17
+ .action(async (options) => {
18
+ try {
19
+ await trainCommand(options);
20
+ }
21
+ catch (error) {
22
+ console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
23
+ process.exit(1);
24
+ }
25
+ });
26
+ }
27
+ async function trainCommand(options) {
28
+ const cwd = process.cwd();
29
+ // Check if project is initialized
30
+ try {
31
+ await access(join(cwd, CONFIG_FILE));
32
+ }
33
+ catch {
34
+ throw new Error('Project not initialized. Run `ft init` first to create .ftpipeline.json');
35
+ }
36
+ // Load config
37
+ const config = await loadConfig(cwd);
38
+ // Check for training file
39
+ const trainPath = join(cwd, TRAIN_FILE);
40
+ try {
41
+ await access(trainPath);
42
+ }
43
+ catch {
44
+ throw new Error('Training file not found. Run `ft format` first to generate data/train.jsonl');
45
+ }
46
+ // Check for validation file (optional but recommended)
47
+ const valPath = join(cwd, VAL_FILE);
48
+ let hasValidationFile = false;
49
+ try {
50
+ const valStat = await stat(valPath);
51
+ hasValidationFile = valStat.size > 0;
52
+ }
53
+ catch {
54
+ // Validation file is optional
55
+ hasValidationFile = false;
56
+ }
57
+ // Initialize provider based on config
58
+ let provider;
59
+ if (config.provider === 'together') {
60
+ provider = new TogetherProvider();
61
+ }
62
+ else {
63
+ throw new Error(`Provider "${config.provider}" not yet supported. Use "together" for now.`);
64
+ }
65
+ console.log('\n' + '═'.repeat(70));
66
+ console.log('Starting Fine-Tuning Job');
67
+ console.log('═'.repeat(70));
68
+ console.log(`\nProvider: ${config.provider}`);
69
+ console.log(`Base model: ${config.model}`);
70
+ // Parse hyperparameters
71
+ const epochs = options.epochs ? parseInt(options.epochs, 10) : 3;
72
+ const batchSize = options.batchSize ? parseInt(options.batchSize, 10) : 4;
73
+ const learningRate = options.learningRate ? parseFloat(options.learningRate) : 1e-5;
74
+ const loraR = options.loraR ? parseInt(options.loraR, 10) : 16;
75
+ const loraAlpha = options.loraAlpha ? parseInt(options.loraAlpha, 10) : 32;
76
+ console.log('\nHyperparameters:');
77
+ console.log('━'.repeat(70));
78
+ console.log(`Epochs: ${epochs}`);
79
+ console.log(`Batch size: ${batchSize}`);
80
+ console.log(`Learning rate: ${learningRate}`);
81
+ console.log(`LoRA rank: ${loraR}`);
82
+ console.log(`LoRA alpha: ${loraAlpha}`);
83
+ // Upload training file
84
+ console.log('\nUploading training file...');
85
+ const trainingFileId = await provider.uploadTrainingFile(trainPath);
86
+ console.log(`Training file uploaded: ${trainingFileId}`);
87
+ // Upload validation file if it exists
88
+ let validationFileId;
89
+ if (hasValidationFile) {
90
+ console.log('Uploading validation file...');
91
+ validationFileId = await provider.uploadTrainingFile(valPath);
92
+ console.log(`Validation file uploaded: ${validationFileId}`);
93
+ }
94
+ else {
95
+ console.log('No validation file found (skipping)');
96
+ }
97
+ // Create fine-tune job
98
+ console.log('\nCreating fine-tune job...');
99
+ const jobId = await provider.createFineTuneJob({
100
+ model: config.model,
101
+ trainingFile: trainingFileId,
102
+ validationFile: validationFileId,
103
+ epochs,
104
+ batchSize,
105
+ learningRate,
106
+ loraR,
107
+ loraAlpha,
108
+ });
109
+ console.log(`Job created: ${jobId}`);
110
+ // Save job info to config
111
+ const jobInfo = {
112
+ jobId,
113
+ provider: config.provider,
114
+ startedAt: new Date().toISOString(),
115
+ status: 'pending',
116
+ hyperparameters: {
117
+ epochs,
118
+ batchSize,
119
+ learningRate,
120
+ loraR,
121
+ loraAlpha,
122
+ },
123
+ };
124
+ config.runs.push(jobInfo);
125
+ await saveConfig(config, cwd);
126
+ // Display next steps
127
+ console.log('\n' + '═'.repeat(70));
128
+ console.log('Job Started Successfully');
129
+ console.log('═'.repeat(70));
130
+ console.log(`\nJob ID: ${jobId}`);
131
+ console.log(`Status: pending`);
132
+ console.log('\nNext Steps:');
133
+ console.log('━'.repeat(70));
134
+ console.log('1. Monitor progress: ft status');
135
+ console.log('2. Check all runs: ft status --all');
136
+ console.log('3. After completion, run evaluations: ft eval');
137
+ console.log('═'.repeat(70) + '\n');
138
+ }
139
+ //# sourceMappingURL=train.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"train.js","sourceRoot":"","sources":["../../src/commands/train.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=train.test.d.ts.map