DeepSeek
Use DeepSeek chat through Chat Completions (default) or Responses. Responses adds native schema output and hosted search on V4 Pro; the endpoints do not have identical state or tool contracts.
Setup and first request
In your application's config/runtime.exs:
import Config
config :beam_weaver, :deepseek, api_key: System.fetch_env!("DEEPSEEK_API_KEY")
alias BeamWeaver.Core.{ChatModel, Message}
{:ok, model} = BeamWeaver.Models.init_chat_model("deepseek:deepseek-flash", max_tokens: 1_024, timeout: 120_000)
{:ok, reply} = ChatModel.invoke(model, "Explain parcel tracking in one sentence.")
true = byte_size(Message.text(reply)) > 0
true = reply.usage_metadata.total_tokens > 0
Use the same identifier in an agent's model declaration. Preserve complete messages across tool rounds so required reasoning content can be replayed.
Endpoint and reasoning choices
| Setting | Meaning |
|---|---|
api: :chat_completions
| Default chat endpoint |
api: :responses
| Responses endpoint with its own supported fields |
thinking:
| Enabled/disabled on Chat Completions |
reasoning_effort:
| Model-supported low/high/max; none disables thinking |
reasoning:
| Responses reasoning map |
beta:
| Beta request routing |
base_url:
| Native API root or gateway |
Thinking is enabled by default. Forced tool choice requires thinking disabled where supported. Native Responses conversation IDs are not supported here: DeepSeek receives full history each turn. Chat Completions uses JSON-object mode with schema instructions/local checks; Responses supports native JSON Schema. See Structured Output for validation limits.
On Flash, top_p takes effect in thinking mode and values below 0.95 are treated as 0.95; non-thinking mode fixes it at 1.0. Chat Completions requires 0 < top_p <= 1. Streaming usage arrives on the last content chunk with its finish reason, followed by [DONE]; a separate usage-only chunk is not required.
Images
Flash supports image input; the V4 Pro profile is text-only. From a repository checkout, use the bundled fixture:
alias BeamWeaver.Core.ContentBlock
question =
Message.user([
ContentBlock.text("Name the single color filling this image."),
ContentBlock.image(data: Base.encode64(File.read!("examples/fixtures/red-square.png")), mime_type: "image/png")
])
{:ok, reply} = ChatModel.invoke(model, [question])
true = reply |> Message.text() |> String.downcase() |> String.contains?("red")
Images are supported media here; PDF/audio/video input are not. Download/copy the image fixture into the same relative path when running outside a checkout.
Responses and hosted tools
Hosted web search is supported on V4 Pro; Flash ignores that declaration. Use the supported model and inspect the preserved native search item:
{:ok, responses} =
BeamWeaver.Models.init_chat_model("deepseek:deepseek-v4-pro", api: :responses, max_tokens: 2_048, timeout: 120_000)
{:ok, reply} =
ChatModel.invoke(
responses,
"Use web search to find the official Elixir programming language website. Return its URL.",
tools: [BeamWeaver.DeepSeek.Tools.web_search()],
tool_choice: %{type: "web_search"}
)
true = byte_size(Message.text(reply)) > 0
true = Enum.any?(List.wrap(reply.content), &(Map.get(&1, :provider_type) == "web_search_call"))
apply_patch declares a client action; your application must implement the executor. A declaration alone does not edit files. Beta routing also supports strict function tools and prefix completion where the selected model allows it.
Raw client
DeepSeek.Client exposes Search, Fetch, FIM completions, model discovery and account balance.
Search and Fetch
The standalone endpoints work independently of the chat model. Create a client from the configured DeepSeek credentials and send native request bodies:
search_client = BeamWeaver.DeepSeek.Client.new(timeout: 60_000)
{:ok, search} = BeamWeaver.DeepSeek.Client.search(search_client, %{
query: "Elixir site:elixir-lang.org",
count: 5,
need_content: true
})
true = is_list(search["results"])
{:ok, page} = BeamWeaver.DeepSeek.Client.fetch(search_client, %{url: "https://elixir-lang.org/"})
true = is_binary(page["content"])
POST /v1/tools/search and POST /v1/tools/fetch each cost $0.75 per 1,000 successful requests. Search is billable only with non-empty results; Fetch requires returned page content. Failures, empty results and timeouts are free. These are request charges, separate from model token usage. The temporary free period through October 31 applies to server-side calls through DeepSeek Harness, Claude Code and Codex, rather than direct standalone API calls. See the
Search & Fetch guide
and
pricing
.
FIM completions
FIM runs without thinking. This complete call checks actual generated code:
client = BeamWeaver.DeepSeek.Client.new()
{:ok, completion} =
BeamWeaver.DeepSeek.Client.completions(client, %{
"model" => "deepseek-flash",
"prompt" => "def add(a, b):\n ",
"suffix" => "\n",
"max_tokens" => 64
})
[text | _] = for choice <- completion["choices"], do: choice["text"]
true = is_binary(text) and byte_size(text) > 0
The complete DeepSeek script also exercises the Anthropic-style endpoint. Native account APIs are separate from agent inference.
Errors, caching and limits
Resource-exhaustion/aborted finish reasons normalize to server errors rather than successful truncated answers. Content-filtered replies can remain replies; inspect the outcome. Retry only within a deliberate budget.
Repeated prefix caching is automatic; inspect reported cache-read tokens. There is no prompt-cache key added by BeamWeaver's caching middleware. Request metadata: is unsupported; use trace metadata for application labels.
Time-based cost estimates use the registered UTC weekday pricing windows. They do not include a Chinese public-holiday calendar; consult DeepSeek's pricing for holiday exceptions.
Models
Limits are local profile data. A dash means not applicable or not recorded, not an unlimited allowance.
| Model | Input / output tokens | Operations and capabilities |
|---|---|---|
deepseek:deepseek-flash
| 1,048,576 / 393,216 | chat; text, image; tools; structured output; reasoning |
deepseek:deepseek-v4-flash
| 1,048,576 / 393,216 | chat; text, image; tools; structured output; reasoning |
deepseek:deepseek-v4-flash-vision-exp
| 1,048,576 / 393,216 | chat; text, image; tools; structured output; reasoning |
deepseek:deepseek-v4-pro
| 1,048,576 / 393,216 | chat; text; tools; structured output; reasoning |
deepseek-flash serves DeepSeek V4.1-Flash-1017. The older V4 Flash identifiers remain accepted aliases for the same model. Pinning an alias does not freeze the provider's underlying model revision.
Further reading
The official tool-call contract describes the native exchange. Use Testing for deterministic failure cases.