@@ -36,14 +36,6 @@ func newOperationCommand() *cobra.Command {
3636 return cmd
3737}
3838
39- // formatFineTunedModel returns the model name or "NA" if blank
40- func formatFineTunedModel (model string ) string {
41- if model == "" {
42- return "NA"
43- }
44- return model
45- }
46-
4739func newOperationSubmitCommand () * cobra.Command {
4840 var filename string
4941 var model string
@@ -154,10 +146,12 @@ func newOperationSubmitCommand() *cobra.Command {
154146// newOperationShowCommand creates a command to show the fine-tuning job details
155147func newOperationShowCommand () * cobra.Command {
156148 var jobID string
149+ var logs bool
150+ var output string
157151
158152 cmd := & cobra.Command {
159153 Use : "show" ,
160- Short : "Show fine-tuning job details ." ,
154+ Short : "Shows detailed information about a specific job ." ,
161155 RunE : func (cmd * cobra.Command , args []string ) error {
162156 ctx := azdext .WithAccessToken (cmd .Context ())
163157 azdClient , err := azdext .NewAzdClient ()
@@ -168,7 +162,7 @@ func newOperationShowCommand() *cobra.Command {
168162
169163 // Show spinner while fetching job
170164 spinner := ux .NewSpinner (& ux.SpinnerOptions {
171- Text : fmt . Sprintf ( "Fetching fine-tuning job %s..." , jobID ) ,
165+ Text : "Fine-Tuning Job Details" ,
172166 })
173167 if err := spinner .Start (ctx ); err != nil {
174168 fmt .Printf ("failed to start spinner: %v\n " , err )
@@ -177,106 +171,73 @@ func newOperationShowCommand() *cobra.Command {
177171 fineTuneSvc , err := services .NewFineTuningService (ctx , azdClient , nil )
178172 if err != nil {
179173 _ = spinner .Stop (ctx )
180- fmt .Println ( )
174+ fmt .Print ( " \n \n " )
181175 return err
182176 }
183177
184178 job , err := fineTuneSvc .GetFineTuningJobDetails (ctx , jobID )
185179 _ = spinner .Stop (ctx )
180+ fmt .Print ("\n \n " )
186181 if err != nil {
187- fmt .Println ()
188182 return err
189183 }
190184
191- // Display job details
192- color .Green ("\n Fine-tuning Job Details\n " )
193- fmt .Printf ("Job ID: %s\n " , job .ID )
194- fmt .Printf ("Status: %s %s\n " , utils .GetStatusSymbol (job .Status ), job .Status )
195- fmt .Printf ("Model: %s\n " , job .Model )
196- fmt .Printf ("Fine-tuned Model: %s\n " , formatFineTunedModel (job .FineTunedModel ))
197- fmt .Printf ("Created At: %s\n " , utils .FormatTime (job .CreatedAt ))
198- if ! job .FinishedAt .IsZero () {
199- fmt .Printf ("Finished At: %s\n " , utils .FormatTime (job .FinishedAt ))
200- }
201- fmt .Printf ("Method: %s\n " , job .Method )
202- fmt .Printf ("Training File: %s\n " , job .TrainingFile )
203- if job .ValidationFile != "" {
204- fmt .Printf ("Validation File: %s\n " , job .ValidationFile )
185+ switch output {
186+ case "json" :
187+ utils .PrintObject (job , utils .FormatJSON )
188+ case "yaml" :
189+ utils .PrintObject (job , utils .FormatYAML )
190+ case "table" , "" :
191+ views := job .ToDetailViews ()
192+ indent := " "
193+ utils .PrintObjectWithIndent (views .Details , utils .FormatTable , indent )
194+
195+ fmt .Println ("\n Timestamps:" )
196+ utils .PrintObjectWithIndent (views .Timestamps , utils .FormatTable , indent )
197+ fmt .Println ("\n Configuration:" )
198+ utils .PrintObjectWithIndent (views .Configuration , utils .FormatTable , indent )
199+
200+ fmt .Println ("\n Data:" )
201+ utils .PrintObjectWithIndent (views .Data , utils .FormatTable , indent )
202+ default :
203+ return fmt .Errorf ("unsupported output format: %s (supported: table, json, yaml)" , output )
205204 }
206205
207- // Print hyperparameters if available
208- if job .Hyperparameters != nil {
209- fmt .Println ("\n Hyperparameters:" )
210- fmt .Printf (" Batch Size: %d\n " , job .Hyperparameters .BatchSize )
211- fmt .Printf (" Learning Rate Multiplier: %f\n " , job .Hyperparameters .LearningRateMultiplier )
212- fmt .Printf (" N Epochs: %d\n " , job .Hyperparameters .NEpochs )
213- }
214-
215- // Fetch and print events
216- eventsSpinner := ux .NewSpinner (& ux.SpinnerOptions {
217- Text : "Fetching job events..." ,
218- })
219- if err := eventsSpinner .Start (ctx ); err != nil {
220- fmt .Printf ("failed to start spinner: %v\n " , err )
221- }
222-
223- events , err := fineTuneSvc .GetJobEvents (ctx , jobID )
224- _ = eventsSpinner .Stop (ctx )
225-
226- if err != nil {
206+ if logs {
227207 fmt .Println ()
228- return err
229- } else if events != nil && len (events .Data ) > 0 {
230- fmt .Println ("\n Job Events:" )
231- for i , event := range events .Data {
232- fmt .Printf (" %d. Event ID: %s\n " , i + 1 , event .ID )
233- fmt .Printf (" [%s] %s - %s\n " , event .Level , utils .FormatTime (event .CreatedAt ), event .Message )
234- }
235- if events .HasMore {
236- fmt .Println (" ... (more events available)" )
237- }
238- }
239-
240- // Fetch and print checkpoints if job is completed
241- if job .Status == models .StatusSucceeded {
242- checkpointsSpinner := ux .NewSpinner (& ux.SpinnerOptions {
243- Text : "Fetching job checkpoints..." ,
208+ // Fetch and print events
209+ eventsSpinner := ux .NewSpinner (& ux.SpinnerOptions {
210+ Text : "Events:" ,
244211 })
245- if err := checkpointsSpinner .Start (ctx ); err != nil {
212+ if err := eventsSpinner .Start (ctx ); err != nil {
246213 fmt .Printf ("failed to start spinner: %v\n " , err )
247214 }
248215
249- checkpoints , err := fineTuneSvc .GetJobCheckpoints (ctx , jobID )
250- _ = checkpointsSpinner .Stop (ctx )
216+ events , err := fineTuneSvc .GetJobEvents (ctx , jobID )
217+ _ = eventsSpinner .Stop (ctx )
218+ fmt .Println ()
251219
252220 if err != nil {
253- fmt .Println ()
254221 return err
255- } else if checkpoints != nil && len (checkpoints .Data ) > 0 {
256- fmt .Println ("\n Job Checkpoints:" )
257- for i , checkpoint := range checkpoints .Data {
258- fmt .Printf (" %d. Checkpoint ID: %s\n " , i + 1 , checkpoint .ID )
259- fmt .Printf (" Checkpoint Name: %s\n " , checkpoint .FineTunedModelCheckpoint )
260- fmt .Printf (" Created On: %s\n " , utils .FormatTime (checkpoint .CreatedAt ))
261- fmt .Printf (" Step Number: %d\n " , checkpoint .StepNumber )
262- if checkpoint .Metrics != nil {
263- fmt .Printf (" Full Validation Loss: %.6f\n " , checkpoint .Metrics .FullValidLoss )
264- }
222+ } else if events != nil && len (events .Data ) > 0 {
223+ const eventIndent = " "
224+ for _ , event := range events .Data {
225+ fmt .Printf ("%s[%s] %s\n " , eventIndent , utils .FormatTime (event .CreatedAt ), event .Message )
265226 }
266- if checkpoints .HasMore {
267- fmt .Println (" ... (more checkpoints available)" )
227+ if events .HasMore {
228+ fmt .Println (" ... (more events available)" )
268229 }
269230 }
270231 }
271232
272- fmt .Println (strings .Repeat ("=" , 120 ))
273-
274233 return nil
275234 },
276235 }
277236
278- cmd .Flags ().StringVarP (& jobID , "job-id" , "i" , "" , "Fine-tuning job ID" )
279- cmd .MarkFlagRequired ("job-id" )
237+ cmd .Flags ().StringVarP (& jobID , "id" , "i" , "" , "Job ID" )
238+ cmd .Flags ().BoolVar (& logs , "logs" , false , "Include recent training logs" )
239+ cmd .Flags ().StringVarP (& output , "output" , "o" , "table" , "Output format: table, json, yaml" )
240+ cmd .MarkFlagRequired ("id" )
280241
281242 return cmd
282243}
@@ -285,6 +246,7 @@ func newOperationShowCommand() *cobra.Command {
285246func newOperationListCommand () * cobra.Command {
286247 var limit int
287248 var after string
249+ var output string
288250 cmd := & cobra.Command {
289251 Use : "list" ,
290252 Short : "List fine-tuning jobs." ,
@@ -298,7 +260,7 @@ func newOperationListCommand() *cobra.Command {
298260
299261 // Show spinner while fetching jobs
300262 spinner := ux .NewSpinner (& ux.SpinnerOptions {
301- Text : "Fetching fine-tuning jobs... " ,
263+ Text : "Fine-Tuning Jobs " ,
302264 })
303265 if err := spinner .Start (ctx ); err != nil {
304266 fmt .Printf ("failed to start spinner: %v\n " , err )
@@ -313,25 +275,26 @@ func newOperationListCommand() *cobra.Command {
313275
314276 jobs , err := fineTuneSvc .ListFineTuningJobs (ctx , limit , after )
315277 _ = spinner .Stop (ctx )
278+ fmt .Print ("\n \n " )
279+
316280 if err != nil {
317- fmt .Println ()
318281 return err
319282 }
320283
321- // Display job list
322- for i , job := range jobs {
323- fmt .Printf ("\n %d. Job ID: %s | Status: %s %s | Model: %s | Fine-tuned: %s | Created: %s" ,
324- i + 1 , job .ID , utils .GetStatusSymbol (job .Status ), job .Status , job .BaseModel ,
325- formatFineTunedModel (job .FineTunedModel ), utils .FormatTime (job .CreatedAt ))
284+ switch output {
285+ case "json" :
286+ utils .PrintObject (jobs , utils .FormatJSON )
287+ case "table" , "" :
288+ utils .PrintObject (jobs , utils .FormatTable )
289+ default :
290+ return fmt .Errorf ("unsupported output format: %s (supported: table, json)" , output )
326291 }
327-
328- fmt .Printf ("\n Total jobs: %d\n " , len (jobs ))
329-
330292 return nil
331293 },
332294 }
333295
334- cmd .Flags ().IntVarP (& limit , "top" , "t" , 50 , "Number of fine-tuning jobs to list" )
335- cmd .Flags ().StringVarP (& after , "after" , "a" , "" , "Cursor for pagination" )
296+ cmd .Flags ().IntVarP (& limit , "top" , "t" , 10 , "Number of jobs to return" )
297+ cmd .Flags ().StringVar (& after , "after" , "" , "Pagination cursor" )
298+ cmd .Flags ().StringVarP (& output , "output" , "o" , "table" , "Output format: table, json" )
336299 return cmd
337300}
0 commit comments