refactor(ai): normalize provider option parsing (#38695)
This commit is contained in:
parent
c06186a9d9
commit
d90da82be2
14 changed files with 256 additions and 84 deletions
57
packages/ai/src/protocols/utils/anthropic-options.ts
Normal file
57
packages/ai/src/protocols/utils/anthropic-options.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import { Effect, Schema } from "effect"
|
||||
import type { LLMRequest } from "../../schema"
|
||||
import { ProviderShared } from "../shared"
|
||||
|
||||
export const ThinkingSchema = 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"),
|
||||
}),
|
||||
])
|
||||
export type Thinking = Schema.Schema.Type<typeof ThinkingSchema>
|
||||
|
||||
export interface Resolved {
|
||||
readonly thinking?: Thinking
|
||||
readonly effort?: string
|
||||
}
|
||||
|
||||
export const resolve = Effect.fn("AnthropicOptions.resolve")(function* (request: LLMRequest) {
|
||||
const input = request.providerOptions?.anthropic
|
||||
return {
|
||||
thinking: yield* resolveThinking(input?.thinking),
|
||||
effort: typeof input?.effort === "string" ? input.effort : undefined,
|
||||
} satisfies Resolved
|
||||
})
|
||||
|
||||
const resolveThinking = Effect.fn("AnthropicOptions.resolveThinking")(function* (input: unknown) {
|
||||
if (!ProviderShared.isRecord(input)) return undefined
|
||||
if (input.type === "adaptive") {
|
||||
const display =
|
||||
input.display === "summarized"
|
||||
? ("summarized" as const)
|
||||
: input.display === "omitted"
|
||||
? ("omitted" as const)
|
||||
: undefined
|
||||
return { type: "adaptive" as const, ...(display === undefined ? {} : { display }) }
|
||||
}
|
||||
if (input.type === "disabled") return { type: "disabled" as const }
|
||||
if (input.type !== "enabled") return undefined
|
||||
const budget =
|
||||
typeof input.budgetTokens === "number"
|
||||
? input.budgetTokens
|
||||
: typeof input.budget_tokens === "number"
|
||||
? input.budget_tokens
|
||||
: undefined
|
||||
if (budget === undefined)
|
||||
return yield* ProviderShared.invalidRequest("Anthropic thinking provider option requires budgetTokens")
|
||||
return { type: "enabled" as const, budget_tokens: budget }
|
||||
})
|
||||
|
||||
export * as AnthropicOptions from "./anthropic-options"
|
||||
27
packages/ai/src/protocols/utils/gemini-options.ts
Normal file
27
packages/ai/src/protocols/utils/gemini-options.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { Schema } from "effect"
|
||||
import type { LLMRequest } from "../../schema"
|
||||
import { ProviderShared } from "../shared"
|
||||
|
||||
export const ThinkingConfigSchema = Schema.Struct({
|
||||
thinkingBudget: Schema.optional(Schema.Number),
|
||||
includeThoughts: Schema.optional(Schema.Boolean),
|
||||
})
|
||||
export type ThinkingConfig = Schema.Schema.Type<typeof ThinkingConfigSchema>
|
||||
|
||||
export interface Resolved {
|
||||
readonly thinkingConfig?: ThinkingConfig
|
||||
}
|
||||
|
||||
export const resolve = (request: LLMRequest): Resolved => {
|
||||
const value = request.providerOptions?.gemini?.thinkingConfig
|
||||
if (!ProviderShared.isRecord(value)) return {}
|
||||
const thinkingConfig = {
|
||||
thinkingBudget: typeof value.thinkingBudget === "number" ? value.thinkingBudget : undefined,
|
||||
includeThoughts: typeof value.includeThoughts === "boolean" ? value.includeThoughts : undefined,
|
||||
}
|
||||
return {
|
||||
thinkingConfig: Object.values(thinkingConfig).some((item) => item !== undefined) ? thinkingConfig : undefined,
|
||||
}
|
||||
}
|
||||
|
||||
export * as GeminiOptions from "./gemini-options"
|
||||
Loading…
Add table
Add a link
Reference in a new issue