mirror of
https://github.com/TencentCloud/TencentDB-Agent-Memory
synced 2026-07-11 04:44:29 +00:00
feat(llm): add disableThinking option to suppress reasoning in extraction models (#228)
Support multiple inference engines and model providers via a strategy
enum so each receives its own thinking-disabling field in
chat-completion request bodies.
Strategies:
- "vllm" → chat_template_kwargs: { enable_thinking: false } (vLLM / SGLang)
- "deepseek" → enable_thinking: false (DeepSeek official API)
- "dashscope" → enable_thinking: false (Alibaba DashScope / Qwen)
- "openai" → reasoning_effort: "low" (OpenAI o-series, cannot fully disable)
- "anthropic" → thinking: { type: "disabled" } (Anthropic Claude)
- "kimi" → thinking: { type: "disabled" } (Kimi / Moonshot)
- "gemini" → thinking_config: { thinking_budget: 0 } (Google Gemini)
Defaults to false (no wrapper). Also accepts boolean true as a shorthand
for "vllm" for convenience.
Covered paths:
- StandaloneLLMRunner (OpenClaw plugin + gateway): llm.disableThinking,
wired through parseConfig, tdai-core, seed-runtime, and gateway config
(TDAI_LLM_DISABLE_THINKING env also accepts strategy names).
- Offload local mode (L1/L1.5/L2): separate offload.disableThinking.
The fetch wrapper lives in src/utils/no-think-fetch.ts with a
STRATEGY_TRANSFORMERS map for clean dispatch. StandaloneLLMRunner builds
it once in the constructor; LocalLlmClient caches it at construction
time and passes it through to callLlm().
Add vitest unit tests for all 7 strategies, normalization, validation,
embedding skip, and non-JSON tolerance (20 tests total).
Signed-off-by: jackson.jia <jiazhenghua0@gmail.com>
This commit is contained in:
@@ -376,7 +376,7 @@ export function registerOffload(api: any, offloadConfig: OffloadConfig): void {
|
||||
|
||||
if (baseUrl && apiKey) {
|
||||
backendClient = new LocalLlmClient(
|
||||
{ baseUrl, apiKey, model: modelId, temperature: offloadConfig.temperature, timeoutMs: offloadConfig.backendTimeoutMs },
|
||||
{ baseUrl, apiKey, model: modelId, temperature: offloadConfig.temperature, timeoutMs: offloadConfig.backendTimeoutMs, disableThinking: offloadConfig.disableThinking },
|
||||
logger,
|
||||
);
|
||||
} else {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* Used when `offload.model` is configured and `offload.backendUrl` is not set.
|
||||
*/
|
||||
import { callLlm, type LlmCallerConfig } from "./llm-caller.js";
|
||||
import { createNoThinkFetch, type DisableThinkingStrategy } from "../../utils/no-think-fetch.js";
|
||||
import { L1_SYSTEM_PROMPT, buildL1UserPrompt, type L1ToolPair } from "./prompts/l1-prompt.js";
|
||||
import { L15_SYSTEM_PROMPT, buildL15UserPrompt, type L15CurrentMmd, type L15MmdMeta } from "./prompts/l15-prompt.js";
|
||||
import { L2_SYSTEM_PROMPT, buildL2UserPrompt, type L2NewEntry } from "./prompts/l2-prompt.js";
|
||||
@@ -24,11 +25,13 @@ export interface LocalLlmClientConfig {
|
||||
model: string;
|
||||
temperature?: number;
|
||||
timeoutMs?: number;
|
||||
disableThinking?: DisableThinkingStrategy;
|
||||
}
|
||||
|
||||
export class LocalLlmClient {
|
||||
private config: LlmCallerConfig;
|
||||
private logger?: PluginLogger;
|
||||
private readonly customFetch?: typeof globalThis.fetch;
|
||||
|
||||
constructor(cfg: LocalLlmClientConfig, logger?: PluginLogger) {
|
||||
this.config = {
|
||||
@@ -37,8 +40,15 @@ export class LocalLlmClient {
|
||||
model: cfg.model,
|
||||
temperature: cfg.temperature ?? 0.2,
|
||||
timeoutMs: cfg.timeoutMs ?? 120_000,
|
||||
disableThinking: cfg.disableThinking ?? false,
|
||||
};
|
||||
this.logger = logger;
|
||||
|
||||
// Cache the fetch wrapper at construction time — avoids per-call creation.
|
||||
this.customFetch = cfg.disableThinking
|
||||
? createNoThinkFetch(cfg.disableThinking)
|
||||
: undefined;
|
||||
|
||||
logger?.info?.(`${TAG} Initialized: model=${cfg.model}, baseUrl=${cfg.baseUrl}`);
|
||||
}
|
||||
|
||||
@@ -59,6 +69,7 @@ export class LocalLlmClient {
|
||||
systemPrompt: L1_SYSTEM_PROMPT,
|
||||
userPrompt,
|
||||
label: "L1",
|
||||
customFetch: this.customFetch,
|
||||
}, this.logger);
|
||||
|
||||
const entries = parseL1Response(raw);
|
||||
@@ -97,6 +108,7 @@ export class LocalLlmClient {
|
||||
systemPrompt: L15_SYSTEM_PROMPT,
|
||||
userPrompt,
|
||||
label: "L1.5",
|
||||
customFetch: this.customFetch,
|
||||
}, this.logger);
|
||||
|
||||
const result = parseL15Response(raw);
|
||||
@@ -138,6 +150,7 @@ export class LocalLlmClient {
|
||||
userPrompt,
|
||||
label: "L2",
|
||||
timeoutMs: 120_000, // L2 may take longer due to complex prompts
|
||||
customFetch: this.customFetch,
|
||||
}, this.logger);
|
||||
|
||||
const result = parseL2Response(raw);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
import { generateText } from "ai";
|
||||
import { createOpenAI } from "@ai-sdk/openai";
|
||||
import { createNoThinkFetch, type DisableThinkingStrategy } from "../../utils/no-think-fetch.js";
|
||||
import type { PluginLogger } from "../types.js";
|
||||
|
||||
const TAG = "[context-offload] [local-llm]";
|
||||
@@ -16,6 +17,11 @@ export interface LlmCallerConfig {
|
||||
model: string;
|
||||
temperature: number;
|
||||
timeoutMs: number;
|
||||
/**
|
||||
* Controls how thinking/reasoning is disabled for the LLM endpoint.
|
||||
* See DisableThinkingStrategy for the full list of strategies.
|
||||
*/
|
||||
disableThinking?: DisableThinkingStrategy;
|
||||
}
|
||||
|
||||
export interface CallLlmOpts {
|
||||
@@ -27,6 +33,8 @@ export interface CallLlmOpts {
|
||||
timeoutMs?: number;
|
||||
/** Label for logging (e.g. "L1", "L1.5", "L2") */
|
||||
label?: string;
|
||||
/** Pre-created fetch wrapper (for caching at the client level). */
|
||||
customFetch?: typeof globalThis.fetch;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,10 +56,15 @@ export async function callLlm(
|
||||
`systemLen=${opts.systemPrompt.length}, userLen=${opts.userPrompt.length}`,
|
||||
);
|
||||
|
||||
const customFetch = opts.customFetch ?? (
|
||||
config.disableThinking ? createNoThinkFetch(config.disableThinking) : undefined
|
||||
);
|
||||
|
||||
const provider = createOpenAI({
|
||||
baseURL: config.baseUrl,
|
||||
apiKey: config.apiKey,
|
||||
compatibility: "compatible",
|
||||
...(customFetch ? { fetch: customFetch } : {}),
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user