fix(core): derive models.dev reasoning variants (#34726)
This commit is contained in:
parent
cfd35c9354
commit
140224b0fc
29 changed files with 457 additions and 119 deletions
|
|
@ -148,9 +148,22 @@ const AnthropicToolChoice = Schema.Union([
|
|||
Schema.Struct({ type: Schema.tag("tool"), name: Schema.String }),
|
||||
])
|
||||
|
||||
const AnthropicThinking = Schema.Struct({
|
||||
type: Schema.tag("enabled"),
|
||||
budget_tokens: Schema.Number,
|
||||
const AnthropicThinking = Schema.Union([
|
||||
Schema.Struct({
|
||||
type: Schema.tag("enabled"),
|
||||
budget_tokens: Schema.Number,
|
||||
}),
|
||||
Schema.Struct({
|
||||
type: Schema.tag("adaptive"),
|
||||
display: Schema.optional(Schema.Literals(["summarized", "omitted"])),
|
||||
}),
|
||||
Schema.Struct({
|
||||
type: Schema.tag("disabled"),
|
||||
}),
|
||||
])
|
||||
|
||||
const AnthropicOutputConfig = Schema.Struct({
|
||||
effort: Schema.optional(Schema.String),
|
||||
})
|
||||
|
||||
const AnthropicBodyFields = {
|
||||
|
|
@ -166,6 +179,7 @@ const AnthropicBodyFields = {
|
|||
top_k: Schema.optional(Schema.Number),
|
||||
stop_sequences: optionalArray(Schema.String),
|
||||
thinking: Schema.optional(AnthropicThinking),
|
||||
output_config: Schema.optional(AnthropicOutputConfig),
|
||||
}
|
||||
const AnthropicMessagesBody = Schema.Struct(AnthropicBodyFields)
|
||||
export type AnthropicMessagesBody = Schema.Schema.Type<typeof AnthropicMessagesBody>
|
||||
|
|
@ -492,7 +506,16 @@ const anthropicOptions = (request: LLMRequest) => request.providerOptions?.anthr
|
|||
|
||||
const lowerThinking = Effect.fn("AnthropicMessages.lowerThinking")(function* (request: LLMRequest) {
|
||||
const thinking = anthropicOptions(request)?.thinking
|
||||
if (!ProviderShared.isRecord(thinking) || thinking.type !== "enabled") return undefined
|
||||
if (!ProviderShared.isRecord(thinking)) return undefined
|
||||
if (thinking.type === "adaptive") {
|
||||
const display = thinking.display
|
||||
return {
|
||||
type: "adaptive" as const,
|
||||
...(display === "summarized" || display === "omitted" ? { display } : {}),
|
||||
}
|
||||
}
|
||||
if (thinking.type === "disabled") return { type: "disabled" as const }
|
||||
if (thinking.type !== "enabled") return undefined
|
||||
const budget =
|
||||
typeof thinking.budgetTokens === "number"
|
||||
? thinking.budgetTokens
|
||||
|
|
@ -503,6 +526,11 @@ const lowerThinking = Effect.fn("AnthropicMessages.lowerThinking")(function* (re
|
|||
return { type: "enabled" as const, budget_tokens: budget }
|
||||
})
|
||||
|
||||
const outputConfig = (request: LLMRequest) => {
|
||||
const effort = anthropicOptions(request)?.effort
|
||||
return typeof effort === "string" ? { effort } : undefined
|
||||
}
|
||||
|
||||
const fromRequest = Effect.fn("AnthropicMessages.fromRequest")(function* (request: LLMRequest) {
|
||||
const toolChoice = request.toolChoice ? yield* lowerToolChoice(request.toolChoice) : undefined
|
||||
const generation = request.generation
|
||||
|
|
@ -549,6 +577,7 @@ const fromRequest = Effect.fn("AnthropicMessages.fromRequest")(function* (reques
|
|||
top_k: generation?.topK,
|
||||
stop_sequences: generation?.stop,
|
||||
thinking: yield* lowerThinking(request),
|
||||
output_config: outputConfig(request),
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -168,8 +168,6 @@ interface ParserState {
|
|||
readonly lifecycle: Lifecycle.State
|
||||
}
|
||||
|
||||
const invalid = ProviderShared.invalidRequest
|
||||
|
||||
// =============================================================================
|
||||
// Request Lowering
|
||||
// =============================================================================
|
||||
|
|
@ -333,8 +331,6 @@ const lowerMessages = Effect.fn("OpenAIChat.lowerMessages")(function* (request:
|
|||
const lowerOptions = Effect.fn("OpenAIChat.lowerOptions")(function* (request: LLMRequest) {
|
||||
const store = OpenAIOptions.store(request)
|
||||
const reasoningEffort = OpenAIOptions.reasoningEffort(request)
|
||||
if (reasoningEffort && !OpenAIOptions.isReasoningEffort(reasoningEffort))
|
||||
return yield* invalid(`OpenAI Chat does not support reasoning effort ${reasoningEffort}`)
|
||||
return {
|
||||
...(store !== undefined ? { store } : {}),
|
||||
...(reasoningEffort ? { reasoning_effort: reasoningEffort } : {}),
|
||||
|
|
|
|||
|
|
@ -457,8 +457,6 @@ const lowerOptions = Effect.fn("OpenAIResponses.lowerOptions")(function* (reques
|
|||
const store = OpenAIOptions.store(request)
|
||||
const promptCacheKey = OpenAIOptions.promptCacheKey(request)
|
||||
const effort = OpenAIOptions.reasoningEffort(request)
|
||||
if (effort && !OpenAIOptions.isReasoningEffort(effort))
|
||||
return yield* invalid(`OpenAI Responses does not support reasoning effort ${effort}`)
|
||||
const summary = OpenAIOptions.reasoningSummary(request)
|
||||
const include = OpenAIOptions.include(request)
|
||||
const verbosity = OpenAIOptions.textVerbosity(request)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
import { Schema } from "effect"
|
||||
import type { LLMRequest, ReasoningEffort, TextVerbosity as TextVerbosityValue } from "../../schema"
|
||||
import type { LLMRequest, TextVerbosity as TextVerbosityValue } from "../../schema"
|
||||
import { ReasoningEfforts, TextVerbosity } from "../../schema"
|
||||
|
||||
export const OpenAIReasoningEfforts = ReasoningEfforts.filter(
|
||||
(effort): effort is Exclude<ReasoningEffort, "max"> => effort !== "max",
|
||||
)
|
||||
export type OpenAIReasoningEffort = (typeof OpenAIReasoningEfforts)[number]
|
||||
export const OpenAIReasoningEfforts = ReasoningEfforts
|
||||
export type OpenAIReasoningEffort = string
|
||||
|
||||
// Mirrors OpenAI's `ResponseIncludable` union from the official SDK. Keep this
|
||||
// in lockstep with `openai-node/src/resources/responses/responses.ts`.
|
||||
|
|
@ -23,22 +21,16 @@ export type OpenAIResponseIncludable = (typeof OpenAIResponseIncludables)[number
|
|||
export const OpenAIServiceTiers = ["auto", "default", "flex", "priority"] as const
|
||||
export type OpenAIServiceTier = (typeof OpenAIServiceTiers)[number]
|
||||
|
||||
const REASONING_EFFORTS = new Set<string>(ReasoningEfforts)
|
||||
const OPENAI_REASONING_EFFORTS = new Set<string>(OpenAIReasoningEfforts)
|
||||
const TEXT_VERBOSITY = new Set<string>(["low", "medium", "high"])
|
||||
const INCLUDABLES = new Set<string>(OpenAIResponseIncludables)
|
||||
const SERVICE_TIERS = new Set<string>(OpenAIServiceTiers)
|
||||
|
||||
export const OpenAIReasoningEffort = Schema.Literals(OpenAIReasoningEfforts)
|
||||
export const OpenAIReasoningEffort = Schema.String
|
||||
export const OpenAITextVerbosity = TextVerbosity
|
||||
export const OpenAIResponseIncludable = Schema.Literals(OpenAIResponseIncludables)
|
||||
export const OpenAIServiceTier = Schema.Literals(OpenAIServiceTiers)
|
||||
|
||||
const isAnyReasoningEffort = (effort: unknown): effort is ReasoningEffort =>
|
||||
typeof effort === "string" && REASONING_EFFORTS.has(effort)
|
||||
|
||||
export const isReasoningEffort = (effort: unknown): effort is OpenAIReasoningEffort =>
|
||||
typeof effort === "string" && OPENAI_REASONING_EFFORTS.has(effort)
|
||||
export const isReasoningEffort = (effort: unknown): effort is OpenAIReasoningEffort => typeof effort === "string"
|
||||
|
||||
const isTextVerbosity = (value: unknown): value is TextVerbosityValue =>
|
||||
typeof value === "string" && TEXT_VERBOSITY.has(value)
|
||||
|
|
@ -50,9 +42,9 @@ export const store = (request: LLMRequest): boolean | undefined => {
|
|||
return typeof value === "boolean" ? value : undefined
|
||||
}
|
||||
|
||||
export const reasoningEffort = (request: LLMRequest): ReasoningEffort | undefined => {
|
||||
export const reasoningEffort = (request: LLMRequest): string | undefined => {
|
||||
const value = options(request)?.reasoningEffort
|
||||
return isAnyReasoningEffort(value) ? value : undefined
|
||||
return typeof value === "string" ? value : undefined
|
||||
}
|
||||
|
||||
export const reasoningSummary = (request: LLMRequest): "auto" | undefined =>
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export const ToolCallID = Schema.String
|
|||
export type ToolCallID = Schema.Schema.Type<typeof ToolCallID>
|
||||
|
||||
export const ReasoningEfforts = ["none", "minimal", "low", "medium", "high", "xhigh", "max"] as const
|
||||
export const ReasoningEffort = Schema.Literals(ReasoningEfforts)
|
||||
export const ReasoningEffort = Schema.String
|
||||
export type ReasoningEffort = Schema.Schema.Type<typeof ReasoningEffort>
|
||||
|
||||
export const TextVerbosity = Schema.Literals(["low", "medium", "high"])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue