-
-
Notifications
You must be signed in to change notification settings - Fork 41
chore: 发布 alpha.43/alpha.5 版本并修复工具调用问题 #554
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
Conversation
Update all package versions and dependencies across the monorepo for the new release cycle.
- Migrate from deprecated additional_kwargs.tool_calls to AIMessage.tool_calls property - Update Qwen, Spark, and Zhipu adapters to use standardized tool_calls format - Remove unused tool_calls handling in shared utilities - Ensure consistent tool call serialization across all adapters
- Bump core package to 1.3.0-alpha.43 - Bump all adapter packages to 1.3.0-alpha.5 - Bump search-service to 1.2.9 - Bump vector-store-service to 1.2.8 - Update peer dependencies to match new core version
|
Important Review skippedReview was skipped due to path filters ⛔ Files ignored due to path filters (2)
CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including You can disable this status message by setting the Walkthrough本次变更在多个适配器的 utils 中统一了对 AIMessage 的 Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant C as Caller
participant U as Adapter Utils
participant P as Provider API
C->>U: langchain Message
alt rawMessage.getType() == "ai"
U->>U: 读取 AIMessage.tool_calls
opt 存在非空 tool_calls
U->>U: 映射为 {id, type:"function", function:{name, arguments(JSON)}}
U->>P: 提交 Provider 消息(含 tool_calls)
end
else 非 AI
U->>P: 提交 Provider 消息(不含 tool_calls)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (7)
packages/spark-adapter/src/utils.ts (3)
84-98: 空数组访问会崩溃:当仅包含 system 且 removeSystemMessage=true 时,result 为空
result[result.length - 1]与result[0]在空数组上会抛异常。需要加长度保护。- if (result[result.length - 1].role === 'assistant') { + if (result.length > 0 && result[result.length - 1].role === 'assistant') { result.push({ role: 'user', content: 'Continue what I said to you last message. Follow these instructions.' }) } - if (result[0].role === 'assistant') { + if (result.length > 0 && result[0].role === 'assistant') { result.unshift({ role: 'user', content: 'Continue what I said to you last time. Follow these instructions.' }) }
154-161: 返回 undefined 与签名不匹配,TS 会报错
formatToolsToSparkTools在空数组时返回undefined,但签名是ChatCompletionTool[]。要么返回空数组,要么放宽签名。建议放宽返回类型,避免下游误用:
-export function formatToolsToSparkTools( - tools: StructuredTool[] -): ChatCompletionTool[] { +export function formatToolsToSparkTools( + tools: StructuredTool[] +): ChatCompletionTool[] | undefined { if (tools.length < 1) { return undefined } return tools.map(formatToolToSparkTool) }如更倾向总是返回数组,也可改为
return []并保留原签名。
103-126: 改为写入 AIMessageChunk.tool_calls(已确认 LangChain 支持)AIMessageChunk/AIMessage 已支持 tool_calls(JS 文档与指南;@langchain/core 在 0.2.9 及后续版本对 OpenAI-formatted tools 有相关支持)。将增量块的 tool_calls 直接写入 chunk.tool_calls,旧版兼容时保留 additional_kwargs 回退。
File: packages/spark-adapter/src/utils.ts
Lines: 103-126- if (delta.tool_calls && delta.tool_calls.length > 0) { - chunk.additional_kwargs.tool_calls = delta.tool_calls.map( + if (delta.tool_calls && delta.tool_calls.length > 0) { + // 若 AIMessageChunk 支持 tool_calls 字段,优先使用之;否则维持 additional_kwargs 以兼容旧路径 + (chunk as any).tool_calls = delta.tool_calls.map( (toolCall) => ({ id: toolCall.id, type: toolCall.type, function: { name: toolCall.function.name, arguments: toolCall.function.arguments } }) ) }packages/qwen-adapter/src/utils.ts (4)
68-77: 为 function 消息补充 name,避免把 name 赋给 tool 消息。函数调用返回(function/function role)通常需要携带函数名,而 tool 消息一般不需要 name。当前条件将 name 赋给 tool,且 function 未赋值,可能导致供应商拒绝或丢失上下文。
应用以下修正:
- name: - role === 'assistant' || role === 'tool' - ? rawMessage.name - : undefined, + name: + role === 'assistant' || role === 'function' + ? rawMessage.name + : undefined,
102-112: arguments 规范化缺少异常捕获,非 JSON 字符串会抛错。当前对每个 tool.arguments 直接 JSON.parse,若为普通字符串将报错并中断请求。
应用 try/catch 降级处理:
- // Remove spaces, new line characters etc. - tool.arguments = JSON.stringify(JSON.parse(tool.arguments)) + // 规范化可解析的 JSON;否则保留原值 + try { + tool.arguments = JSON.stringify(JSON.parse(tool.arguments)) + } catch { + /* noop */ + }
114-116: 潜在空指针:rawMessage.additional_kwargs 可能为 undefined。直接访问
.images有 NPE 风险,违背“空值安全检查”目标。建议使用可选链并保持类型断言:
- const images = rawMessage.additional_kwargs.images as string[] | null + const images = (rawMessage as any).additional_kwargs?.images as string[] | null
193-196: fix: role 可能为 undefined,toLowerCase 会崩溃。当 delta.role 为空且 defaultRole 未传入时,.toLowerCase() 调用会抛错。
建议保证回退值:
- const role = ( - (delta.role?.length ?? 0) > 0 ? delta.role : defaultRole - ).toLowerCase() + const rawRole = + ((delta.role?.length ?? 0) > 0 ? delta.role : defaultRole) ?? 'assistant' + const role = rawRole.toLowerCase()
🧹 Nitpick comments (5)
packages/spark-adapter/src/utils.ts (2)
33-46: tool_calls 映射方向正确;arguments 建议做“字符串或对象”双分支以更健壮
当前总是JSON.stringify(toolCall.args);当上游已提供字符串时会出现二次转义。建议按类型处理,保持与其他适配器一致。- msg.tool_calls = toolCalls.map((toolCall) => ({ + msg.tool_calls = toolCalls.map((toolCall) => ({ id: toolCall.id, type: 'function', function: { name: toolCall.name, - arguments: JSON.stringify(toolCall.args) + arguments: + typeof (toolCall as any).args === 'string' + ? (toolCall as any).args + : JSON.stringify((toolCall as any).args) } }))
71-81: 硬编码英文提示文本,建议走 i18n 或最少抽常量
在多语言环境下固定英文回复可能影响体验,且不便于后续调整。可将固定文案提取到 constants 并/或接入现有 i18n 方案。
Also applies to: 84-98
packages/shared/src/utils.ts (2)
49-49: 建议移除注释掉的代码这行被注释掉的
function_call代码已被新的tool_calls实现替代,应该被移除以保持代码整洁。应用以下修改来移除过时的注释代码:
- // function_call: rawMessage.additional_kwargs.function_call,
53-59: 确认:msg.tool_calls 的空值删除不会导致错误delete 语句在赋值之前(53–59 行)执行,但删除不存在的属性无副作用;后续在 rawMessage.getType() === 'ai' 分支(61–74 行)满足条件时会重新赋值,逻辑正确。可选:为可读性将 53–59 行的删除逻辑移到 74 行之后或直接移除初始的 delete(非必须)。
packages/qwen-adapter/src/utils.ts (1)
199-205: additionalKwargs 的类型声明包含未使用字段。function_call 与 tool_calls 未被填充,易误导维护者。
可精简为仅保留 reasoning_content:
- const additionalKwargs: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/naming-convention - function_call?: any - // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/naming-convention - tool_calls?: any - reasoning_content?: string - } = {} + const additionalKwargs: { reasoning_content?: string } = {}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (26)
packages/azure-openai-adapter/package.jsonis excluded by!**/*.jsonpackages/claude-adapter/package.jsonis excluded by!**/*.jsonpackages/core/package.jsonis excluded by!**/*.jsonpackages/deepseek-adapter/package.jsonis excluded by!**/*.jsonpackages/dify-adapter/package.jsonis excluded by!**/*.jsonpackages/doubao-adapter/package.jsonis excluded by!**/*.jsonpackages/embeddings-service/package.jsonis excluded by!**/*.jsonpackages/gemini-adapter/package.jsonis excluded by!**/*.jsonpackages/hunyuan-adapter/package.jsonis excluded by!**/*.jsonpackages/image-renderer/package.jsonis excluded by!**/*.jsonpackages/image-service/package.jsonis excluded by!**/*.jsonpackages/long-memory/package.jsonis excluded by!**/*.jsonpackages/mcp-client/package.jsonis excluded by!**/*.jsonpackages/ollama-adapter/package.jsonis excluded by!**/*.jsonpackages/openai-adapter/package.jsonis excluded by!**/*.jsonpackages/openai-like-adapter/package.jsonis excluded by!**/*.jsonpackages/plugin-common/package.jsonis excluded by!**/*.jsonpackages/qwen-adapter/package.jsonis excluded by!**/*.jsonpackages/rwkv-adapter/package.jsonis excluded by!**/*.jsonpackages/search-service/package.jsonis excluded by!**/*.jsonpackages/shared/package.jsonis excluded by!**/*.jsonpackages/spark-adapter/package.jsonis excluded by!**/*.jsonpackages/variable-extension/package.jsonis excluded by!**/*.jsonpackages/vector-store-service/package.jsonis excluded by!**/*.jsonpackages/wenxin-adapter/package.jsonis excluded by!**/*.jsonpackages/zhipu-adapter/package.jsonis excluded by!**/*.json
📒 Files selected for processing (4)
packages/qwen-adapter/src/utils.ts(3 hunks)packages/shared/src/utils.ts(3 hunks)packages/spark-adapter/src/utils.ts(2 hunks)packages/zhipu-adapter/src/utils.ts(2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-15T17:40:57.183Z
Learnt from: dingyi222666
PR: ChatLunaLab/chatluna#546
File: packages/core/src/llm-core/chat/app.ts:114-119
Timestamp: 2025-09-15T17:40:57.183Z
Learning: 在 ChatLuna 的 packages/core/src/llm-core/chat/app.ts 中,displayResponse 的构造只需要保留 content 和 additional_kwargs,tool_calls、tool_call_id、name、id 等元数据在代码库的其他地方处理,无需在 displayResponse 中保留这些字段。
Applied to files:
packages/spark-adapter/src/utils.ts
🧬 Code graph analysis (3)
packages/qwen-adapter/src/utils.ts (2)
packages/zhipu-adapter/src/types.ts (1)
ChatCompletionResponseMessage(25-44)packages/qwen-adapter/src/types.ts (1)
ChatCompletionResponseMessage(24-45)
packages/zhipu-adapter/src/utils.ts (1)
packages/zhipu-adapter/src/types.ts (1)
ChatCompletionResponseMessage(25-44)
packages/spark-adapter/src/utils.ts (1)
packages/spark-adapter/src/types.ts (1)
ChatCompletionMessage(110-116)
🔇 Additional comments (8)
packages/spark-adapter/src/utils.ts (2)
2-2: 导入 AIMessage 用于标准化 tool_calls:LGTM
与本 PR 的迁移目标一致,所需类型已正确引入。
48-48: 返回已构造的 msg:LGTM
与上方条件追加 tool_calls 的策略一致。packages/shared/src/utils.ts (2)
2-2: 正确迁移到标准工具调用接口添加 AIMessage 导入支持了从旧的
additional_kwargs.tool_calls到新的标准AIMessage.tool_calls属性的迁移。这符合 LangChain 的最新工具调用接口标准。
61-74: LGTM:正确实现类型安全的工具调用处理这个实现正确地:
- 仅对 AI 类型消息提取工具调用
- 将工具调用映射为标准格式,包含 id、type 和 function 对象
- 正确序列化参数为 JSON 字符串
与 PR 目标和其他适配器的实现保持一致。
packages/zhipu-adapter/src/utils.ts (2)
2-2: LGTM: 正确引入 AIMessage 类型从 LangChain 的文档可以看出,工具调用处理已经从
AIMessage.additional_kwargs迁移到标准的AIMessage.tool_calls属性。正确引入AIMessage类型是实现这一迁移的必要步骤。
48-61: LGTM: 正确实现工具调用处理的标准化迁移这段代码正确实现了从已弃用的
additional_kwargs.tool_calls到标准AIMessage.tool_calls属性的迁移:
- 类型检查: 只有当消息类型为 'ai' 时才处理工具调用
- 标准格式: 将工具调用映射为标准的 ToolCall 格式,包含 id、type 为 'function' 和 function 对象(包含 name 和 JSON 字符串化的 arguments)
- 空值安全: 检查
toolCalls是否为数组且长度大于 0这与其他适配器的实现保持一致,符合 PR 目标中提到的统一工具调用处理的要求。
packages/qwen-adapter/src/utils.ts (2)
1-12: 引入 AIMessage 合理,与下方对 AIMessage.tool_calls 的使用一致。
171-186: 确认 'function' 角色是否为 Qwen 可接受角色;必要时映射为 'tool'。部分供应商已弃用 'function' 角色,统一使用 'tool'。当前实现返回 'function' 可能导致请求被拒。
若确认不支持 'function',建议调整如下:
- case 'function': - return 'function' + case 'function': + return 'tool'并与上文 name 赋值逻辑保持一致(function -> name,tool -> 无 name)。
此 PR 包含版本更新和重要的工具调用修复。
主要更改
additional_kwargs.tool_calls迁移到标准的AIMessage.tool_calls属性版本更新
Bug 修复
其他更改
Close #550