mirror of
https://github.com/Warky-Devs/vecna.git
synced 2026-05-05 01:26:58 +00:00
feat(onboard): add interactive extra maps configuration step
This commit is contained in:
@@ -34,7 +34,7 @@ func runOnboard(_ *cobra.Command, _ []string) error {
|
|||||||
|
|
||||||
// ── Step 1: Discover ──────────────────────────────────────────────────────
|
// ── Step 1: Discover ──────────────────────────────────────────────────────
|
||||||
|
|
||||||
step(1, 5, "Discover embedding servers")
|
step(1, 6, "Discover embedding servers")
|
||||||
|
|
||||||
fmt.Println("Scanning (Ollama, LM Studio, vLLM, LocalAI, Jan, Kobold, Tabby)...")
|
fmt.Println("Scanning (Ollama, LM Studio, vLLM, LocalAI, Jan, Kobold, Tabby)...")
|
||||||
servers := discovery.Scan(context.Background())
|
servers := discovery.Scan(context.Background())
|
||||||
@@ -89,7 +89,7 @@ func runOnboard(_ *cobra.Command, _ []string) error {
|
|||||||
|
|
||||||
// ── Step 2: Detect dimensions ─────────────────────────────────────────────
|
// ── Step 2: Detect dimensions ─────────────────────────────────────────────
|
||||||
|
|
||||||
step(2, 5, "Detect model dimensions")
|
step(2, 6, "Detect model dimensions")
|
||||||
|
|
||||||
for i := range targets {
|
for i := range targets {
|
||||||
fmt.Printf("Probing %s / %s ... ", targets[i].endpoint, targets[i].model)
|
fmt.Printf("Probing %s / %s ... ", targets[i].endpoint, targets[i].model)
|
||||||
@@ -106,7 +106,7 @@ func runOnboard(_ *cobra.Command, _ []string) error {
|
|||||||
|
|
||||||
// ── Step 3: Configure adapter ─────────────────────────────────────────────
|
// ── Step 3: Configure adapter ─────────────────────────────────────────────
|
||||||
|
|
||||||
step(3, 5, "Configure dimension adapter")
|
step(3, 6, "Configure dimension adapter")
|
||||||
|
|
||||||
// Use the first target's detected dim as the source dimension default
|
// Use the first target's detected dim as the source dimension default
|
||||||
firstDim := 0
|
firstDim := 0
|
||||||
@@ -156,7 +156,7 @@ func runOnboard(_ *cobra.Command, _ []string) error {
|
|||||||
|
|
||||||
// ── Step 4: Configure vecna server ────────────────────────────────────────
|
// ── Step 4: Configure vecna server ────────────────────────────────────────
|
||||||
|
|
||||||
step(4, 5, "Configure vecna server")
|
step(4, 6, "Configure vecna server")
|
||||||
|
|
||||||
portRaw, err := promptString(in, "Bind port [8080]: ", "8080")
|
portRaw, err := promptString(in, "Bind port [8080]: ", "8080")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -189,9 +189,44 @@ func runOnboard(_ *cobra.Command, _ []string) error {
|
|||||||
}
|
}
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|
||||||
// ── Step 5: Test & write ──────────────────────────────────────────────────
|
// ── Step 5: Extra maps ────────────────────────────────────────────────────
|
||||||
|
|
||||||
step(5, 5, "Test connections and write config")
|
step(5, 6, "Configure extra maps (optional)")
|
||||||
|
|
||||||
|
extraMaps := map[string]config.ExtraMapConfig{}
|
||||||
|
|
||||||
|
addMaps, err := promptBool(in, "Add extra dimension maps (/map/{key}/v1/embeddings)?", false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if addMaps {
|
||||||
|
// Build the list of target names from the already-collected targets.
|
||||||
|
targetNames := make([]string, 0, len(targets))
|
||||||
|
for _, t := range targets {
|
||||||
|
targetNames = append(targetNames, t.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
mc, mapErr := collectExtraMap(in, sourceDim, targetDim, adapterType, truncateMode, padMode, targetNames)
|
||||||
|
if mapErr != nil {
|
||||||
|
return mapErr
|
||||||
|
}
|
||||||
|
extraMaps[mc.key] = mc.cfg
|
||||||
|
|
||||||
|
another, promptErr := promptBool(in, "Add another extra map?", false)
|
||||||
|
if promptErr != nil {
|
||||||
|
return promptErr
|
||||||
|
}
|
||||||
|
if !another {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
// ── Step 6: Test & write ──────────────────────────────────────────────────
|
||||||
|
|
||||||
|
step(6, 6, "Test connections and write config")
|
||||||
|
|
||||||
allPassed := true
|
allPassed := true
|
||||||
for _, t := range targets {
|
for _, t := range targets {
|
||||||
@@ -260,6 +295,7 @@ func runOnboard(_ *cobra.Command, _ []string) error {
|
|||||||
TruncateMode: truncateMode,
|
TruncateMode: truncateMode,
|
||||||
PadMode: padMode,
|
PadMode: padMode,
|
||||||
},
|
},
|
||||||
|
ExtraMaps: extraMaps,
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultCfgPath := config.ResolveFile(cfgFile)
|
defaultCfgPath := config.ResolveFile(cfgFile)
|
||||||
@@ -467,6 +503,103 @@ func mustParseInt(s string, fallback int) int {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pendingExtraMap pairs the map key with its collected config.
|
||||||
|
type pendingExtraMap struct {
|
||||||
|
key string
|
||||||
|
cfg config.ExtraMapConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// collectExtraMap interactively collects one extra_map entry.
|
||||||
|
// Global adapter values are shown as defaults; the user may override any field.
|
||||||
|
func collectExtraMap(
|
||||||
|
in *bufio.Reader,
|
||||||
|
globalSourceDim, globalTargetDim int,
|
||||||
|
globalAdapterType, globalTruncateMode, globalPadMode string,
|
||||||
|
targetNames []string,
|
||||||
|
) (pendingExtraMap, error) {
|
||||||
|
key, err := promptString(in, "Map key (used in URL path, e.g. \"512\"): ", "")
|
||||||
|
if err != nil || key == "" {
|
||||||
|
return pendingExtraMap{}, fmt.Errorf("map key is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
mc := config.ExtraMapConfig{}
|
||||||
|
|
||||||
|
// Target dimension (required — always shown)
|
||||||
|
targetDimRaw, err := promptString(in,
|
||||||
|
fmt.Sprintf("Target dimension [%d]: ", globalTargetDim), fmt.Sprintf("%d", globalTargetDim))
|
||||||
|
if err != nil {
|
||||||
|
return pendingExtraMap{}, err
|
||||||
|
}
|
||||||
|
mc.TargetDim = mustParseInt(targetDimRaw, globalTargetDim)
|
||||||
|
|
||||||
|
// Forward target override
|
||||||
|
if len(targetNames) > 0 {
|
||||||
|
fmt.Println("Available forward targets: " + strings.Join(targetNames, ", "))
|
||||||
|
ftRaw, err := promptString(in, "Forward target override (leave empty to use global default): ", "")
|
||||||
|
if err != nil {
|
||||||
|
return pendingExtraMap{}, err
|
||||||
|
}
|
||||||
|
mc.ForwardTarget = strings.TrimSpace(ftRaw)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adapter type override
|
||||||
|
adapterTypeRaw, err := promptString(in,
|
||||||
|
fmt.Sprintf("Adapter type override (truncate/random/projection) [%s]: ", globalAdapterType), globalAdapterType)
|
||||||
|
if err != nil {
|
||||||
|
return pendingExtraMap{}, err
|
||||||
|
}
|
||||||
|
if adapterTypeRaw != globalAdapterType {
|
||||||
|
mc.Type = adapterTypeRaw
|
||||||
|
}
|
||||||
|
effectiveType := coalesce(mc.Type, globalAdapterType)
|
||||||
|
|
||||||
|
// Source dim override
|
||||||
|
sourceDimRaw, err := promptString(in,
|
||||||
|
fmt.Sprintf("Source dimension override (leave empty to use global %d): ", globalSourceDim), "")
|
||||||
|
if err != nil {
|
||||||
|
return pendingExtraMap{}, err
|
||||||
|
}
|
||||||
|
if sourceDimRaw != "" {
|
||||||
|
mc.SourceDim = mustParseInt(sourceDimRaw, globalSourceDim)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Truncate/pad mode overrides — only for truncate type
|
||||||
|
if effectiveType == "truncate" {
|
||||||
|
tmRaw, err := promptString(in,
|
||||||
|
fmt.Sprintf("Truncate mode override (from_end/from_start) [%s]: ", globalTruncateMode), globalTruncateMode)
|
||||||
|
if err != nil {
|
||||||
|
return pendingExtraMap{}, err
|
||||||
|
}
|
||||||
|
if tmRaw != globalTruncateMode {
|
||||||
|
mc.TruncateMode = tmRaw
|
||||||
|
}
|
||||||
|
|
||||||
|
pmRaw, err := promptString(in,
|
||||||
|
fmt.Sprintf("Pad mode override (at_end/at_start) [%s]: ", globalPadMode), globalPadMode)
|
||||||
|
if err != nil {
|
||||||
|
return pendingExtraMap{}, err
|
||||||
|
}
|
||||||
|
if pmRaw != globalPadMode {
|
||||||
|
mc.PadMode = pmRaw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seed — only for random type
|
||||||
|
if effectiveType == "random" {
|
||||||
|
seedRaw, err := promptString(in, "Seed (0 = time-based): ", "0")
|
||||||
|
if err != nil {
|
||||||
|
return pendingExtraMap{}, err
|
||||||
|
}
|
||||||
|
var seed int64
|
||||||
|
if _, err := fmt.Sscanf(seedRaw, "%d", &seed); err != nil {
|
||||||
|
seed = 0
|
||||||
|
}
|
||||||
|
mc.Seed = seed
|
||||||
|
}
|
||||||
|
|
||||||
|
return pendingExtraMap{key: key, cfg: mc}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func writeFullConfig(path string, cfg config.Config) error {
|
func writeFullConfig(path string, cfg config.Config) error {
|
||||||
// If file already exists, preserve any targets not touched by onboard
|
// If file already exists, preserve any targets not touched by onboard
|
||||||
// by using SaveTarget for each new target; otherwise write the whole file.
|
// by using SaveTarget for each new target; otherwise write the whole file.
|
||||||
|
|||||||
Reference in New Issue
Block a user