chore(vendor): import pi 0.85.1
Imported as a linear vendor commit so forge rebases do not replay the upstream root tree. git-subtree-dir: third_party/pi git-subtree-split: d981de1229ef899957bbe968bc8dcda02a21f477
This commit is contained in:
95
third_party/pi/packages/ai/src/api/simple-options.ts
vendored
Normal file
95
third_party/pi/packages/ai/src/api/simple-options.ts
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
import type {
|
||||
Api,
|
||||
Context,
|
||||
Model,
|
||||
SimpleStreamOptions,
|
||||
StreamOptions,
|
||||
ThinkingBudgets,
|
||||
ThinkingLevel,
|
||||
} from "../types.ts";
|
||||
import { estimateContextTokens } from "../utils/estimate.ts";
|
||||
|
||||
const CONTEXT_SAFETY_TOKENS = 4096;
|
||||
const MIN_MAX_TOKENS = 1;
|
||||
|
||||
export function clampMaxTokensToContext(model: Model<Api>, context: Context, maxTokens: number): number {
|
||||
if (model.contextWindow <= 0) return Math.max(MIN_MAX_TOKENS, maxTokens);
|
||||
const available = model.contextWindow - estimateContextTokens(context).tokens - CONTEXT_SAFETY_TOKENS;
|
||||
return Math.min(maxTokens, Math.max(MIN_MAX_TOKENS, available));
|
||||
}
|
||||
|
||||
export function buildBaseOptions(
|
||||
model: Model<Api>,
|
||||
context: Context,
|
||||
options?: SimpleStreamOptions,
|
||||
apiKey?: string,
|
||||
): StreamOptions {
|
||||
const samplingParams =
|
||||
model.samplingParams || options?.samplingParams
|
||||
? { ...model.samplingParams, ...options?.samplingParams }
|
||||
: undefined;
|
||||
return {
|
||||
temperature: options?.temperature,
|
||||
samplingParams,
|
||||
maxTokens: clampMaxTokensToContext(model, context, options?.maxTokens ?? model.maxTokens),
|
||||
signal: options?.signal,
|
||||
telemetryContext: options?.telemetryContext,
|
||||
apiKey: apiKey || options?.apiKey,
|
||||
fetch: options?.fetch,
|
||||
transport: options?.transport,
|
||||
cacheRetention: options?.cacheRetention,
|
||||
sessionId: options?.sessionId,
|
||||
headers: options?.headers,
|
||||
onPayload: options?.onPayload,
|
||||
onResponse: options?.onResponse,
|
||||
timeoutMs: options?.timeoutMs,
|
||||
websocketConnectTimeoutMs: options?.websocketConnectTimeoutMs,
|
||||
maxRetries: options?.maxRetries,
|
||||
maxRetryDelayMs: options?.maxRetryDelayMs,
|
||||
metadata: options?.metadata,
|
||||
env: options?.env,
|
||||
};
|
||||
}
|
||||
|
||||
/** Tokens always left for the answer when a thinking budget shares the response ceiling. */
|
||||
export const MIN_ANSWER_TOKENS = 1024;
|
||||
|
||||
export const DEFAULT_THINKING_BUDGETS: ThinkingBudgets = {
|
||||
minimal: 1024,
|
||||
low: 2048,
|
||||
medium: 8192,
|
||||
high: 16384,
|
||||
};
|
||||
|
||||
export function clampReasoning(effort: ThinkingLevel | undefined): Exclude<ThinkingLevel, "xhigh" | "max"> | undefined {
|
||||
return effort === "xhigh" || effort === "max" ? "high" : effort;
|
||||
}
|
||||
|
||||
export function thinkingBudgetForLevel(reasoningLevel: ThinkingLevel, customBudgets?: ThinkingBudgets): number {
|
||||
const budgets = { ...DEFAULT_THINKING_BUDGETS, ...customBudgets };
|
||||
const level = clampReasoning(reasoningLevel)!;
|
||||
return budgets[level]!;
|
||||
}
|
||||
|
||||
/** Cap a thinking budget so at least MIN_ANSWER_TOKENS remain under a shared response ceiling. */
|
||||
export function clampThinkingBudgetToAnswerRoom(thinkingBudget: number, ceiling: number): number {
|
||||
return Math.min(thinkingBudget, Math.max(0, ceiling - MIN_ANSWER_TOKENS));
|
||||
}
|
||||
|
||||
export function adjustMaxTokensForThinking(
|
||||
// Undefined means no explicit caller cap. Use the model cap and fit thinking inside it.
|
||||
baseMaxTokens: number | undefined,
|
||||
modelMaxTokens: number,
|
||||
reasoningLevel: ThinkingLevel,
|
||||
customBudgets?: ThinkingBudgets,
|
||||
): { maxTokens: number; thinkingBudget: number } {
|
||||
let thinkingBudget = thinkingBudgetForLevel(reasoningLevel, customBudgets);
|
||||
const maxTokens =
|
||||
baseMaxTokens === undefined ? modelMaxTokens : Math.min(baseMaxTokens + thinkingBudget, modelMaxTokens);
|
||||
|
||||
if (maxTokens <= thinkingBudget) {
|
||||
thinkingBudget = clampThinkingBudgetToAnswerRoom(thinkingBudget, maxTokens);
|
||||
}
|
||||
|
||||
return { maxTokens, thinkingBudget };
|
||||
}
|
||||
Reference in New Issue
Block a user