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

96 lines
3.1 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
// Package backend defines a pluggable inference-engine interface used by the
// miner. Backends translate miner task inputs into model outputs; this package
// deliberately imports nothing outside the stdlib so adapters (llama.cpp,
// vllm, ollama, remote OpenAI-compatible endpoints, etc.) can be dropped in
// without bloating the miner binary.
//
// The interface is intentionally minimal — it mirrors what the miner actually
// does in runInference, runChat, and runEmbedding.
package backend
import "context"
// Message is a single chat turn. Shape matches OpenAI chat messages and the
// miner's internal message type.
type Message struct {
Role string `json:"role"`
Content string `json:"content"`
}
// ChatRequest is a multi-turn chat prompt.
type ChatRequest struct {
Model string `json:"model"`
Messages []Message `json:"messages"`
MaxTokens int `json:"max_tokens,omitempty"`
}
// ChatResponse is the assistant's reply.
type ChatResponse struct {
Role string `json:"role"`
Content string `json:"content"`
Model string `json:"model"`
Tokens int `json:"tokens,omitempty"`
}
// InferenceRequest is a single-prompt completion request.
type InferenceRequest struct {
Model string `json:"model"`
Prompt string `json:"prompt"`
MaxTokens int `json:"max_tokens,omitempty"`
}
// InferenceResponse is the completion output.
type InferenceResponse struct {
Text string `json:"text"`
Tokens int `json:"tokens"`
Model string `json:"model"`
}
// EmbedRequest asks for a vector embedding of a piece of text.
type EmbedRequest struct {
Model string `json:"model"`
Text string `json:"text"`
}
// EmbedResponse carries the embedding vector.
type EmbedResponse struct {
Embedding []float64 `json:"embedding"`
Model string `json:"model"`
}
// Capabilities reports what a backend can do. Consumers use this to pick a
// backend or to skip tasks a backend cannot serve.
type Capabilities struct {
Chat bool `json:"chat"`
Inference bool `json:"inference"`
Embedding bool `json:"embedding"`
// EmbeddingDims, when non-zero, declares a fixed output dimensionality for
// embeddings; 0 means the backend decides per-request.
EmbeddingDims int `json:"embedding_dims,omitempty"`
}
// InferenceBackend is the pluggable compute layer for the miner.
//
// Implementations must be safe for concurrent use — the miner's task worker
// pool may invoke any method from multiple goroutines.
type InferenceBackend interface {
// Name returns a short identifier ("noop", "openai", ...). Used in logs
// and config matching.
Name() string
// Capabilities reports what this backend supports.
Capabilities() Capabilities
// Chat runs a multi-turn chat completion.
Chat(ctx context.Context, req ChatRequest) (ChatResponse, error)
// Inference runs a single-prompt completion.
Inference(ctx context.Context, req InferenceRequest) (InferenceResponse, error)
// Embed produces an embedding vector for the given text.
Embed(ctx context.Context, req EmbedRequest) (EmbedResponse, error)
}