Files
zeekay 6f13ef421a pkg/miner: pluggable inference-engine backend interface
Close three `// TODO: Integrate with actual ...` stubs in
pkg/miner/miner.go (runInference, runChat, runEmbedding) by introducing
a small pluggable backend interface. The miner now dispatches through
backend.InferenceBackend rather than inlining placeholder output.

Two reference backends ship in-tree:

- pkg/miner/backend/noop  โ€” deterministic mock, byte-for-byte identical
  to the pre-refactor inline stubs. Default. Zero config, zero deps.
- pkg/miner/backend/openai โ€” OpenAI-compatible HTTP adapter built on
  net/http. Covers llama.cpp, vllm, ollama, LocalAI, and api.openai.com
  via OPENAI_API_BASE. No new go.mod dependencies.

Config gains Backend / OpenAIBase / OpenAIAPIKey / OpenAIModel /
OpenAIEmbeddingModel fields. Unknown backend values fall back to noop so
operator typos don't crash-loop the miner. Existing miner_test.go passes
unchanged; DefaultConfig() behaviour is preserved.

Also wire a GPUStatsProvider hook on Miner so GetStats can surface
best-effort GPU telemetry (GPUUtilization, MemoryUsed) without pulling
NVML/MLX bindings into the main binary. Default is nil = no-op, matching
current behaviour; a follow-up PR will wire a real provider.

Closes luxfi/ai#1.

Contributed by kcolbchain (https://kcolbchain.com) ยท https://abhishekkrishna.com
2026-04-21 06:55:21 +05:30

87 lines
2.7 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
// Package noop provides a deterministic in-process InferenceBackend. It
// preserves the placeholder behaviour that was inlined into
// pkg/miner/miner.go before the backend interface landed, so existing tests
// and downstream consumers that rely on "some response comes back" keep
// working with zero configuration.
//
// This backend performs no real inference. Use it for local dev, CI, and as
// the safe default when an operator hasn't configured a real engine.
package noop
import (
"context"
"fmt"
"github.com/luxfi/ai/pkg/miner/backend"
)
// DefaultEmbeddingDims matches the placeholder dim used by the pre-refactor
// embedding stub in pkg/miner/miner.go (len(embedding) == 384).
const DefaultEmbeddingDims = 384
// Backend is a deterministic mock implementing backend.InferenceBackend.
type Backend struct {
// EmbeddingDims controls the length of the zero-vector returned by
// Embed. Defaults to DefaultEmbeddingDims when zero.
EmbeddingDims int
}
// New returns a new noop backend with default embedding dimensionality.
func New() *Backend {
return &Backend{EmbeddingDims: DefaultEmbeddingDims}
}
// Name implements backend.InferenceBackend.
func (*Backend) Name() string { return "noop" }
// Capabilities implements backend.InferenceBackend.
func (b *Backend) Capabilities() backend.Capabilities {
dims := b.EmbeddingDims
if dims == 0 {
dims = DefaultEmbeddingDims
}
return backend.Capabilities{
Chat: true,
Inference: true,
Embedding: true,
EmbeddingDims: dims,
}
}
// Chat returns a fixed assistant message. Identical to the string returned by
// the previous inline stub in miner.runChat.
func (b *Backend) Chat(_ context.Context, req backend.ChatRequest) (backend.ChatResponse, error) {
return backend.ChatResponse{
Role: "assistant",
Content: "I'm an AI assistant running on the Lux network.",
Model: req.Model,
}, nil
}
// Inference echoes the prompt, matching the previous inline stub in
// miner.runInference.
func (b *Backend) Inference(_ context.Context, req backend.InferenceRequest) (backend.InferenceResponse, error) {
return backend.InferenceResponse{
Text: fmt.Sprintf("Response to: %s", req.Prompt),
Tokens: 10,
Model: req.Model,
}, nil
}
// Embed returns a zero vector of EmbeddingDims length โ€” byte-for-byte identical
// to the pre-refactor miner.runEmbedding placeholder.
func (b *Backend) Embed(_ context.Context, req backend.EmbedRequest) (backend.EmbedResponse, error) {
dims := b.EmbeddingDims
if dims == 0 {
dims = DefaultEmbeddingDims
}
vec := make([]float64, dims)
return backend.EmbedResponse{
Embedding: vec,
Model: req.Model,
}, nil
}