From 7114cef03e3cbad99a733fe5b9ab1200cd9b4f26 Mon Sep 17 00:00:00 2001 From: lightrabbit Date: Tue, 11 Mar 2025 14:13:17 +0800 Subject: [PATCH] feat: openai-compatible deepseek/qwq reasoning support --- src/api/providers/openai.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/api/providers/openai.ts b/src/api/providers/openai.ts index a6e3eb14881..ee6137133c6 100644 --- a/src/api/providers/openai.ts +++ b/src/api/providers/openai.ts @@ -14,6 +14,7 @@ import { convertToR1Format } from "../transform/r1-format" import { convertToSimpleMessages } from "../transform/simple-format" import { ApiStream, ApiStreamUsageChunk } from "../transform/stream" import { BaseProvider } from "./base-provider" +import { XmlMatcher } from "../../utils/xml-matcher" const DEEP_SEEK_DEFAULT_TEMPERATURE = 0.6 @@ -99,15 +100,23 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl const stream = await this.client.chat.completions.create(requestOptions) + const matcher = new XmlMatcher( + "think", + (chunk) => + ({ + type: chunk.matched ? "reasoning" : "text", + text: chunk.data, + }) as const, + ) + let lastUsage for await (const chunk of stream) { const delta = chunk.choices[0]?.delta ?? {} if (delta.content) { - yield { - type: "text", - text: delta.content, + for (const chunk of matcher.update(delta.content)) { + yield chunk } } @@ -121,6 +130,9 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl lastUsage = chunk.usage } } + for (const chunk of matcher.final()) { + yield chunk + } if (lastUsage) { yield this.processUsageMetrics(lastUsage, modelInfo)