



















@@ -1,7 +1,10 @@
11import type { StreamFn } from "@mariozechner/pi-agent-core";
22import type { ProviderWrapStreamFnContext } from "openclaw/plugin-sdk/plugin-entry";
33import { normalizeProviderId } from "openclaw/plugin-sdk/provider-model-shared";
4-import { createPayloadPatchStreamWrapper } from "openclaw/plugin-sdk/provider-stream-shared";
4+import {
5+createPayloadPatchStreamWrapper,
6+isOpenAICompatibleThinkingEnabled,
7+} from "openclaw/plugin-sdk/provider-stream-shared";
5869type VllmThinkingLevel = ProviderWrapStreamFnContext["thinkingLevel"];
710type VllmQwenThinkingFormat = "chat-template" | "top-level";
@@ -41,19 +44,6 @@ function resolveVllmQwenThinkingFormat(
4144);
4245}
434644-function resolveOpenAICompatibleThinkingEnabled(params: {
45-thinkingLevel: VllmThinkingLevel;
46-options: Parameters<StreamFn>[2];
47-}): boolean {
48-const options = (params.options ?? {}) as { reasoningEffort?: unknown; reasoning?: unknown };
49-const raw = options.reasoningEffort ?? options.reasoning ?? params.thinkingLevel ?? "high";
50-if (typeof raw !== "string") {
51-return true;
52-}
53-const normalized = raw.trim().toLowerCase();
54-return normalized !== "off" && normalized !== "none";
55-}
56-5747function setQwenChatTemplateThinking(payload: Record<string, unknown>, enabled: boolean): void {
5848const existing = payload.chat_template_kwargs;
5949if (existing && typeof existing === "object" && !Array.isArray(existing)) {
@@ -73,6 +63,31 @@ function setQwenChatTemplateThinking(payload: Record<string, unknown>, enabled:
7363};
7464}
756566+function isVllmNemotronModel(model: { api?: unknown; provider?: unknown; id?: unknown }): boolean {
67+return (
68+model.api === "openai-completions" &&
69+typeof model.provider === "string" &&
70+normalizeProviderId(model.provider) === "vllm" &&
71+typeof model.id === "string" &&
72+/\bnemotron-3(?:[-_](?:nano|super|ultra))?\b/i.test(model.id)
73+);
74+}
75+76+function setNemotronThinkingOffChatTemplateKwargs(payload: Record<string, unknown>): void {
77+const defaults = {
78+enable_thinking: false,
79+force_nonempty_content: true,
80+};
81+const existing = payload.chat_template_kwargs;
82+payload.chat_template_kwargs =
83+existing && typeof existing === "object" && !Array.isArray(existing)
84+ ? {
85+ ...defaults,
86+ ...(existing as Record<string, unknown>),
87+}
88+ : defaults;
89+}
90+7691export function createVllmQwenThinkingWrapper(params: {
7792baseStreamFn: StreamFn | undefined;
7893format: VllmQwenThinkingFormat;
@@ -81,7 +96,7 @@ export function createVllmQwenThinkingWrapper(params: {
8196return createPayloadPatchStreamWrapper(
8297params.baseStreamFn,
8398({ payload: payloadObj, options }) => {
84-const enableThinking = resolveOpenAICompatibleThinkingEnabled({
99+const enableThinking = isOpenAICompatibleThinkingEnabled({
85100thinkingLevel: params.thinkingLevel,
86101 options,
87102});
@@ -100,17 +115,50 @@ export function createVllmQwenThinkingWrapper(params: {
100115);
101116}
102117118+export function createVllmProviderThinkingWrapper(params: {
119+baseStreamFn: StreamFn | undefined;
120+qwenFormat?: VllmQwenThinkingFormat;
121+thinkingLevel: VllmThinkingLevel;
122+}): StreamFn {
123+const qwenWrapped = params.qwenFormat
124+ ? createVllmQwenThinkingWrapper({
125+baseStreamFn: params.baseStreamFn,
126+format: params.qwenFormat,
127+thinkingLevel: params.thinkingLevel,
128+})
129+ : params.baseStreamFn;
130+return createPayloadPatchStreamWrapper(
131+qwenWrapped,
132+({ payload: payloadObj }) => {
133+setNemotronThinkingOffChatTemplateKwargs(payloadObj);
134+},
135+{
136+shouldPatch: ({ model }) =>
137+model.api === "openai-completions" &&
138+params.thinkingLevel === "off" &&
139+isVllmNemotronModel(model),
140+},
141+);
142+}
143+103144export function wrapVllmProviderStream(ctx: ProviderWrapStreamFnContext): StreamFn | undefined {
104145if (!isVllmProviderId(ctx.provider) || (ctx.model && ctx.model.api !== "openai-completions")) {
105146return undefined;
106147}
107-const format = resolveVllmQwenThinkingFormat(ctx.extraParams);
108-if (!format) {
148+const qwenFormat = resolveVllmQwenThinkingFormat(ctx.extraParams);
149+const shouldHandleNemotron =
150+ctx.thinkingLevel === "off" &&
151+isVllmNemotronModel({
152+api: "openai-completions",
153+provider: ctx.provider,
154+id: ctx.modelId,
155+});
156+if (!qwenFormat && !shouldHandleNemotron) {
109157return undefined;
110158}
111-return createVllmQwenThinkingWrapper({
159+return createVllmProviderThinkingWrapper({
112160baseStreamFn: ctx.streamFn,
113-format,
161+qwenFormat,
114162thinkingLevel: ctx.thinkingLevel,
115163});
116164}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。