ollama source for Momentry Core verification

This commit is contained in:
Accusys
2026-05-22 17:19:10 +08:00
commit 0b31ff9135
2020 changed files with 1413145 additions and 0 deletions

View File

@@ -0,0 +1,307 @@
package manifest
import (
"encoding/binary"
"encoding/json"
"fmt"
"io"
"os"
"path/filepath"
"sort"
"strings"
"github.com/ollama/ollama/envconfig"
)
// ManifestLayer represents a layer in the manifest.
type ManifestLayer struct {
MediaType string `json:"mediaType"`
Digest string `json:"digest"`
Size int64 `json:"size"`
Name string `json:"name,omitempty"` // Path-style name: "component/tensor" or "path/to/config.json"
}
// Manifest represents the manifest JSON structure.
type Manifest struct {
SchemaVersion int `json:"schemaVersion"`
MediaType string `json:"mediaType"`
Config ManifestLayer `json:"config"`
Layers []ManifestLayer `json:"layers"`
}
// ModelManifest holds a parsed manifest with helper methods.
type ModelManifest struct {
Manifest *Manifest
BlobDir string
}
func DefaultBlobDir() string {
return filepath.Join(envconfig.Models(), "blobs")
}
// DefaultManifestDir returns the manifest storage directory.
// Respects OLLAMA_MODELS.
func DefaultManifestDir() string {
return filepath.Join(envconfig.Models(), "manifests")
}
// LoadManifest loads a manifest for the given model name.
// Model name format: "modelname" or "modelname:tag" or "host/namespace/name:tag"
func LoadManifest(modelName string) (*ModelManifest, error) {
manifestPath := resolveManifestPath(modelName)
data, err := os.ReadFile(manifestPath)
if err != nil {
return nil, fmt.Errorf("read manifest: %w", err)
}
var manifest Manifest
if err := json.Unmarshal(data, &manifest); err != nil {
return nil, fmt.Errorf("parse manifest: %w", err)
}
return &ModelManifest{
Manifest: &manifest,
BlobDir: DefaultBlobDir(),
}, nil
}
// resolveManifestPath converts a model name to a manifest file path.
func resolveManifestPath(modelName string) string {
// Parse model name into components
// Default: registry.ollama.ai/library/<name>/<tag>
host := "registry.ollama.ai"
namespace := "library"
name := modelName
tag := "latest"
// Handle explicit tag
if idx := strings.LastIndex(name, ":"); idx != -1 {
tag = name[idx+1:]
name = name[:idx]
}
// Handle full path like "host/namespace/name"
parts := strings.Split(name, "/")
switch len(parts) {
case 3:
host = parts[0]
namespace = parts[1]
name = parts[2]
case 2:
namespace = parts[0]
name = parts[1]
}
return filepath.Join(DefaultManifestDir(), host, namespace, name, tag)
}
// BlobPath returns the full path to a blob given its digest.
func (m *ModelManifest) BlobPath(digest string) string {
// Convert "sha256:abc123" to "sha256-abc123"
blobName := strings.Replace(digest, ":", "-", 1)
return filepath.Join(m.BlobDir, blobName)
}
// GetTensorLayers returns tensor layers, optionally filtered by component.
// If component is empty, returns all tensor layers (for LLM models).
// If component is specified (e.g., "text_encoder", "transformer", "vae"),
// returns only layers with that prefix.
func (m *ModelManifest) GetTensorLayers(component string) []ManifestLayer {
var layers []ManifestLayer
for _, layer := range m.Manifest.Layers {
if layer.MediaType != "application/vnd.ollama.image.tensor" {
continue
}
if component == "" || strings.HasPrefix(layer.Name, component+"/") {
layers = append(layers, layer)
}
}
return layers
}
// GetConfigLayer returns the config layer for a given path.
func (m *ModelManifest) GetConfigLayer(configPath string) *ManifestLayer {
for _, layer := range m.Manifest.Layers {
if layer.MediaType == "application/vnd.ollama.image.json" && layer.Name == configPath {
return &layer
}
}
return nil
}
// ReadConfig reads and returns the content of a config file.
func (m *ModelManifest) ReadConfig(configPath string) ([]byte, error) {
layer := m.GetConfigLayer(configPath)
if layer == nil {
return nil, fmt.Errorf("config %q not found in manifest", configPath)
}
blobPath := m.BlobPath(layer.Digest)
return os.ReadFile(blobPath)
}
// ReadConfigJSON reads and unmarshals a config file.
func (m *ModelManifest) ReadConfigJSON(configPath string, v any) error {
data, err := m.ReadConfig(configPath)
if err != nil {
return err
}
return json.Unmarshal(data, v)
}
// OpenBlob opens a blob for reading.
func (m *ModelManifest) OpenBlob(digest string) (io.ReadCloser, error) {
return os.Open(m.BlobPath(digest))
}
// HasTensorLayers returns true if the manifest has any tensor layers.
func (m *ModelManifest) HasTensorLayers() bool {
for _, layer := range m.Manifest.Layers {
if layer.MediaType == "application/vnd.ollama.image.tensor" {
return true
}
}
return false
}
// TotalTensorSize returns the total size in bytes of all tensor layers.
func (m *ModelManifest) TotalTensorSize() int64 {
var total int64
for _, layer := range m.Manifest.Layers {
if layer.MediaType == "application/vnd.ollama.image.tensor" {
total += layer.Size
}
}
return total
}
// ModelInfo contains metadata about an image generation model.
type ModelInfo struct {
Architecture string
ParameterCount int64
Quantization string
}
// GetModelInfo returns metadata about an image generation model.
func GetModelInfo(modelName string) (*ModelInfo, error) {
manifest, err := LoadManifest(modelName)
if err != nil {
return nil, fmt.Errorf("failed to load manifest: %w", err)
}
info := &ModelInfo{}
// Read model_index.json for architecture, parameter count, and quantization
if data, err := manifest.ReadConfig("model_index.json"); err == nil {
var index struct {
Architecture string `json:"architecture"`
ParameterCount int64 `json:"parameter_count"`
Quantization string `json:"quantization"`
}
if json.Unmarshal(data, &index) == nil {
info.Architecture = index.Architecture
info.ParameterCount = index.ParameterCount
info.Quantization = index.Quantization
}
}
// Fallback: detect quantization from first tensor blob's __metadata__
if info.Quantization == "" {
info.Quantization = detectQuantizationFromBlobs(manifest)
}
if info.Quantization == "" {
info.Quantization = "BF16"
}
// Fallback: estimate parameter count if not in config
if info.ParameterCount == 0 {
var totalSize int64
for _, layer := range manifest.Manifest.Layers {
if layer.MediaType == "application/vnd.ollama.image.tensor" {
totalSize += layer.Size
}
}
// Assume BF16 (2 bytes/param) as rough estimate
info.ParameterCount = totalSize / 2
}
return info, nil
}
// detectQuantizationFromBlobs reads __metadata__ from the first tensor blob
// to detect quantization type.
func detectQuantizationFromBlobs(manifest *ModelManifest) string {
for _, layer := range manifest.Manifest.Layers {
if layer.MediaType != "application/vnd.ollama.image.tensor" {
continue
}
data, err := readBlobHeader(manifest.BlobPath(layer.Digest))
if err != nil {
continue
}
var header map[string]json.RawMessage
if json.Unmarshal(data, &header) != nil {
continue
}
if metaRaw, ok := header["__metadata__"]; ok {
var meta map[string]string
if json.Unmarshal(metaRaw, &meta) == nil {
if qt, ok := meta["quant_type"]; ok && qt != "" {
return strings.ToUpper(qt)
}
}
}
// Only check the first tensor blob
break
}
return ""
}
// ParseBlobTensorNames reads a safetensors blob and returns all "main" tensor names.
// Filters out __metadata__, .scale, and .bias entries to return only primary weight tensors.
func ParseBlobTensorNames(path string) ([]string, error) {
data, err := readBlobHeader(path)
if err != nil {
return nil, err
}
var header map[string]json.RawMessage
if err := json.Unmarshal(data, &header); err != nil {
return nil, err
}
var names []string
for k := range header {
if k == "__metadata__" || strings.HasSuffix(k, ".scale") || strings.HasSuffix(k, ".bias") {
continue
}
names = append(names, k)
}
sort.Strings(names)
return names, nil
}
// readBlobHeader reads the JSON header bytes from a safetensors blob file.
func readBlobHeader(path string) ([]byte, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
var headerSize uint64
if err := binary.Read(f, binary.LittleEndian, &headerSize); err != nil {
return nil, err
}
if headerSize > 1024*1024 {
return nil, fmt.Errorf("header too large: %d", headerSize)
}
data := make([]byte, headerSize)
if _, err := io.ReadFull(f, data); err != nil {
return nil, err
}
return data, nil
}

View File

@@ -0,0 +1,57 @@
package manifest
import (
"path/filepath"
"testing"
)
func TestTotalTensorSize(t *testing.T) {
m := &ModelManifest{
Manifest: &Manifest{
Layers: []ManifestLayer{
{MediaType: "application/vnd.ollama.image.tensor", Size: 1000},
{MediaType: "application/vnd.ollama.image.tensor", Size: 2000},
{MediaType: "application/vnd.ollama.image.json", Size: 500}, // not a tensor
{MediaType: "application/vnd.ollama.image.tensor", Size: 3000},
},
},
}
got := m.TotalTensorSize()
want := int64(6000)
if got != want {
t.Errorf("TotalTensorSize() = %d, want %d", got, want)
}
}
func TestTotalTensorSizeEmpty(t *testing.T) {
m := &ModelManifest{
Manifest: &Manifest{
Layers: []ManifestLayer{},
},
}
if got := m.TotalTensorSize(); got != 0 {
t.Errorf("TotalTensorSize() = %d, want 0", got)
}
}
func TestManifestAndBlobDirsRespectOLLAMAModels(t *testing.T) {
modelsDir := filepath.Join(t.TempDir(), "models")
// Simulate packaged/systemd environment
t.Setenv("OLLAMA_MODELS", modelsDir)
t.Setenv("HOME", "/usr/share/ollama")
// Manifest dir must respect OLLAMA_MODELS
wantManifest := filepath.Join(modelsDir, "manifests")
if got := DefaultManifestDir(); got != wantManifest {
t.Fatalf("DefaultManifestDir() = %q, want %q", got, wantManifest)
}
// Blob dir must respect OLLAMA_MODELS
wantBlobs := filepath.Join(modelsDir, "blobs")
if got := DefaultBlobDir(); got != wantBlobs {
t.Fatalf("DefaultBlobDir() = %q, want %q", got, wantBlobs)
}
}

View File

@@ -0,0 +1,296 @@
package manifest
import (
"fmt"
"sort"
"strconv"
"strings"
"github.com/ollama/ollama/x/imagegen/mlx"
)
// ManifestWeights provides fast weight loading from tensor blobs.
// Uses native mmap loading with synthetic safetensors headers for zero-copy.
type ManifestWeights struct {
manifest *ModelManifest
component string
tensors map[string]ManifestLayer // name -> layer
cache map[string]*mlx.Array // name -> loaded array
nativeCache []*mlx.SafetensorsFile // keep native handles alive
quantType string // quantization type from blob metadata (e.g., "int4", "int8")
groupSize int // quantization group size from blob metadata
}
// LoadWeightsFromManifest creates a weight loader from manifest storage.
// If component is empty, loads all tensors (for LLM models).
// If component is specified, loads only tensors for that component and strips the prefix.
func LoadWeightsFromManifest(manifest *ModelManifest, component string) (*ManifestWeights, error) {
layers := manifest.GetTensorLayers(component)
if len(layers) == 0 {
if component == "" {
return nil, fmt.Errorf("no tensor layers found in manifest")
}
return nil, fmt.Errorf("no tensor layers found for component %q", component)
}
// Strip component prefix from tensor names for model loading
// e.g., "text_encoder/model.embed_tokens.weight" -> "model.embed_tokens.weight"
tensors := make(map[string]ManifestLayer, len(layers))
for _, layer := range layers {
if component == "" {
tensors[layer.Name] = layer
} else {
tensorName := strings.TrimPrefix(layer.Name, component+"/")
tensors[tensorName] = layer
}
}
return &ManifestWeights{
manifest: manifest,
component: component,
tensors: tensors,
cache: make(map[string]*mlx.Array),
}, nil
}
// Load loads all tensor blobs using native mmap (zero-copy).
// Blobs are stored in safetensors format for native mlx_load_safetensors mmap.
// Combined quantized blobs contain tensors keyed by name, name+".scale", and optional name+".bias"
// with quantization metadata. Scale and bias are stored in cache as name+"_scale"
// and name+"_qbias" for compatibility with downstream loading code.
// Packed blobs (e.g., for expert groups) contain multiple tensors; the manifest name
// is a group prefix and individual tensors are loaded by their actual names from the blob.
// If dtype is non-zero, non-quantized tensors are converted to the specified dtype.
func (mw *ManifestWeights) Load(dtype mlx.Dtype) error {
// Track native handles to free after batch eval
nativeHandles := make([]*mlx.SafetensorsFile, 0, len(mw.tensors))
arrays := make([]*mlx.Array, 0, len(mw.tensors))
// Group tensors by digest to avoid loading the same blob multiple times
type blobEntry struct {
name string
layer ManifestLayer
}
blobGroups := make(map[string][]blobEntry)
for name, layer := range mw.tensors {
blobGroups[layer.Digest] = append(blobGroups[layer.Digest], blobEntry{name, layer})
}
for digest, entries := range blobGroups {
path := mw.manifest.BlobPath(digest)
// Load blob as safetensors (native mmap, zero-copy)
sf, err := mlx.LoadSafetensorsNative(path)
if err != nil {
for _, h := range nativeHandles {
h.Free()
}
return fmt.Errorf("load %s: %w", entries[0].name, err)
}
nativeHandles = append(nativeHandles, sf)
// Read quantization metadata from blob
if qt := sf.GetMetadata("quant_type"); qt != "" && mw.quantType == "" {
mw.quantType = qt
if gs := sf.GetMetadata("group_size"); gs != "" {
mw.groupSize, _ = strconv.Atoi(gs)
}
}
for _, entry := range entries {
name := entry.name
// Try to get tensor by stripped name first, then with component prefix,
// then fall back to "data" for legacy blobs created by older versions
// that stored all tensors with the generic key "data".
lookupName := name
arr := sf.Get(lookupName)
if arr == nil && mw.component != "" {
lookupName = mw.component + "/" + name
arr = sf.Get(lookupName)
}
if arr == nil {
// Legacy blob format: tensor stored as "data"
lookupName = "data"
arr = sf.Get(lookupName)
}
if arr != nil {
// Single-tensor blob or tensor found by name
if dtype != 0 && arr.Dtype() != dtype {
arr = mlx.AsType(arr, dtype)
}
arr = mlx.Contiguous(arr)
mw.cache[name] = arr
arrays = append(arrays, arr)
// Check for scale tensor
if scale := sf.Get(lookupName + ".scale"); scale != nil {
scale = mlx.Contiguous(scale)
mw.cache[name+"_scale"] = scale
arrays = append(arrays, scale)
}
// Check for bias tensor
if bias := sf.Get(lookupName + ".bias"); bias != nil {
bias = mlx.Contiguous(bias)
mw.cache[name+"_qbias"] = bias
arrays = append(arrays, bias)
}
} else {
// Packed blob: manifest name is a group prefix, not a tensor name.
// Load all individual tensors from the blob.
tensorNames, err := ParseBlobTensorNames(path)
if err != nil {
for _, h := range nativeHandles {
h.Free()
}
return fmt.Errorf("parse packed blob for %s: %w", name, err)
}
for _, tensorName := range tensorNames {
tArr := sf.Get(tensorName)
if tArr == nil {
continue
}
if dtype != 0 && tArr.Dtype() != dtype {
tArr = mlx.AsType(tArr, dtype)
}
tArr = mlx.Contiguous(tArr)
// Strip component prefix from blob-internal names so cache keys
// match the stripped names used by LoadModule.
cacheName := tensorName
if mw.component != "" {
cacheName = strings.TrimPrefix(tensorName, mw.component+"/")
}
mw.cache[cacheName] = tArr
arrays = append(arrays, tArr)
// Check for scale tensor
if scale := sf.Get(tensorName + ".scale"); scale != nil {
scale = mlx.Contiguous(scale)
mw.cache[cacheName+"_scale"] = scale
arrays = append(arrays, scale)
}
// Check for bias tensor
if bias := sf.Get(tensorName + ".bias"); bias != nil {
bias = mlx.Contiguous(bias)
mw.cache[cacheName+"_qbias"] = bias
arrays = append(arrays, bias)
}
}
}
}
}
// Batch evaluate all tensors at once (much faster than one at a time)
mlx.Eval(arrays...)
// Now safe to free all native handles
for _, sf := range nativeHandles {
sf.Free()
}
return nil
}
// GetTensor returns a tensor from cache. Call Load() first.
func (mw *ManifestWeights) GetTensor(name string) (*mlx.Array, error) {
if mw.cache == nil {
return nil, fmt.Errorf("cache not initialized: call Load() first")
}
arr, ok := mw.cache[name]
if !ok {
return nil, fmt.Errorf("tensor %q not found", name)
}
return arr, nil
}
// ListTensors returns all tensor names in sorted order.
// Includes both manifest tensor names and scale/bias entries from combined blobs.
func (mw *ManifestWeights) ListTensors() []string {
seen := make(map[string]bool, len(mw.tensors)+len(mw.cache))
for name := range mw.tensors {
seen[name] = true
}
// Also include cache entries (scale/bias from combined blobs)
for name := range mw.cache {
seen[name] = true
}
names := make([]string, 0, len(seen))
for name := range seen {
names = append(names, name)
}
sort.Strings(names)
return names
}
// HasTensor checks if a tensor exists in the manifest or cache.
func (mw *ManifestWeights) HasTensor(name string) bool {
if _, ok := mw.tensors[name]; ok {
return true
}
// Also check cache for scale/bias entries from combined blobs
if _, ok := mw.cache[name]; ok {
return true
}
return false
}
// Quantization returns the model's quantization type.
// Returns the quant_type from blob metadata (e.g., "int4", "int8", "nvfp4", "mxfp8").
// Returns empty string if not quantized.
// Falls back to model_index.json for image gen models.
func (mw *ManifestWeights) Quantization() string {
if mw.quantType != "" {
return strings.ToUpper(mw.quantType)
}
if mw.manifest == nil {
return ""
}
// Fallback: read from model_index.json (for image gen models)
var index struct {
Quantization string `json:"quantization"`
}
if err := mw.manifest.ReadConfigJSON("model_index.json", &index); err == nil && index.Quantization != "" {
return index.Quantization
}
return ""
}
// GroupSize returns the quantization group size.
// Returns the group_size from blob metadata.
// Returns 0 if not specified (caller should use default based on quantization type).
func (mw *ManifestWeights) GroupSize() int {
if mw.groupSize > 0 {
return mw.groupSize
}
if mw.manifest == nil {
return 0
}
// Fallback: read from model_index.json (for image gen models)
var index struct {
GroupSize int `json:"group_size"`
}
if err := mw.manifest.ReadConfigJSON("model_index.json", &index); err == nil && index.GroupSize > 0 {
return index.GroupSize
}
return 0
}
// ReleaseAll frees all native handles and clears the tensor cache.
func (mw *ManifestWeights) ReleaseAll() {
for _, sf := range mw.nativeCache {
sf.Free()
}
mw.nativeCache = nil
mw.cache = nil
}