mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-07 05:39:05 +08:00
fix/anthropic-vertex (#11397)
* 100m * feat: add web search header for Claude 4 series models * fix: typo * fix: identify model --------- Co-authored-by: defi-failure <159208748+defi-failure@users.noreply.github.com>
This commit is contained in:
parent
f98a063a8f
commit
a1ac3207f1
@ -1,13 +1,32 @@
|
|||||||
import { isClaude45ReasoningModel } from '@renderer/config/models'
|
import { isClaude4SeriesModel, isClaude45ReasoningModel } from '@renderer/config/models'
|
||||||
|
import { isAwsBedrockProvider } from '@renderer/config/providers'
|
||||||
|
import { isVertexProvider } from '@renderer/hooks/useVertexAI'
|
||||||
|
import { getProviderByModel } from '@renderer/services/AssistantService'
|
||||||
import type { Assistant, Model } from '@renderer/types'
|
import type { Assistant, Model } from '@renderer/types'
|
||||||
import { isToolUseModeFunction } from '@renderer/utils/assistant'
|
import { isToolUseModeFunction } from '@renderer/utils/assistant'
|
||||||
|
|
||||||
|
// https://docs.claude.com/en/docs/build-with-claude/extended-thinking#interleaved-thinking
|
||||||
const INTERLEAVED_THINKING_HEADER = 'interleaved-thinking-2025-05-14'
|
const INTERLEAVED_THINKING_HEADER = 'interleaved-thinking-2025-05-14'
|
||||||
|
// https://docs.claude.com/en/docs/build-with-claude/context-windows#1m-token-context-window
|
||||||
|
const CONTEXT_100M_HEADER = 'context-1m-2025-08-07'
|
||||||
|
// https://docs.cloud.google.com/vertex-ai/generative-ai/docs/partner-models/claude/web-search
|
||||||
|
const WEBSEARCH_HEADER = 'web-search-2025-03-05'
|
||||||
|
|
||||||
export function addAnthropicHeaders(assistant: Assistant, model: Model): string[] {
|
export function addAnthropicHeaders(assistant: Assistant, model: Model): string[] {
|
||||||
const anthropicHeaders: string[] = []
|
const anthropicHeaders: string[] = []
|
||||||
if (isClaude45ReasoningModel(model) && isToolUseModeFunction(assistant)) {
|
const provider = getProviderByModel(model)
|
||||||
|
if (
|
||||||
|
isClaude45ReasoningModel(model) &&
|
||||||
|
isToolUseModeFunction(assistant) &&
|
||||||
|
!(isVertexProvider(provider) && isAwsBedrockProvider(provider))
|
||||||
|
) {
|
||||||
anthropicHeaders.push(INTERLEAVED_THINKING_HEADER)
|
anthropicHeaders.push(INTERLEAVED_THINKING_HEADER)
|
||||||
}
|
}
|
||||||
|
if (isClaude4SeriesModel(model)) {
|
||||||
|
if (isVertexProvider(provider) && assistant.enableWebSearch) {
|
||||||
|
anthropicHeaders.push(WEBSEARCH_HEADER)
|
||||||
|
}
|
||||||
|
anthropicHeaders.push(CONTEXT_100M_HEADER)
|
||||||
|
}
|
||||||
return anthropicHeaders
|
return anthropicHeaders
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,8 +21,6 @@ import {
|
|||||||
isSupportedThinkingTokenModel,
|
isSupportedThinkingTokenModel,
|
||||||
isWebSearchModel
|
isWebSearchModel
|
||||||
} from '@renderer/config/models'
|
} from '@renderer/config/models'
|
||||||
import { isAwsBedrockProvider } from '@renderer/config/providers'
|
|
||||||
import { isVertexProvider } from '@renderer/hooks/useVertexAI'
|
|
||||||
import { getAssistantSettings, getDefaultModel } from '@renderer/services/AssistantService'
|
import { getAssistantSettings, getDefaultModel } from '@renderer/services/AssistantService'
|
||||||
import store from '@renderer/store'
|
import store from '@renderer/store'
|
||||||
import type { CherryWebSearchConfig } from '@renderer/store/websearch'
|
import type { CherryWebSearchConfig } from '@renderer/store/websearch'
|
||||||
@ -179,8 +177,7 @@ export async function buildStreamTextParams(
|
|||||||
|
|
||||||
let headers: Record<string, string | undefined> = options.requestOptions?.headers ?? {}
|
let headers: Record<string, string | undefined> = options.requestOptions?.headers ?? {}
|
||||||
|
|
||||||
// https://docs.claude.com/en/docs/build-with-claude/extended-thinking#interleaved-thinking
|
if (isAnthropicModel(model)) {
|
||||||
if (!isVertexProvider(provider) && !isAwsBedrockProvider(provider) && isAnthropicModel(model)) {
|
|
||||||
const newBetaHeaders = { 'anthropic-beta': addAnthropicHeaders(assistant, model).join(',') }
|
const newBetaHeaders = { 'anthropic-beta': addAnthropicHeaders(assistant, model).join(',') }
|
||||||
headers = combineHeaders(headers, newBetaHeaders)
|
headers = combineHeaders(headers, newBetaHeaders)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -382,6 +382,12 @@ export function isClaude45ReasoningModel(model: Model): boolean {
|
|||||||
return regex.test(modelId)
|
return regex.test(modelId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isClaude4SeriesModel(model: Model): boolean {
|
||||||
|
const modelId = getLowerBaseModelName(model.id, '/')
|
||||||
|
const regex = /claude-(sonnet|opus|haiku)-4(?:[.-]\d+)?(?:-[\w-]+)?$/i
|
||||||
|
return regex.test(modelId)
|
||||||
|
}
|
||||||
|
|
||||||
export function isClaudeReasoningModel(model?: Model): boolean {
|
export function isClaudeReasoningModel(model?: Model): boolean {
|
||||||
if (!model) {
|
if (!model) {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@ -11,10 +11,11 @@ import {
|
|||||||
isVertexAiProvider
|
isVertexAiProvider
|
||||||
} from '../providers'
|
} from '../providers'
|
||||||
import { isEmbeddingModel, isRerankModel } from './embedding'
|
import { isEmbeddingModel, isRerankModel } from './embedding'
|
||||||
|
import { isClaude4SeriesModel } from './reasoning'
|
||||||
import { isAnthropicModel } from './utils'
|
import { isAnthropicModel } from './utils'
|
||||||
import { isPureGenerateImageModel, isTextToImageModel } from './vision'
|
import { isPureGenerateImageModel, isTextToImageModel } from './vision'
|
||||||
|
|
||||||
export const CLAUDE_SUPPORTED_WEBSEARCH_REGEX = new RegExp(
|
const CLAUDE_SUPPORTED_WEBSEARCH_REGEX = new RegExp(
|
||||||
`\\b(?:claude-3(-|\\.)(7|5)-sonnet(?:-[\\w-]+)|claude-3(-|\\.)5-haiku(?:-[\\w-]+)|claude-(haiku|sonnet|opus)-4(?:-[\\w-]+)?)\\b`,
|
`\\b(?:claude-3(-|\\.)(7|5)-sonnet(?:-[\\w-]+)|claude-3(-|\\.)5-haiku(?:-[\\w-]+)|claude-(haiku|sonnet|opus)-4(?:-[\\w-]+)?)\\b`,
|
||||||
'i'
|
'i'
|
||||||
)
|
)
|
||||||
@ -73,11 +74,11 @@ export function isWebSearchModel(model: Model): boolean {
|
|||||||
|
|
||||||
const modelId = getLowerBaseModelName(model.id, '/')
|
const modelId = getLowerBaseModelName(model.id, '/')
|
||||||
|
|
||||||
// bedrock和vertex不支持
|
// bedrock不支持
|
||||||
if (
|
if (isAnthropicModel(model) && !(provider.id === SystemProviderIds['aws-bedrock'])) {
|
||||||
isAnthropicModel(model) &&
|
if (isVertexAiProvider(provider)) {
|
||||||
!(provider.id === SystemProviderIds['aws-bedrock'] || provider.id === SystemProviderIds.vertexai)
|
return isClaude4SeriesModel(model)
|
||||||
) {
|
}
|
||||||
return CLAUDE_SUPPORTED_WEBSEARCH_REGEX.test(modelId)
|
return CLAUDE_SUPPORTED_WEBSEARCH_REGEX.test(modelId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user