-
-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Fix:Add KimiExecutor to fix the error of reasoning_content is missing in kimi thing mode #3132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
|
|
||
| import { DefaultExecutor } from "./default.ts"; | ||
| type JsonRecord = Record<string, unknown>; | ||
| import { | ||
| type ProviderCredentials, | ||
| } from "./base.ts"; | ||
|
|
||
| import { applyProviderRequestDefaults } from "../services/providerRequestDefaults.ts"; | ||
|
|
||
| function hasActiveKimiThinking(body: JsonRecord): boolean { | ||
| const reasoningEffort = body.reasoning_effort; | ||
| if (typeof reasoningEffort === "string") { | ||
| const normalized = reasoningEffort.trim().toLowerCase(); | ||
| if (normalized && normalized !== "off" && normalized !== "none") return true; | ||
| } | ||
|
|
||
| const reasoning = body.reasoning; | ||
| if (reasoning && typeof reasoning === "object" && !Array.isArray(reasoning)) { | ||
| const reasoningRecord = reasoning as JsonRecord; | ||
| const effort = reasoningRecord.effort; | ||
| if (typeof effort === "string") { | ||
| const normalized = effort.trim().toLowerCase(); | ||
| if (normalized && normalized !== "off" && normalized !== "none") return true; | ||
| } | ||
| if (reasoningRecord.enabled === true || reasoningRecord.type === "enabled") return true; | ||
| } | ||
|
|
||
| const thinking = body.thinking; | ||
| if (thinking && typeof thinking === "object" && !Array.isArray(thinking)) { | ||
| const thinkingRecord = thinking as JsonRecord; | ||
| return thinkingRecord.type === "enabled" || thinkingRecord.type === "adaptive"; | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| function ensureToolCallReasoningContent(body: JsonRecord): JsonRecord { | ||
| if (!hasActiveKimiThinking(body) || !Array.isArray(body.messages)) return body; | ||
|
|
||
| let changed = false; | ||
| const messages = body.messages.map((message: unknown) => { | ||
| if (!message || typeof message !== "object" || Array.isArray(message)) return message; | ||
|
|
||
| const msg = message as JsonRecord; | ||
| if (msg.role !== "assistant" || !Array.isArray(msg.tool_calls)) return message; | ||
| if (Object.prototype.hasOwnProperty.call(msg, "reasoning_content")) return message; | ||
|
|
||
| changed = true; | ||
| return { ...msg, reasoning_content: "" }; | ||
| }); | ||
|
|
||
| return changed ? { ...body, messages } : body; | ||
| } | ||
|
|
||
| function hasTools(body: unknown): boolean { | ||
| const record = asRecord(body); | ||
| return Array.isArray(record?.tools) && record.tools.length > 0; | ||
| } | ||
|
|
||
|
|
||
| function asRecord(value: unknown): JsonRecord | null { | ||
| return value && typeof value === "object" && !Array.isArray(value) ? (value as JsonRecord) : null; | ||
| } | ||
|
|
||
| function applyKimiRequestDefaults(body: unknown, defaults?: JsonRecord | null): unknown { | ||
| const withDefaults = applyProviderRequestDefaults(body, defaults); | ||
| const record = asRecord(withDefaults); | ||
| if (record && hasActiveKimiThinking(record) && hasTools(record)) { | ||
| return ensureToolCallReasoningContent(record); | ||
| } | ||
| return withDefaults; | ||
| } | ||
|
Comment on lines
+65
to
+72
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In Furthermore, if thinking is enabled via the defaults rather than the initial request body, To fix this, apply the provider request defaults first, and then perform the Kimi-specific check and transformation on the resulting object. function applyKimiRequestDefaults(body: unknown, defaults?: JsonRecord | null): unknown {
const withDefaults = applyProviderRequestDefaults(body, defaults);
const record = asRecord(withDefaults);
if (record && hasActiveKimiThinking(record) && hasTools(record)) {
// 此处 kimi 开启了 thinking 功能且存在工具调用,确保 tool_calls 中包含 reasoning_content 字段以兼容老版本 Kimi 后端的要求
return ensureToolCallReasoningContent(record);
}
return withDefaults;
} |
||
|
|
||
| export class KimiExecutor extends DefaultExecutor { | ||
| constructor(provider = "kimi-coding") { | ||
| super(provider); | ||
| } | ||
|
Comment on lines
+74
to
+77
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to the Repository Style Guide (Rule 9), tests must always be included when changing or adding production code in References
|
||
|
|
||
| transformRequest( | ||
| model: string, | ||
| body: unknown, | ||
| stream: boolean, | ||
| credentials: ProviderCredentials | ||
| ) { | ||
| const cleanedBody = super.transformRequest(model, body, stream, credentials); | ||
| return applyKimiRequestDefaults(cleanedBody); | ||
| } | ||
| } | ||
|
|
||
| export default KimiExecutor; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently,
"kimi-coding-apikey"is registered usingnew KimiExecutor(), which defaults the internalprovidername to"kimi-coding". This means any provider-specific checks or configurations matching"kimi-coding-apikey"will not be correctly resolved within the executor instance.Additionally, the
"kimi-coding"provider itself is not registered to useKimiExecutor, meaning it will not benefit from thereasoning_contentfix when thinking mode is active.To resolve this, pass the correct provider name to the constructor for both
"kimi-coding"and"kimi-coding-apikey", and register both to useKimiExecutor.