Files
new-api/common/endpoint_type.go
Calcium-Ion 6cf0d90b5f feat(deepseek): support V4.1 Flash, the Search and Fetch APIs, and @ reasoning modifiers (#7867)
* fix(model): find channels for @-modified model names without the memory cache

With the channel memory cache off (no Redis and MEMORY_CACHE_ENABLED
unset), channel selection matched abilities by the exact requested name,
so a name such as deepseek-flash@effort:max found no channel. Retry with
the routing name when the exact name has no channel, as the cached path
already does.

* feat(deepseek): support V4.1 Flash, the Search and Fetch APIs, and @ reasoning modifiers

Follows the DeepSeek API update of 2026-10-17.

- Default models: deepseek-flash and deepseek-v4-pro, each with -none,
  -low and -max, plus deepseek-search and deepseek-fetch. The retired
  deepseek-chat, deepseek-reasoner and deepseek-v4-flash names are no
  longer listed.
- Thinking: the -none/-low/-max tails also work on deepseek-flash.
  @thinking and @effort now reach DeepSeek's own fields on Chat
  (thinking, reasoning_effort), Anthropic (thinking, output_config.effort)
  and Responses (reasoning.effort), and take precedence over the tails.
- Built-in prices: peak/off-peak expressions for deepseek-flash (also the
  deepseek-v4-flash aliases) and deepseek-v4-pro, and $0.75 per 1,000
  requests for deepseek-search and deepseek-fetch.
- Server-side search: searches and page fetches DeepSeek runs for Claude
  Code and Codex bill at $0.75 per 1,000 under deepseek_search and
  deepseek_fetch, whatever model name the client sent. Searches whose
  results already arrived stay billed when a stream ends before its final
  usage; this also applies to Alibaba's Anthropic endpoint.
- New endpoints POST /v1/tools/search and /v1/tools/fetch relay the
  DeepSeek APIs like /v1/alpha/search. A call is charged only when
  DeepSeek returns results or page content.

* fix(deepseek): price /v1/tools/search and /v1/tools/fetch by endpoint

A model named in the request body chose the billing model, so a body such
as {"query":"...","model":"deepseek-flash"} was priced as a chat model with
no tokens and the search or fetch cost nothing. Both endpoints now always
use their routing name, deepseek-search or deepseek-fetch. DeepSeek ignores
the body field, so the body is still forwarded unchanged.

* fix(deepseek): bill Claude-format page fetches at the DeepSeek Fetch price

usage.server_tool_use.web_fetch_requests always went to the web_fetch
tool price, which has no built-in value, while only searches used the
DeepSeek key. A channel can now name its own fetch key next to the search
key, and DeepSeek channels bill reported fetches under deepseek_fetch. A
channel retry clears it like the search key.
2026-10-17 23:24:33 +08:00

70 lines
3.1 KiB
Go

package common
import "github.com/QuantumNous/new-api/constant"
// GetEndpointTypesByChannelType 获取渠道最优先端点类型(所有的渠道都支持 OpenAI 端点)
func GetEndpointTypesByChannelType(channelType int, modelName string) []constant.EndpointType {
// The DeepSeek Search and Fetch routing names serve only their endpoint.
switch modelName {
case constant.DeepSeekSearchModel:
return []constant.EndpointType{constant.EndpointTypeDeepSeekToolsSearch}
case constant.DeepSeekFetchModel:
return []constant.EndpointType{constant.EndpointTypeDeepSeekToolsFetch}
}
var endpointTypes []constant.EndpointType
switch channelType {
case constant.ChannelTypeJina:
endpointTypes = []constant.EndpointType{constant.EndpointTypeJinaRerank}
//case constant.ChannelTypeMidjourney, constant.ChannelTypeMidjourneyPlus:
// endpointTypes = []constant.EndpointType{constant.EndpointTypeMidjourney}
//case constant.ChannelTypeSunoAPI:
// endpointTypes = []constant.EndpointType{constant.EndpointTypeSuno}
//case constant.ChannelTypeKling:
// endpointTypes = []constant.EndpointType{constant.EndpointTypeKling}
//case constant.ChannelTypeJimeng:
// endpointTypes = []constant.EndpointType{constant.EndpointTypeJimeng}
case constant.ChannelTypeAws:
fallthrough
case constant.ChannelTypeAnthropic:
endpointTypes = []constant.EndpointType{constant.EndpointTypeAnthropic, constant.EndpointTypeOpenAI}
case constant.ChannelTypeVertexAi:
fallthrough
case constant.ChannelTypeGemini:
endpointTypes = []constant.EndpointType{constant.EndpointTypeGemini, constant.EndpointTypeOpenAI}
case constant.ChannelTypeOpenRouter: // OpenRouter 只支持 OpenAI 端点
endpointTypes = []constant.EndpointType{constant.EndpointTypeOpenAI}
case constant.ChannelTypeXai:
endpointTypes = []constant.EndpointType{constant.EndpointTypeOpenAI, constant.EndpointTypeOpenAIResponse}
case constant.ChannelTypeVLLM, constant.ChannelTypeSGLang:
endpointTypes = GetAdvancedCustomPreset(channelType).SupportedEndpointTypesForModel(modelName)
case constant.ChannelTypeSora:
endpointTypes = []constant.EndpointType{constant.EndpointTypeOpenAIVideo}
case constant.ChannelTypeSub2API, constant.ChannelTypeNewAPI:
endpointTypes = []constant.EndpointType{
constant.EndpointTypeOpenAI,
constant.EndpointTypeOpenAIResponse,
constant.EndpointTypeOpenAIResponseCompact,
constant.EndpointTypeAnthropic,
constant.EndpointTypeGemini,
constant.EndpointTypeOpenAIAlphaSearch,
}
case constant.ChannelTypeCodex:
endpointTypes = []constant.EndpointType{
constant.EndpointTypeOpenAIResponse,
constant.EndpointTypeOpenAIResponseCompact,
constant.EndpointTypeOpenAIAlphaSearch,
}
default:
if IsOpenAIResponseOnlyModel(modelName) {
endpointTypes = []constant.EndpointType{constant.EndpointTypeOpenAIResponse}
} else {
endpointTypes = []constant.EndpointType{constant.EndpointTypeOpenAI}
}
}
if IsImageGenerationModel(modelName) {
// add to first
endpointTypes = append([]constant.EndpointType{constant.EndpointTypeImageGeneration}, endpointTypes...)
}
return endpointTypes
}