
























11import { AzureOpenAI } from "openai";
22import type { ResponseCreateParamsStreaming } from "openai/resources/responses/responses.js";
33import { getEnvApiKey } from "../env-api-keys.js";
4-import { clampThinkingLevel } from "../model-utils.js";
54import type {
6-Api,
7-AssistantMessage,
85Context,
96Model,
107SimpleStreamOptions,
118StreamFunction,
129StreamOptions,
1310} from "../types.js";
1411import { AssistantMessageEventStream } from "../utils/event-stream.js";
15-import { headersToRecord } from "../utils/headers.js";
1612import { resolveAzureDeploymentNameFromMap } from "./azure-deployment-map.js";
1713import { clampOpenAIPromptCacheKey } from "./openai-prompt-cache.js";
1814import {
15+applyCommonResponsesParams,
1916convertResponsesMessages,
20-convertResponsesTools,
21-processResponsesStream,
17+createResponsesAssistantOutput,
18+resolveResponsesReasoningEffort,
19+runResponsesStreamLifecycle,
2220} from "./openai-responses-shared.js";
2321import { buildBaseOptions } from "./simple-options.js";
2422@@ -81,76 +79,21 @@ export const streamAzureOpenAIResponses: StreamFunction<
8179options?: AzureOpenAIResponsesOptions,
8280) => {
8381const stream = new AssistantMessageEventStream();
82+const output = createResponsesAssistantOutput(model, "azure-openai-responses");
84838584// Start async processing
86-void (async () => {
87-const deploymentName = resolveDeploymentName(model, options);
88-89-const output: AssistantMessage = {
90-role: "assistant",
91-content: [],
92-api: "azure-openai-responses" as Api,
93-provider: model.provider,
94-model: model.id,
95-usage: {
96-input: 0,
97-output: 0,
98-cacheRead: 0,
99-cacheWrite: 0,
100-totalTokens: 0,
101-cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
102-},
103-stopReason: "stop",
104-timestamp: Date.now(),
105-};
106-107-try {
108-// Create Azure OpenAI client
85+void runResponsesStreamLifecycle({
86+ stream,
87+ model,
88+ output,
89+ options,
90+createClient: () => {
10991const apiKey = options?.apiKey || getEnvApiKey(model.provider) || "";
110-const client = createClient(model, apiKey, options);
111-let params = buildParams(model, context, options, deploymentName);
112-const nextParams = await options?.onPayload?.(params, model);
113-if (nextParams !== undefined) {
114-params = nextParams as ResponseCreateParamsStreaming;
115-}
116-const requestOptions = {
117- ...(options?.signal ? { signal: options.signal } : {}),
118- ...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),
119- ...(options?.maxRetries !== undefined ? { maxRetries: options.maxRetries } : {}),
120-};
121-const { data: openaiStream, response } = await client.responses
122-.create(params, requestOptions)
123-.withResponse();
124-await options?.onResponse?.(
125-{ status: response.status, headers: headersToRecord(response.headers) },
126-model,
127-);
128-stream.push({ type: "start", partial: output });
129-130-await processResponsesStream(openaiStream, output, stream, model);
131-132-if (options?.signal?.aborted) {
133-throw new Error("Request was aborted");
134-}
135-136-if (output.stopReason === "aborted" || output.stopReason === "error") {
137-throw new Error("An unknown error occurred");
138-}
139-140-stream.push({ type: "done", reason: output.stopReason, message: output });
141-stream.end();
142-} catch (error) {
143-for (const block of output.content) {
144-delete (block as { index?: number }).index;
145-// partialJson is only a streaming scratch buffer; never persist it.
146-delete (block as { partialJson?: string }).partialJson;
147-}
148-output.stopReason = options?.signal?.aborted ? "aborted" : "error";
149-output.errorMessage = formatAzureOpenAIError(error);
150-stream.push({ type: "error", reason: output.stopReason, error: output });
151-stream.end();
152-}
153-})();
92+return createClient(model, apiKey, options);
93+},
94+buildParams: () => buildParams(model, context, options, resolveDeploymentName(model, options)),
95+formatError: formatAzureOpenAIError,
96+});
1549715598return stream;
15699};
@@ -165,19 +108,10 @@ export const streamSimpleAzureOpenAIResponses: StreamFunction<
165108}
166109167110const base = buildBaseOptions(model, options, apiKey);
168-const clampedReasoning = options?.reasoning
169- ? clampThinkingLevel(model, options.reasoning)
170- : undefined;
171-const reasoningEffort =
172-clampedReasoning === "off"
173- ? undefined
174- : clampedReasoning === "max"
175- ? "xhigh"
176- : clampedReasoning;
177111178112return streamAzureOpenAIResponses(model, context, {
179113 ...base,
180- reasoningEffort,
114+reasoningEffort: resolveResponsesReasoningEffort(model, options?.reasoning),
181115} satisfies AzureOpenAIResponsesOptions);
182116};
183117@@ -294,36 +228,7 @@ function buildParams(
294228 : clampOpenAIPromptCacheKey(options?.promptCacheKey ?? options?.sessionId),
295229};
296230297-if (options?.maxTokens) {
298-params.max_output_tokens = options?.maxTokens;
299-}
300-301-if (options?.temperature !== undefined) {
302-params.temperature = options?.temperature;
303-}
304-305-if (context.tools && context.tools.length > 0) {
306-params.tools = convertResponsesTools(context.tools, { model });
307-}
308-309-if (model.reasoning) {
310-if (options?.reasoningEffort || options?.reasoningSummary) {
311-const effort = options?.reasoningEffort
312- ? (model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort)
313- : "medium";
314-params.reasoning = {
315-effort: effort as NonNullable<typeof params.reasoning>["effort"],
316-summary: options?.reasoningSummary || "auto",
317-};
318-params.include = ["reasoning.encrypted_content"];
319-} else if (model.thinkingLevelMap?.off !== null) {
320-params.reasoning = {
321-effort: (model.thinkingLevelMap?.off ?? "none") as NonNullable<
322-typeof params.reasoning
323->["effort"],
324-};
325-}
326-}
231+applyCommonResponsesParams(params, model, context, options);
327232328233return params;
329234}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。