Package: dappco.re/go/inference
File: go/dataset.go
The smallest pull-based dataset contract shared by training, evaluation, distillation, and reasoning rollouts. One sample at a time, optional reset. Every package agrees on this shape so a dataset assembled in eval/datapipe flows directly into a train/ loop without conversion.
type DatasetSample struct {
Text string // raw text (continuation pretraining)
Prompt string // user prompt (SFT, instruct)
Response string // assistant response (SFT target)
Reasoning string // chain-of-thought (GRPO, distillation)
Messages []Message // multi-turn conversation
Format string // source-corpus row shape it was normalised from
Labels map[string]string // routing / filtering metadata
}A sample carries whichever fields the task needs. SFT samples populate Prompt + Response. GRPO samples add Reasoning. Eval samples often only use Messages. Format records the source row shape ("text", "openai_messages", "sharegpt", "prompt_response", "alpaca", "reasoning") — stamped by train/dataset.LoadJSONL, empty for samples built directly.
type DatasetStream interface {
Next() (DatasetSample, bool, error)
}Next returns (sample, ok, err). ok=false + err=nil = end of stream. Errors are terminal — the caller stops consuming.
type DatasetResetter interface {
Reset() error
}Optional. Streams that wrap an in-memory list or a seekable file implement Reset so training loops can run multiple epochs. Streaming-only sources (HF datasets streaming mode) don't.
dataset.go no longer holds only the stream contract — it also carries the backend-neutral config + report DTOs the training and eval pipelines exchange (all plain JSON-tagged structs):
- Batching:
LossMask,Batch(token IDs + attention/loss masks + samples) - Evaluation:
EvalConfig,EvalMetrics,QualityProbe,QualityProbeResult,EvalReport, and theEvaluatorinterface (Evaluate(ctx, DatasetStream, EvalConfig) (*EvalReport, error)) - Benchmark:
BenchConfig,BenchReport - Memory planning:
MemoryPlan,ModelFitReport - Training:
TrainingConfig,TrainingMetrics,TrainingResult,DistillConfig(embedsTrainingConfig),GRPOConfig(embedsTrainingConfig)
These are wire-stable shapes; the loops that produce and consume them live in train/ and eval/.
The temptation is to have TrainingDataset, EvalDataset, DistillDataset — different shapes per task. We resist. A single DatasetStream.Next() → DatasetSample covers every task because DatasetSample is wide enough that each consumer reads the fields it cares about. New tasks add fields to DatasetSample without churning consumers.
train/dataset/— JSONL / corpus ingestion →DatasetStream(LoadJSONLstampsDatasetSample.Format)eval/datapipe/— evaluation data pipelines- test fixtures via in-memory slice wrappers
train/—sft.go(supervised fine-tuning),ssd.go(self-distillation),grpo/,distill/eval/— evaluation + benchmark runnersagent/— scoring/eval agent loop
- training.md —
TrainableModel; thetrain/pipelines drive it over aDatasetStream go/train/dataset/— the reference JSONL loader