Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions cmd/pnf/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ func tuiCmd(args []string) {
listener.Close()

// Start local server in background, with web UI so 'o' can open it in a browser
srv, err := server.New(*logdir, web.DistFS())
srv, err := server.New(*logdir, web.DistFS(), "", "")
if err != nil {
fmt.Fprintf(os.Stderr, "Error creating server: %v\n", err)
os.Exit(1)
Expand Down Expand Up @@ -420,8 +420,17 @@ func serveCmd(args []string) {
port := fs.Int("port", 6767, "Port to listen on")
host := fs.String("host", "localhost", "Host to bind to")
openBrowser := fs.Bool("open", true, "Open browser automatically")
remoteURL := fs.String("url", "", "Remote API base URL (fallback: P95_URL)")
apiKey := fs.String("api-key", "", "Remote API key (fallback: P95_API_KEY)")
fs.Parse(args)

if *remoteURL == "" {
*remoteURL = os.Getenv("P95_URL")
}
if *apiKey == "" {
*apiKey = os.Getenv("P95_API_KEY")
}

if *logdir == "" {
*logdir = defaultLogDir()
}
Expand All @@ -436,7 +445,7 @@ func serveCmd(args []string) {
webFS := web.DistFS()

// Create server
srv, err := server.New(*logdir, webFS)
srv, err := server.New(*logdir, webFS, *remoteURL, *apiKey)
if err != nil {
log.Fatalf("Failed to create server: %v", err)
}
Expand Down
55 changes: 55 additions & 0 deletions internal/domain/sweep.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package domain

import "time"

// SweepStatus represents the status of a hyperparameter sweep
type SweepStatus string

const (
SweepStatusRunning SweepStatus = "running"
SweepStatusCompleted SweepStatus = "completed"
SweepStatusFailed SweepStatus = "failed"
SweepStatusStopped SweepStatus = "stopped"
)

// ParameterSpec defines a hyperparameter search space
type ParameterSpec struct {
Name string `json:"name"`
Type string `json:"type"` // uniform, log_uniform, int, categorical
Min *float64 `json:"min,omitempty"`
Max *float64 `json:"max,omitempty"`
Values []any `json:"values,omitempty"`
}

// SearchSpace contains the hyperparameter search space
type SearchSpace struct {
Parameters []ParameterSpec `json:"parameters"`
}

// EarlyStoppingConfig configures early stopping for a sweep
type EarlyStoppingConfig struct {
Method string `json:"method"`
MinSteps int `json:"min_steps"`
Warmup int `json:"warmup"`
}

// Sweep represents a hyperparameter sweep
type Sweep struct {
ID string `json:"id"`
Name string `json:"name"`
Status SweepStatus `json:"status"`
Method string `json:"method"` // random, grid
MetricName string `json:"metric_name"`
MetricGoal string `json:"metric_goal"` // minimize, maximize
SearchSpace SearchSpace `json:"search_space"`
Config map[string]any `json:"config,omitempty"`
MaxRuns *int `json:"max_runs,omitempty"`
EarlyStopping *EarlyStoppingConfig `json:"early_stopping,omitempty"`
BestRunID *string `json:"best_run_id,omitempty"`
BestValue *float64 `json:"best_value,omitempty"`
RunCount int `json:"run_count"`
GridIndex int `json:"grid_index"`
StartedAt time.Time `json:"started_at"`
EndedAt *time.Time `json:"ended_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
Loading
Loading