Skip to content

feat(providers): add deepseek responses adapter#285

Merged
SantiagoDePolonia merged 2 commits intomainfrom
feat/deepseek-responses-translation
Apr 27, 2026
Merged

feat(providers): add deepseek responses adapter#285
SantiagoDePolonia merged 2 commits intomainfrom
feat/deepseek-responses-translation

Conversation

@SantiagoDePolonia
Copy link
Copy Markdown
Contributor

@SantiagoDePolonia SantiagoDePolonia commented Apr 27, 2026

Summary

  • add a first-class DeepSeek provider type
  • translate /v1/responses create and stream requests to DeepSeek /chat/completions
  • map GoModel reasoning effort to DeepSeek reasoning_effort and update Codex/config docs

Tests

  • go test ./...

Summary by CodeRabbit

  • New Features

    • Added DeepSeek as a supported LLM provider (chat completions, streaming, model discovery, and responses translation for compatibility).
  • Documentation

    • Added DeepSeek setup, env var guidance, examples, quickstart and guide pages; updated supported providers, roadmap, and chart/readme descriptions.
  • Tests

    • Added provider discovery and DeepSeek provider unit tests covering request/response translation and streaming behavior.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 27, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Adds DeepSeek as a supported LLM provider: new provider implementation, registration in the app, tests, translations from /v1/responses to DeepSeek chat completions, documentation updates, and examples.

Changes

Cohort / File(s) Summary
DeepSeek provider implementation
internal/providers/deepseek/deepseek.go, internal/providers/deepseek/deepseek_test.go
New provider package registering type: "deepseek". Implements chat completions, streaming, model listing, Responses→chat translation, reasoning_effort normalization, and returns an error for embeddings. Includes comprehensive unit tests.
App registration & boot
cmd/gomodel/main.go, cmd/gomodel/docs/docs.go
Imports and registers the DeepSeek provider; updates Swagger/OpenAPI description to include DeepSeek (and MiniMax).
Configuration & examples
config/config.example.yaml, config/config_test.go, internal/providers/config_test.go
Adds DeepSeek example config and default base URL guidance; extends env-var test helpers and provider discovery tests to handle DEEPSEEK_API_KEY, DEEPSEEK_BASE_URL, and related discovery behavior.
Documentation & guides
README.md, docs/getting-started/quickstart.mdx, docs/advanced/configuration.mdx, docs/guides/codex.mdx, docs/guides/deepseek.mdx, docs/docs.json, docs/docs.json
Adds DeepSeek to provider lists, quickstart, advanced config, and new DeepSeek guide; documents request rewrites (reasoning_effort), supported endpoints, and config snippets.
Site metadata & roadmap
docs/about/roadmap.mdx, docs/adr/0001-explicit-provider-registration.md, helm/Chart.yaml, helm/README.md
Updates roadmap and ADR context to include/remove specified providers and adds DeepSeek to Helm/chart metadata.
OpenAPI artifact
docs/openapi.json
Top-level OpenAPI info.description updated to include DeepSeek.

Sequence Diagram

sequenceDiagram
    actor Client
    participant GoModel as GoModel
    participant DeepSeek as DeepSeek API

    Client->>GoModel: POST /v1/chat/completions (reasoning.{effort}=medium)
    activate GoModel
    Note over GoModel: Rewrite to top-level\nreasoning_effort="high"
    GoModel->>DeepSeek: POST /chat/completions (reasoning_effort="high")
    activate DeepSeek
    DeepSeek-->>GoModel: 200 OK (chat response)
    deactivate DeepSeek
    GoModel-->>Client: 200 OK (ChatResponse)
    deactivate GoModel

    Client->>GoModel: POST /v1/responses (wire API)
    activate GoModel
    Note over GoModel: Translate Responses payload\n→ chat/completions + mapping rules
    GoModel->>DeepSeek: POST /chat/completions (translated)
    activate DeepSeek
    DeepSeek-->>GoModel: 200 OK (chat response)
    deactivate DeepSeek
    Note over GoModel: Map chat response → ResponsesResponse
    GoModel-->>Client: 200 OK (ResponsesResponse)
    deactivate GoModel
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly Related PRs

Poem

🐰 I hopped in with keys and a mapping so neat,
I rewrote reasoning and kept every beat,
From /responses to chat I translate with a grin,
DeepSeek now joins — let the model races begin! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(providers): add deepseek responses adapter' accurately describes the main objective: adding DeepSeek provider support with responses API translation, which is the core focus across all changes in the PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/deepseek-responses-translation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov-commenter
Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 56.04396% with 40 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/providers/deepseek/deepseek.go 56.66% 30 Missing and 9 partials ⚠️
cmd/gomodel/main.go 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 27, 2026

Greptile Summary

This PR adds a first-class deepseek provider type that translates GoModel's /v1/responses API to DeepSeek's /chat/completions, correctly mapping the reasoning effort field to DeepSeek's reasoning_effort parameter (including their compatibility aliases: low/mediumhigh, xhighmax). All remaining findings are P2 style suggestions and do not block merge.

Confidence Score: 5/5

Safe to merge; no P0 or P1 findings, all issues are minor style suggestions.

The core logic is correct: base URL (https://api.deepseek.com without /v1) matches DeepSeek's actual HTTP endpoint, the reasoning effort normalisation mirrors DeepSeek's own documented compatibility mapping, and embeddings correctly return an error since DeepSeek exposes no embeddings endpoint. Tests cover auth, reasoning translation, Responses-to-chat translation (streaming and non-streaming), and negative capability assertions. Only two P2 items remain (spurious reasoning: {} in the wire body and no comment about the thinking-toggle limitation), neither of which affects correctness.

No files require special attention.

Important Files Changed

Filename Overview
internal/providers/deepseek/deepseek.go New DeepSeek provider: correctly maps reasoning_effort, translates /v1/responses to /chat/completions, and uses the right base URL (api.deepseek.com without /v1). Two minor P2 style items around the reasoning serialisation path.
internal/providers/deepseek/deepseek_test.go Comprehensive table-driven and httptest-backed tests covering auth headers, reasoning_effort mapping, Responses-to-chat translation (streaming and non-streaming), and negative capabilities. Good coverage.
cmd/gomodel/main.go Registers deepseek.Registration with the provider factory; minimal, correct change.
internal/providers/config_test.go Adds DeepSeek to testDiscoveryConfigs and adds env-var discovery test; matches patterns of other providers.
config/config.example.yaml Updates DeepSeek example from type:openai+/v1 suffix to type:deepseek+bare base URL; correctly reflects new first-class provider.
docs/guides/codex.mdx Adds DeepSeek V4 Codex integration guide and updates flow diagram to be provider-agnostic; accurate and useful.
config/config_test.go Adds DEEPSEEK_* env vars to the clear list used by provider env-var tests; correct hygiene.

Sequence Diagram

sequenceDiagram
    participant Client
    participant GoModel
    participant DeepSeek

    Client->>GoModel: POST /v1/responses (ResponsesRequest)
    GoModel->>GoModel: providers.ResponsesViaChat()
    GoModel->>GoModel: adaptChatRequest()<br/>reasoning.effort → reasoning_effort<br/>(low/medium→high, xhigh/max→max)
    GoModel->>DeepSeek: POST /chat/completions<br/>(reasoning_effort: high|max)
    DeepSeek-->>GoModel: ChatResponse
    GoModel->>GoModel: Normalise → ResponsesResponse
    GoModel-->>Client: ResponsesResponse (object:response, status:completed)

    Client->>GoModel: POST /v1/responses (stream:true)
    GoModel->>GoModel: StreamResponsesViaChat()
    GoModel->>GoModel: adaptChatRequest() + WithStreaming()
    GoModel->>DeepSeek: POST /chat/completions (stream:true)
    DeepSeek-->>GoModel: SSE chat.completion.chunk stream
    GoModel->>GoModel: Rewrite chunks → response.output_text.delta events
    GoModel-->>Client: SSE responses event stream
Loading

Comments Outside Diff (2)

  1. internal/providers/deepseek/deepseek.go, line 435-453 (link)

    P2 reasoning: {} leaks into the request body when Effort is unset

    When req.Reasoning is non-nil but req.Reasoning.Effort is empty (e.g. the caller sets Reasoning: &core.Reasoning{}), adaptChatRequest returns req unchanged. Because ChatRequest.Reasoning has omitempty at the pointer level but the inner Effort field uses omitempty on a string, the serialised body will contain "reasoning": {}. DeepSeek ignores unknown fields so this is harmless today, but it sends unnecessary noise in every such request. Adding a nil/empty path for the inner struct would keep the wire format clean and consistent regardless of how callers construct the request.

  2. internal/providers/deepseek/deepseek.go, line 455-465 (link)

    P2 Thinking-mode toggle not forwarded

    adaptChatRequest sets reasoning_effort but never sets DeepSeek's thinking field. Per the DeepSeek docs thinking defaults to enabled, so reasoning requests work out of the box. However, users who want to explicitly disable thinking (e.g. to target the non-thinking mode of deepseek-v4-flash) currently have no path to do so through the GoModel API — the thinking key is not present in core.ChatRequest and ExtraFields is tagged json:"-" so it is silently dropped by adaptChatRequest. A comment noting this limitation would help future maintainers.

Reviews (1): Last reviewed commit: "feat(providers): add deepseek responses ..." | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@helm/README.md`:
- Line 3: Update the provider list string in helm/README.md by removing
"DeepSeek" from the comma-separated providers on the line that currently reads
"High-performance AI gateway for multiple LLM providers (OpenAI, Anthropic,
Gemini, DeepSeek, Groq, Z.ai, xAI, Oracle)"; edit that phrase to exclude
DeepSeek and adjust punctuation/spacing so the list remains grammatically
correct (e.g., "OpenAI, Anthropic, Gemini, Groq, Z.ai, xAI, Oracle"). Ensure no
other README lines advertise DeepSeek support.

In `@internal/providers/deepseek/deepseek_test.go`:
- Around line 230-237: The test TestEmbeddings_ReturnsUnsupported should assert
the error semantics for unsupported embeddings rather than any error; update the
assertion after calling provider.Embeddings (created via NewWithHTTPClient) to
check for the specific unsupported error (e.g., use errors.Is(err,
core.ErrUnsupported) or compare to the provider-specific sentinel like
ErrEmbeddingsNotSupported, or assert the error message contains "unsupported")
so the test fails only for unrelated transport/config errors while still
validating that embeddings are intentionally unsupported.

In `@internal/providers/deepseek/deepseek.go`:
- Around line 98-107: normalizeReasoningEffort currently accepts
DeepSeek-specific inputs like "xhigh" and "max"; change it so the public API
only accepts OpenAI-standard values ("low","medium","high") and maps them
internally to DeepSeek equivalents ("low" and "medium" -> "high", "high" ->
"xhigh"/"max" as required by DeepSeek). Update the function
normalizeReasoningEffort (and any caller at the API boundary) to validate the
incoming reasoning effort is one of "low","medium","high", return a clear error
or fallback for invalid values, and then perform the internal mapping to the
DeepSeek-specific token before sending to DeepSeek. Ensure callers do not pass
through "xhigh" or "max" from external inputs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 052a6826-d374-4176-8311-23fca3f7a4f3

📥 Commits

Reviewing files that changed from the base of the PR and between 1bc20ab and c9073cf.

📒 Files selected for processing (16)
  • README.md
  • cmd/gomodel/docs/docs.go
  • cmd/gomodel/main.go
  • config/config.example.yaml
  • config/config_test.go
  • docs/about/roadmap.mdx
  • docs/adr/0001-explicit-provider-registration.md
  • docs/advanced/configuration.mdx
  • docs/getting-started/quickstart.mdx
  • docs/guides/codex.mdx
  • docs/openapi.json
  • helm/Chart.yaml
  • helm/README.md
  • internal/providers/config_test.go
  • internal/providers/deepseek/deepseek.go
  • internal/providers/deepseek/deepseek_test.go

Comment thread helm/README.md
# GoModel Helm Chart

High-performance AI gateway for multiple LLM providers (OpenAI, Anthropic, Gemini, Groq, Z.ai, xAI, Oracle).
High-performance AI gateway for multiple LLM providers (OpenAI, Anthropic, Gemini, DeepSeek, Groq, Z.ai, xAI, Oracle).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Verify whether the Helm chart actually exposes DeepSeek settings.
rg -n -C2 'deepseek|DEEPSEEK|providers\.deepseek' helm

Repository: ENTERPILOT/GoModel

Length of output: 44


Remove DeepSeek from the provider list in line 3.

The README advertises DeepSeek support, but the Helm chart does not expose any DeepSeek configuration (no providers.deepseek.* or DEEPSEEK_* settings found in helm/). Operators cannot configure this provider from Helm, so remove it from the description to match what the chart actually supports.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@helm/README.md` at line 3, Update the provider list string in helm/README.md
by removing "DeepSeek" from the comma-separated providers on the line that
currently reads "High-performance AI gateway for multiple LLM providers (OpenAI,
Anthropic, Gemini, DeepSeek, Groq, Z.ai, xAI, Oracle)"; edit that phrase to
exclude DeepSeek and adjust punctuation/spacing so the list remains
grammatically correct (e.g., "OpenAI, Anthropic, Gemini, Groq, Z.ai, xAI,
Oracle"). Ensure no other README lines advertise DeepSeek support.

Comment thread internal/providers/deepseek/deepseek_test.go
Comment thread internal/providers/deepseek/deepseek.go
@mintlify
Copy link
Copy Markdown

mintlify Bot commented Apr 27, 2026

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
gomodel 🟢 Ready View Preview Apr 27, 2026, 10:08 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

Document DeepSeek V4's two-level reasoning_effort surface and the
low/medium -> high remap so users aren't surprised by the upgrade.
Cross-link from the Codex guide and add a comment on
normalizeReasoningEffort pointing to the user-facing table.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@SantiagoDePolonia SantiagoDePolonia merged commit a26fbd1 into main Apr 27, 2026
18 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants