# `LangChain.ChatModels.ChatDeepSeek`
[🔗](https://github.com/brainlid/langchain/blob/v0.13.0/lib/chat_models/chat_deepseek.ex#L1)

Module for interacting with [DeepSeek models](https://www.deepseek.com/).

DeepSeek provides an API that is compatible with OpenAI's API format, making it
easy to integrate with existing OpenAI-based code.

## Model Options

DeepSeek supports the following models:
- `deepseek-chat` - Non-thinking mode of DeepSeek-V3.2-Exp
- `deepseek-reasoner` - Thinking mode of DeepSeek-V3.2-Exp

## API Configuration

The DeepSeek API uses the following configuration:
- Base URL: `https://api.deepseek.com` (or `https://api.deepseek.com/v1` for OpenAI compatibility)
- Authentication: Bearer token (API key)

## Example Usage

    # Basic usage
    model = ChatDeepSeek.new!(%{
      model: "deepseek-chat",
      api_key: "your-api-key-here"
    })

    # Using with LLMChain
    {:ok, chain} =
      LLMChain.new!(%{llm: model})
      |> LLMChain.add_message(Message.new_user!("Hello!"))

    {:ok, response} = LLMChain.run(chain)

## Tool Support

DeepSeek supports function calling through the OpenAI-compatible API format.
You can use tools in the same way as with OpenAI:

    model = ChatDeepSeek.new!(%{
      model: "deepseek-chat",
      api_key: "your-api-key-here"
    })

    function = Function.new!(%{
      name: "get_weather",
      description: "Get current weather for a location",
      parameters_schema: %{
        "type" => "object",
        "properties" => %{
          "location" => %{
            "type" => "string",
            "description" => "The city and state, e.g. San Francisco, CA"
          }
        },
        "required" => ["location"]
      }
    })

## Callbacks

See the set of available callbacks: `LangChain.Chains.ChainCallbacks`

### Token Usage

DeepSeek returns token usage information as part of the response body. The
`LangChain.TokenUsage` is added to the `metadata` of the `LangChain.Message`
and `LangChain.MessageDelta` structs that are processed under the `:usage`
key.

The `TokenUsage` data is accumulated for `MessageDelta` structs and the final usage information will be on the `LangChain.Message`.

## Connection Retry Behavior

The `retry_count` option controls how many times a request is retried when
a pooled HTTP connection turns out to be stale (server closed it between
requests). This is a transport-level issue where retrying with a fresh
connection is the correct response.

**Only closed-connection errors are retried.** Timeouts, rate limits (429),
overloaded (529), authentication errors, and invalid requests all return
immediately -- they are not problems that a simple retry will fix.

| `retry_count` | Total HTTP requests |
|---|---|
| `0` | 1 (no retries) |
| `1` | 2 (1 initial + 1 retry) |
| `2` (default) | 3 (1 initial + 2 retries) |

Req's built-in HTTP retry is disabled to prevent the two retry layers from
compounding. See [GitHub issue #503](https://github.com/brainlid/langchain/issues/503).

When running LLM calls from a background job queue (e.g., Oban) that has its
own retry logic, set `retry_count: 0` so there are no hidden retries:

    ChatDeepseek.new!(%{model: "...", retry_count: 0})

# `t`
[🔗](https://github.com/brainlid/langchain/blob/v0.13.0/lib/chat_models/chat_deepseek.ex#L196)

```elixir
@type t() :: %LangChain.ChatModels.ChatDeepSeek{
  api_key: term(),
  callbacks: term(),
  endpoint: term(),
  frequency_penalty: term(),
  json_response: term(),
  json_schema: term(),
  logprobs: term(),
  max_tokens: term(),
  model: term(),
  n: term(),
  parallel_tool_calls: term(),
  receive_timeout: term(),
  req_config: term(),
  retry_count: term(),
  seed: term(),
  stream: term(),
  stream_options: term(),
  temperature: term(),
  tool_choice: term(),
  top_logprobs: term(),
  user: term(),
  verbose_api: term()
}
```

# `call`
[🔗](https://github.com/brainlid/langchain/blob/v0.13.0/lib/chat_models/chat_deepseek.ex#L503)

Calls the DeepSeek API passing the ChatDeepSeek struct with configuration, plus
either a simple message or the list of messages to act as the prompt.

Optionally pass in a list of tools available to the LLM for requesting
execution in response.

Optionally pass in a callback function that can be executed as data is
received from the API.

**NOTE:** This function *can* be used directly, but the primary interface
should be through `LangChain.Chains.LLMChain`. The `ChatDeepSeek` module is more
focused on translating the `LangChain` data structures to and from the DeepSeek
API.

Another benefit of using `LangChain.Chains.LLMChain` is that it combines the
storage of messages, adding tools, adding custom context that should be
passed to tools, and automatically applying `LangChain.MessageDelta`
structs as they are are received, then converting those to the full
`LangChain.Message` once fully complete.

# `decode_stream`
[🔗](https://github.com/brainlid/langchain/blob/v0.13.0/lib/chat_models/chat_deepseek.ex#L817)

```elixir
@spec decode_stream({String.t(), String.t()}, list(), non_neg_integer()) ::
  {%{required(String.t()) =&gt; any()}} | {:error, LangChain.LangChainError.t()}
```

Decode a streamed response from a DeepSeek server. This is the same as the OpenAI
implementation since DeepSeek uses an OpenAI-compatible API.

# `for_api`
[🔗](https://github.com/brainlid/langchain/blob/v0.13.0/lib/chat_models/chat_deepseek.ex#L388)

```elixir
@spec for_api(
  struct(),
  LangChain.Message.t()
  | LangChain.PromptTemplate.t()
  | LangChain.Message.ToolCall.t()
  | LangChain.Message.ToolResult.t()
  | LangChain.Message.ContentPart.t()
  | LangChain.Function.t()
) :: %{required(String.t()) =&gt; any()} | [%{required(String.t()) =&gt; any()}]
```

Convert a LangChain Message-based structure to the expected map of data for
the DeepSeek API.

# `for_api`
[🔗](https://github.com/brainlid/langchain/blob/v0.13.0/lib/chat_models/chat_deepseek.ex#L296)

```elixir
@spec for_api(
  t() | LangChain.Message.t() | LangChain.Function.t(),
  message :: [map()],
  LangChain.ChatModels.ChatModel.tools()
) :: %{required(atom()) =&gt; any()}
```

Return the params formatted for an API request.

# `new`
[🔗](https://github.com/brainlid/langchain/blob/v0.13.0/lib/chat_models/chat_deepseek.ex#L234)

```elixir
@spec new(attrs :: map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()}
```

Setup a ChatDeepSeek client configuration.

# `new!`
[🔗](https://github.com/brainlid/langchain/blob/v0.13.0/lib/chat_models/chat_deepseek.ex#L245)

```elixir
@spec new!(attrs :: map()) :: t() | no_return()
```

Setup a ChatDeepSeek client configuration and return it or raise an error if invalid.

# `restore_from_map`
[🔗](https://github.com/brainlid/langchain/blob/v0.13.0/lib/chat_models/chat_deepseek.ex#L1275)

Restores the model from the config.

# `retry_on_fallback?`
[🔗](https://github.com/brainlid/langchain/blob/v0.13.0/lib/chat_models/chat_deepseek.ex#L1237)

```elixir
@spec retry_on_fallback?(LangChain.LangChainError.t()) :: boolean()
```

Determine if an error should be retried. If `true`, a fallback LLM may be
used. If `false`, the error is understood to be more fundamental with the
request rather than a service issue and it should not be retried or fallback
to another service.

# `serialize_config`
[🔗](https://github.com/brainlid/langchain/blob/v0.13.0/lib/chat_models/chat_deepseek.ex#L1250)

```elixir
@spec serialize_config(t()) :: %{required(String.t()) =&gt; any()}
```

Generate a config map that can later restore the model's configuration.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
