# How the Provider Registry Resolves Model References in DeepSeek-Reasonix

> Discover how DeepSeek-Reasonix resolves model references using its three-step Config.ResolveModel algorithm. Learn to scan configurations and get immutable ProviderEntry objects for instantiation.

- Repository: [YHH/DeepSeek-Reasonix](https://github.com/esengine/DeepSeek-Reasonix)
- Tags: internals
- Published: 2026-08-08

---

**DeepSeek-Reasonix resolves model references through a three-step algorithm in `Config.ResolveModel` that handles full provider/model paths, provider-only strings, and bare model names by scanning the configuration catalog and returning an immutable `ProviderEntry` ready for instantiation.**

The DeepSeek-Reasonix provider registry serves as the central authority for translating user-supplied model references into concrete provider configurations. When you specify a model like `deepseek/deepseek-v4-pro`, `deepseek`, or just `deepseek-v4-pro`, the system must locate the correct endpoint configuration and determine which specific model variant to use. This resolution process, implemented in [`internal/config/config.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/config/config.go), ensures that every reference maps to a valid `ProviderEntry` that the runtime can instantiate through the provider factory.

## The Three-Step Resolution Algorithm

The resolution logic lives in `Config.ResolveModel` at [[`internal/config/config.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/config/config.go) lines 33-77](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/config/config.go#L33-L77). The algorithm processes input strings in strict priority order, attempting three distinct matching strategies before returning the result.

### Step 1: Full Provider/Model References

When the input contains a forward slash (`/`), the system interprets it as a `provider/model` pattern. The implementation uses `strings.Cut` to split the string into provider name and model name components.

- The provider name is validated against `c.Provider` (the configured provider catalog)
- The model name is checked via `e.HasModel` to confirm the provider supports that specific model
- If both conditions pass, the function returns a copy of the `ProviderEntry` with the `Model` field explicitly set to the requested model name

This pattern allows precise selection of models across different vendors, such as `deepseek/deepseek-v4-pro` or `openai/gpt-4`.

### Step 2: Provider-Only References

If the input contains no slash, the algorithm treats it as a provider name lookup. The system searches the configuration for a provider matching the exact string.

When found, the entry's **default model** is automatically selected via `e.DefaultModel()`. This enables shorthand references where users specify just `deepseek` and receive the provider's configured default (for example, `deepseek-v4-flash`).

### Step 3: Bare Model Names

For inputs that match neither previous pattern, the system performs a catalog scan across all configured providers. The algorithm iterates through the provider list and selects the first provider where `HasModel(ref)` returns true.

Upon finding a match:
- The provider entry is copied
- The entry's `Model` field is set to the bare model name provided by the user
- The entry's `Name` field retains the provider that owns the model

This fallback mechanism allows users to reference models without knowing which provider hosts them, such as specifying `deepseek-v4-pro` without the `deepseek/` prefix.

## ProviderEntry Construction and Immutability

The `ResolveModel` function guarantees configuration immutability by returning a **copy** of the stored `ProviderEntry` rather than a pointer to the original configuration. This prevents runtime mutations from affecting the global configuration state.

Before returning the entry, the system applies model-specific overrides:

- `applyModelPrice` updates pricing information based on the resolved model
- `applyModelOverride` applies any model-specific configuration overrides defined in the config

If the reference cannot be resolved through any of the three steps, `ResolveModel` returns `nil, false` (as implemented at [lines 78-79](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/config/config.go#L78-L79)).

## The Provider Factory Integration

While `Config.ResolveModel` handles the reference-to-entry mapping, the actual provider instantiation occurs through the provider registry in [[`internal/provider/provider.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/provider/provider.go)](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/provider/provider.go).

The registry maintains a mapping from **provider kind** (such as `"openai"` or `"deepseek"`) to factory functions that create concrete implementations. Each provider sub-package registers itself via an `init()` function, ensuring that `NewProvider(entry)` can instantiate the correct backend once `ResolveModel` has populated the `Model` field.

```go
// Example: Resolving and instantiating a provider
entry, ok := cfg.ResolveModel("deepseek/deepseek-v4-pro")
if ok {
    // entry.Model is now "deepseek-v4-pro"
    // entry.Name remains "deepseek"
    prov, err := provider.NewProvider(entry)
    // prov is now a concrete DeepSeek provider ready for API calls
}

```

## Higher-Level Resolution Helpers

The base `ResolveModel` function powers several convenience methods that implement fallback strategies for specific use cases:

- **`ResolveModelWithFallback`**: Attempts primary resolution, then falls back to a default provider if the reference is empty or unresolvable
- **`ResolveNewSessionChatModel`**: Specialized resolution for new chat sessions that applies session-specific defaults

These helpers are wired into the system through the `ProviderResolver` interface, which merges static configuration with extension sidecars during the boot process ([[`internal/boot/boot.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/boot/boot.go)](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/boot/boot.go)). The controller ([[`internal/control/controller.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/control/controller.go)](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/control/controller.go)) exposes this resolver to the rest of the runtime for processing turns that require model inference.

## Summary

- **Three-step resolution** handles `provider/model`, `provider`, and bare model patterns in strict priority order
- **Immutability guarantee** ensures `ResolveModel` returns copies of `ProviderEntry` objects, protecting the global configuration
- **Automatic defaults** select the provider's default model when only a provider name is specified
- **Catalog scanning** enables bare model references by searching across all configured providers
- **Factory integration** connects resolved entries to concrete provider implementations via the registry in [`internal/provider/provider.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/provider/provider.go)

## Frequently Asked Questions

### What happens if I specify a model that doesn't exist in the provider catalog?

`ResolveModel` returns `nil, false` when no match is found through any of the three resolution steps. Higher-level helpers like `ResolveModelWithFallback` typically catch this condition and substitute a configured default provider instead.

### Can I use the same model name across different providers?

Yes. The resolution algorithm prioritizes the `provider/model` syntax to disambiguate conflicts. When using bare model names (Step 3), the first provider in the configuration listing that model wins, making provider order significant for ambiguous references.

### How does the system handle pricing configuration for specific models?

After resolving the entry, `ResolveModel` invokes `applyModelPrice` to attach model-specific pricing data from the configuration. This ensures that cost calculations reflect the actual model being used, even when the reference was resolved through a provider-only or bare-model pattern.

### Where is the provider registry initialized?

The registry map is populated during package initialization via `init()` functions in each provider sub-package (such as the OpenAI or DeepSeek implementations). This registration pattern ensures that `NewProvider` in [`internal/provider/provider.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/provider/provider.go) can instantiate any supported backend without explicit imports in the configuration layer.