mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-10-06 17:57:47 +08:00
Measured on Bedrock: Claude Opus 4.7, 4.8 and every Claude 5 model reject
a thinking budget ("thinking.type.enabled") and a temperature, and all of
them accept adaptive thinking. The retry used to drop thinking, so with
a thinking budget set these models did not think at all. It now switches
to adaptive thinking with display "summarized"; without that setting the
models think but send no thinking text to show.
The suggested Bedrock ids had no region prefix, and the newer models only
answer through an inference profile id: "anthropic.claude-sonnet-5-5"
fails with "on-demand throughput isn't supported". Each suggested id was
called once; the Claude ones now start with "global.", Llama, Pixtral and
Nova 2 Lite with "us.". Nova Premier (end of life) and the ids without a
working profile are gone. The docs example had the same problem and a
wrong date.
95 lines
3.2 KiB
TypeScript
95 lines
3.2 KiB
TypeScript
import { wrapLanguageModel } from "ai"
|
|
import { rejectionText } from "@/lib/output-token-limit"
|
|
|
|
type WrappedModel = ReturnType<typeof wrapLanguageModel>
|
|
|
|
/**
|
|
* Claude 4.7 and later answer a non-default temperature, top_p or top_k,
|
|
* and the extended thinking budget (thinking type "enabled"), with a 400.
|
|
* TEMPERATURE and the *_THINKING_BUDGET_TOKENS settings send exactly these.
|
|
*/
|
|
const DEPRECATED_PARAM =
|
|
/`?(?:temperature|top_p|top_k)`? is deprecated for this model|"?thinking\.type\.enabled"? is not supported/i
|
|
|
|
interface CallParams {
|
|
temperature?: number
|
|
topP?: number
|
|
topK?: number
|
|
providerOptions?: Record<string, Record<string, unknown> | undefined>
|
|
}
|
|
|
|
// What these models take instead of a budget. Without display "summarized"
|
|
// they think but send no thinking text to show.
|
|
const ADAPTIVE_THINKING = { type: "adaptive", display: "summarized" }
|
|
|
|
/** Turn a thinking config of type "enabled" stored under key into adaptive */
|
|
function adaptiveThinking(
|
|
options: Record<string, unknown> | undefined,
|
|
key: string,
|
|
): Record<string, unknown> | undefined {
|
|
const config = options?.[key] as { type?: string } | undefined
|
|
if (config?.type !== "enabled") return options
|
|
return { ...options, [key]: ADAPTIVE_THINKING }
|
|
}
|
|
|
|
/**
|
|
* The params without the settings newer Claude models reject, or null when
|
|
* the error is about something else or there is nothing to change. The
|
|
* model then runs with its default sampling, and a thinking budget becomes
|
|
* adaptive thinking.
|
|
*/
|
|
export function withoutDeprecatedParams<T extends CallParams>(
|
|
error: unknown,
|
|
params: T,
|
|
): T | null {
|
|
const text = rejectionText(error)
|
|
if (!text || !DEPRECATED_PARAM.test(text)) return null
|
|
|
|
const { temperature, topP, topK, ...rest } = params
|
|
const options = params.providerOptions
|
|
const anthropic = adaptiveThinking(options?.anthropic, "thinking")
|
|
const bedrock = adaptiveThinking(options?.bedrock, "reasoningConfig")
|
|
const changed =
|
|
temperature !== undefined ||
|
|
topP !== undefined ||
|
|
topK !== undefined ||
|
|
anthropic !== options?.anthropic ||
|
|
bedrock !== options?.bedrock
|
|
if (!changed) return null
|
|
|
|
return {
|
|
...rest,
|
|
...(options && {
|
|
providerOptions: {
|
|
...options,
|
|
...(anthropic && { anthropic }),
|
|
...(bedrock && { bedrock }),
|
|
},
|
|
}),
|
|
} as T
|
|
}
|
|
|
|
/** Retry the stream once without the settings newer Claude models reject. */
|
|
export function withDeprecatedParamsFallback(
|
|
model: WrappedModel,
|
|
): WrappedModel {
|
|
return wrapLanguageModel({
|
|
model,
|
|
middleware: {
|
|
specificationVersion: "v3",
|
|
async wrapStream({ doStream, params, model: inner }) {
|
|
try {
|
|
return await doStream()
|
|
} catch (error) {
|
|
const retry = withoutDeprecatedParams(error, params)
|
|
if (!retry) throw error
|
|
console.warn(
|
|
"[model params] Rejected sampling or thinking settings, retrying with default sampling and adaptive thinking",
|
|
)
|
|
return await inner.doStream(retry)
|
|
}
|
|
},
|
|
},
|
|
})
|
|
}
|