# How Model Aliases Work in DS2API for OpenAI, Claude, and Gemini Compatibility

> Understand DS2API's model alias system for seamless OpenAI, Claude, and Gemini compatibility. Map provider models to DeepSeek IDs without payload changes.

- Repository: [CJACK./ds2api](https://github.com/CJackHwang/ds2api)
- Tags: internals
- Published: 2026-04-26

---

**DS2API uses a two-layer model alias system that maps OpenAI, Claude, and Gemini model names to native DeepSeek model IDs, allowing seamless cross-provider compatibility without changing request payloads.**

The **model aliases** in DS2API enable the API gateway to accept requests using external provider naming conventions while routing everything to a DeepSeek backend. This architecture decouples the consumer-facing model identifiers from the actual inference engine, supporting runtime customization through configuration overlays.

## The Model Alias Architecture

DS2API implements alias resolution through a hierarchical lookup system defined in [`internal/config/models.go`](https://github.com/CJackHwang/ds2api/blob/main/internal/config/models.go). The design separates static defaults from dynamic runtime overrides, ensuring that operators can customize mappings without rebuilding the binary.

### Default Alias Table

The system ships with a comprehensive built-in mapping called `DefaultModelAliases` that covers major providers:

- **OpenAI GPT family**: `"gpt-4"` maps to `"deepseek-v4-flash"`
- **Claude models**: `"claude-sonnet-4-6"` maps to `"deepseek-v4-flash"` (lines 35-48)
- **Gemini variants**: `"gemini-pro"` maps to `"deepseek-v4-pro"`, while `"gemini-flash-latest"` maps to `"deepseek-v4-flash"` (lines 66-82)

These mappings reside in [`internal/config/models.go`](https://github.com/CJackHwang/ds2api/blob/main/internal/config/models.go) and load into memory at startup, providing immediate compatibility for common model identifiers.

### Runtime Configuration Overrides

Operators can extend or override the default table through the [`config.json`](https://github.com/CJackHwang/ds2api/blob/main/config.json) configuration file under the `ModelAliases` key. The admin API handlers in [`internal/httpapi/admin/settings/handler_settings_parse.go`](https://github.com/CJackHwang/ds2api/blob/main/internal/httpapi/admin/settings/handler_settings_parse.go) (lines 119-138) parse JSON payloads containing a `"model_aliases"` field and merge them into the running configuration.

```json
{
  "model_aliases": {
    "my-custom-gpt": "deepseek-v4-pro",
    "experimental-claude": "deepseek-v4-flash"
  }
}

```

This runtime merging allows hot-swapping alias definitions without service restarts.

## How Alias Resolution Works

The resolution algorithm implemented in `config.ResolveModel` follows an eight-step precedence chain to determine the final DeepSeek model ID:

1. **Normalize** the request string (trim whitespace, convert to lowercase)
2. **Reject** retired historical model names via `isRetiredHistoricalModel`
3. **Return immediately** if the request already matches a valid DeepSeek model
4. **Build lookup map** starting with defaults, then overlay runtime aliases from `store.ModelAliases()`
5. **Map if valid** when the request exists in the alias table and points to a supported DeepSeek model
6. **Validate prefix** for strings starting with `"deepseek-"` that weren't recognized (treat as invalid)
7. **Heuristic resolution** for unknown families based on substrings (vision, reasoning, search)
8. **Fallback** to `"deepseek-v4-flash"` for any other recognized family

The function signature in [`internal/config/models.go`](https://github.com/CJackHwang/ds2api/blob/main/internal/config/models.go) (lines 89-108) accepts a `ModelAliasReader` interface and the requested model string:

```go
// internal/config/models.go
func ResolveModel(store ModelAliasReader, req string) (string, bool) {
    // Normalization and lookup logic
}

```

## Provider-Specific Integration

Each supported provider leverages the same resolution core, ensuring consistent behavior across different API endpoints.

### OpenAI GPT Compatibility

When requests arrive with OpenAI-style model names like `gpt-4-turbo` or `gpt-3.5-turbo`, DS2API consults the alias table and translates these to their DeepSeek counterparts before forwarding to the inference engine. The mapping handles both current and legacy OpenAI model naming conventions.

### Claude Conversion Layer

The Claude-specific handler in [`internal/claudeconv/convert.go`](https://github.com/CJackHwang/ds2api/blob/main/internal/claudeconv/convert.go) explicitly calls the resolver to translate Anthropic model names:

```go
// internal/claudeconv/convert.go
func ConvertClaudeToDeepSeek(req map[string]any, aliasProvider config.ModelAliasReader, defaultClaudeModel string) map[string]any {
    model := req["model"].(string)
    dsModel, ok := config.ResolveModel(aliasProvider, model)
    if !ok {
        // Handle resolution failure
    }
    // Build DeepSeek-compatible payload
    out := map[string]any{
        "model": dsModel,
        "messages": convertedMessages,
    }
    return out
}

```

This conversion happens early in the request lifecycle, ensuring that downstream DeepSeek handling remains provider-agnostic.

### Gemini Support

Gemini endpoints utilize the same `ResolveModel` function. When a request specifies `gemini-pro` or `gemini-flash-latest`, the resolver maps these to `deepseek-v4-pro` or `deepseek-v4-flash` respectively. The Gemini handlers require no special-case conversion logic beyond this resolution step.

## Runtime Alias Management

The administrative API surface exposes endpoints for dynamic alias configuration. Handlers in `internal/httpapi/admin/settings/handler_settings_*.go` process JSON updates containing the `"model_aliases"` key:

```go
// internal/httpapi/admin/settings/handler_settings_parse.go
func parseModelAliases(input []byte) (map[string]string, error) {
    var cfg struct {
        ModelAliases map[string]string `json:"model_aliases"`
    }
    if err := json.Unmarshal(input, &cfg); err != nil {
        return nil, err
    }
    return cfg.ModelAliases, nil
}

```

Once parsed, these aliases populate the configuration store that `ResolveModel` queries during subsequent requests.

## Custom Alias Resolution Example

To programmatically resolve a Claude model name without custom aliases:

```go
package main

import (
    "fmt"
    "ds2api/internal/config"
)

func main() {
    // Passing nil for store uses only default aliases
    model, ok := config.ResolveModel(nil, "claude-sonnet-4-6")
    if ok {
        fmt.Println("Resolved to DeepSeek model:", model)
        // Output: deepseek-v4-flash
    }
}

```

When runtime aliases exist, pass the configuration store instead of `nil` to include custom mappings in the resolution chain.

## Summary

- **DS2API** treats DeepSeek as the native backend but accepts OpenAI, Claude, and Gemini model names through an alias abstraction layer.
- **Default mappings** live in [`internal/config/models.go`](https://github.com/CJackHwang/ds2api/blob/main/internal/config/models.go) covering major provider model families.
- **Runtime overrides** via [`config.json`](https://github.com/CJackHwang/ds2api/blob/main/config.json) or admin APIs allow operators to customize aliases without redeployment.
- **Resolution precedence** follows an eight-step algorithm in `config.ResolveModel`, handling normalization, validation, and fallback logic.
- **Provider handlers** in [`internal/claudeconv/convert.go`](https://github.com/CJackHwang/ds2api/blob/main/internal/claudeconv/convert.go) and Gemini HTTP routes call the centralized resolver, keeping provider-specific code minimal.

## Frequently Asked Questions

### How do I add a custom model alias in DS2API?

Submit a PATCH request to the admin settings endpoint with a JSON body containing the `"model_aliases"` field, or define mappings in your [`config.json`](https://github.com/CJackHwang/ds2api/blob/main/config.json) file under the `ModelAliases` key. The system merges these with default aliases in [`internal/config/models.go`](https://github.com/CJackHwang/ds2api/blob/main/internal/config/models.go), with runtime values taking precedence.

### What happens if I request an unsupported model name?

If `config.ResolveModel` cannot find the requested name in the alias table or recognize it as a valid DeepSeek model, it returns `false` for the second boolean parameter. The API handler typically responds with a 400 error indicating an unsupported model, unless the name matches heuristics for vision or reasoning models that trigger fallback logic.

### Why does DS2API map everything to DeepSeek models instead of supporting multiple backends?

DS2API architecture standardizes on DeepSeek as the inference engine to simplify deployment and optimization. The alias system provides **cross-provider compatibility** for callers already integrated with OpenAI, Claude, or Gemini SDKs, allowing them to migrate to DS2API without changing their model naming conventions or request formatting.

### Can I override the default OpenAI or Claude mappings?

Yes. Runtime aliases defined in [`config.json`](https://github.com/CJackHwang/ds2api/blob/main/config.json) or via the admin API (handled in [`internal/httpapi/admin/settings/handler_settings_parse.go`](https://github.com/CJackHwang/ds2api/blob/main/internal/httpapi/admin/settings/handler_settings_parse.go)) override the default mappings from `DefaultModelAliases`. This allows you to redirect common model names like `"gpt-4"` to different DeepSeek variants or custom deployment endpoints.