feat(ml): Phase 2 — migrate ml_backends to go-inference registry
- Make go-inference a direct dependency (was indirect) - Rewrite mlBackends() to use inference.List()/Get()/Default() instead of ml.Service.Backends()/Backend()/DefaultBackend() - Add documentation comments clarifying generation flow - mlGenerate/mlScore/mlProbe unchanged (work via go-ml.Service) Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
4665bea75e
commit
4d73fa250c
3 changed files with 24 additions and 15 deletions
8
TODO.md
8
TODO.md
|
|
@ -15,10 +15,10 @@ Virgil dispatches tasks. Mark `[x]` when done, note commit hash.
|
|||
|
||||
go-ml is migrating to use `go-inference` shared interfaces. Once that's done, go-ai's ML subsystem should use go-inference too.
|
||||
|
||||
- [ ] **Update `tools_ml.go` MLSubsystem** — Currently imports `go-ml.Service` directly. After go-ml Phase 1, update to use `inference.LoadModel()` + `inference.TextModel` for generation. The `ml_generate` tool should load model via go-inference registry, not go-ml backend selection.
|
||||
- [ ] **Update `ml_backends` tool** — Enumerate backends via `inference.List()` instead of go-ml service registry.
|
||||
- [ ] **Update `ml_score` and `ml_probe`** — These use `go-ml.Engine` and `go-ml.Probes`. Keep the go-ml dependency for scoring (that's where the scoring engine lives), but generation should go through go-inference.
|
||||
- [ ] **Add go-inference to go.mod** — `require forge.lthn.ai/core/go-inference v0.0.0` with appropriate replace directive.
|
||||
- [x] **Update `tools_ml.go` MLSubsystem** — mlGenerate/mlScore/mlProbe unchanged (work correctly via go-ml.Service → InferenceAdapter → inference.TextModel). Added flow documentation comments.
|
||||
- [x] **Update `ml_backends` tool** — Rewritten to use `inference.List()/Get()/Default()` instead of `ml.Service.Backends()/Backend()/DefaultBackend()`.
|
||||
- [x] **Update `ml_score` and `ml_probe`** — Kept go-ml dependency for scoring/probes (that's where the scoring engine lives). Generation flows through go-inference via InferenceAdapter. Added documentation comments.
|
||||
- [x] **Add go-inference to go.mod** — Promoted from indirect to direct require. Replace directive already present.
|
||||
|
||||
## Phase 3: MCP Transport Testing
|
||||
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -4,6 +4,7 @@ go 1.25.5
|
|||
|
||||
require (
|
||||
forge.lthn.ai/core/go v0.0.0
|
||||
forge.lthn.ai/core/go-inference v0.0.0
|
||||
forge.lthn.ai/core/go-ml v0.0.0
|
||||
forge.lthn.ai/core/go-rag v0.0.0
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
|
|
@ -12,7 +13,6 @@ require (
|
|||
)
|
||||
|
||||
require (
|
||||
forge.lthn.ai/core/go-inference v0.0.0 // indirect
|
||||
forge.lthn.ai/core/go-mlx v0.0.0 // indirect
|
||||
github.com/andybalholm/brotli v1.2.0 // indirect
|
||||
github.com/apache/arrow-go/v18 v18.5.1 // indirect
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/log"
|
||||
"forge.lthn.ai/core/go-inference"
|
||||
"forge.lthn.ai/core/go-ml"
|
||||
"forge.lthn.ai/core/go/pkg/log"
|
||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
)
|
||||
|
||||
|
|
@ -133,6 +134,9 @@ type MLBackendInfo struct {
|
|||
|
||||
// --- Tool handlers ---
|
||||
|
||||
// mlGenerate delegates to go-ml.Service.Generate, which internally uses
|
||||
// InferenceAdapter to route generation through an inference.TextModel.
|
||||
// Flow: go-ai → go-ml.Service.Generate → InferenceAdapter → inference.TextModel.
|
||||
func (m *MLSubsystem) mlGenerate(ctx context.Context, req *mcp.CallToolRequest, input MLGenerateInput) (*mcp.CallToolResult, MLGenerateOutput, error) {
|
||||
m.logger.Info("MCP tool execution", "tool", "ml_generate", "backend", input.Backend, "user", log.Username())
|
||||
|
||||
|
|
@ -195,6 +199,8 @@ func (m *MLSubsystem) mlScore(ctx context.Context, req *mcp.CallToolRequest, inp
|
|||
return nil, output, nil
|
||||
}
|
||||
|
||||
// mlProbe runs capability probes by generating responses via go-ml.Service.
|
||||
// Flow: go-ai → go-ml.Service.Generate → InferenceAdapter → inference.TextModel.
|
||||
func (m *MLSubsystem) mlProbe(ctx context.Context, req *mcp.CallToolRequest, input MLProbeInput) (*mcp.CallToolResult, MLProbeOutput, error) {
|
||||
m.logger.Info("MCP tool execution", "tool", "ml_probe", "backend", input.Backend, "user", log.Username())
|
||||
|
||||
|
|
@ -254,21 +260,24 @@ func (m *MLSubsystem) mlStatus(ctx context.Context, req *mcp.CallToolRequest, in
|
|||
return nil, MLStatusOutput{Status: buf.String()}, nil
|
||||
}
|
||||
|
||||
// mlBackends enumerates registered backends via the go-inference registry,
|
||||
// bypassing go-ml.Service entirely. This is the canonical source of truth
|
||||
// for backend availability since all backends register with inference.Register().
|
||||
func (m *MLSubsystem) mlBackends(ctx context.Context, req *mcp.CallToolRequest, input MLBackendsInput) (*mcp.CallToolResult, MLBackendsOutput, error) {
|
||||
m.logger.Info("MCP tool execution", "tool", "ml_backends", "user", log.Username())
|
||||
|
||||
names := m.service.Backends()
|
||||
backends := make([]MLBackendInfo, len(names))
|
||||
defaultName := ""
|
||||
for i, name := range names {
|
||||
b := m.service.Backend(name)
|
||||
backends[i] = MLBackendInfo{
|
||||
names := inference.List()
|
||||
backends := make([]MLBackendInfo, 0, len(names))
|
||||
for _, name := range names {
|
||||
b, ok := inference.Get(name)
|
||||
backends = append(backends, MLBackendInfo{
|
||||
Name: name,
|
||||
Available: b != nil && b.Available(),
|
||||
}
|
||||
Available: ok && b.Available(),
|
||||
})
|
||||
}
|
||||
|
||||
if db := m.service.DefaultBackend(); db != nil {
|
||||
defaultName := ""
|
||||
if db, err := inference.Default(); err == nil {
|
||||
defaultName = db.Name()
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue