Skip to content

feat(llm): LLM module protocol optimization - #429

Open
openjiuwen-sync-bot[bot] wants to merge 1 commit into
openJiuwen-ai:developfrom
openjiuwenai:sync/pr-2257
Open

feat(llm): LLM module protocol optimization#429
openjiuwen-sync-bot[bot] wants to merge 1 commit into
openJiuwen-ai:developfrom
openjiuwenai:sync/pr-2257

Conversation

@openjiuwen-sync-bot

@openjiuwen-sync-bot openjiuwen-sync-bot Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Paired: GitHub #429GitCode !2257

What type of PR is this?

/kind bug

Self-checklist:(请自检,在[ ]内打上x,我们将检视你的完成情况,否则会导致pr无法合入

    • 设计:PR对应的方案是否已经经过Maintainer评审,方案检视意见是否均已答复并完成方案修改
    • 测试:PR中的代码是否已有UT/ST测试用例进行充分的覆盖,新增测试用例是否随本PR一并上库或已经上库
    • 验证:PR描述信息中是否已包含对该PR对应的Feature、Refactor、Bugfix的预期目标达成情况的详细验证结果描述
    • 接口:是否涉及对外接口变更,相应变更已得到接口评审组织的通过,API对应的注释信息已经刷新正确
    • 文档:是否涉及官网文档修改,如果涉及请及时提交资料到Doc仓

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

1 similar comment
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@openjiuwen-collaboration-bot

openjiuwen-collaboration-bot Bot commented Aug 10, 2026

Copy link
Copy Markdown

head_sha: ca46e3235f9d63ad64baf4aefce92ccf32a4619a

变更摘要

此 PR 主要对 LLM 模块的协议层进行了优化:引入多认证模式(LLMAuthMode)和端点配置文件(endpoint_profiles)系统,使单一 OpenAI provider 能够通过 profile/扩展配置自动路由到不同兼容端点;同时大幅增强 AnthropicModelClient,支持 thinking/推理内容块的保留与重放、OpenAI 风格图片格式的自动转换、以及更精确的采样参数策略。

主要改动

  • 新增认证与 API 模式枚举及端点配置系统:在 config.py 中新增 LLMApiModeLLMAuthModeKVCacheExtensionConfigLLMExtensionsConfig,并在新增的 endpoint_profiles.py 中定义 EndpointProfileLEGACY_PROVIDER_ALIASES,实现旧 provider(如 DeepSeekDashScope)到 OpenAI + profile 的规范化映射及消息转换注册机制。
  • Anthropic 客户端全面增强anthropic_model_client.py 新增 _sanitize_replay_block_preserved_content_blocks_convert_tool_choice_image_source_block 等函数,支持 thinking/signature 内容块在消息往返中保留与重放、OpenAI image_url 到 Anthropic image source 块的自动转换,以及流式场景下 thinking_delta/signature_delta 事件的累积与 metadata 回传。
  • OpenAI 客户端集成端点配置与消息转换openai_model_client.py_build_request_params 中调用 apply_message_transforms,根据 endpoint_profile(如 deepseek)自动注入 reasoning_content 字段;_resolved_api_key_for_configNoneAuth 模式返回占位密钥 "EMPTY"connection_key 增加 auth_mode 维度以区分不同认证模式的连接缓存。
  • 消息 chunk 的 metadata 传递链路完善AssistantMessageChunk.__add__ 现在合并非空 metadata;ReActAgent 在构造 AssistantMessage 时携带 accumulated_chunk.metadata,确保 Anthropic 内容块元数据在 agent 消息历史中不丢失。
  • 模型客户端创建路由优化model_clients/__init__.py 新增 _profile_or_extension_provider,根据 api_modeauth_modeendpoint_profilekv_cache 扩展配置动态推断 dispatch provider(如 OpenAIAccountInferenceAffinityAscendAffinity 等),实现 profile 驱动的统一路由。

@openjiuwen-collaboration-bot

openjiuwen-collaboration-bot Bot commented Aug 10, 2026

Copy link
Copy Markdown

head_sha: ca46e3235f9d63ad64baf4aefce92ccf32a4619a

代码审查

审查总结

发现问题汇总

优先级 数量
P0 0
P1 0
P2 1
P3 3

各文件审查结论

文件 结论
openjiuwen/core/foundation/llm/__init__.py 无问题(新增导入和 __all__ 导出,正确)
openjiuwen/core/foundation/llm/model_clients/__init__.py 无问题(_value / _profile_or_extension_provider / create_model_client 路由逻辑正确)
openjiuwen/core/foundation/llm/model_clients/anthropic_model_client.py P2: _content_to_blocks 图像转换失败时静默丢弃;P3: connection_key 缺少 auth_mode
openjiuwen/core/foundation/llm/model_clients/base_model_client.py P3: _validate_config 对非 ApiKey 模式跳过 api_key 校验,对 Anthropic 等始终需要 API Key 的提供方存在校验缺口
openjiuwen/core/foundation/llm/model_clients/openai_model_client.py 无问题(_resolved_api_key_for_configconnection_key、消息变换集成正确)
openjiuwen/core/foundation/llm/schema/config.py 无问题(新增枚举类和配置字段正确;_validate_top_level_provider_config 逻辑与 _validate_config 一致)
openjiuwen/core/foundation/llm/schema/message_chunk.py 无问题(metadata 合并修复正确)
openjiuwen/core/foundation/llm/utils/endpoint_profiles.py P3: LEGACY_PROVIDER_ALIASESclient_provider 映射为死代码
openjiuwen/core/single_agent/agents/react_agent.py 无问题(metadata 透传正确)
tests/unit_tests/core/foundation/llm/test_anthropic_model_client.py 无问题(测试覆盖充分)
tests/unit_tests/core/foundation/llm/test_message_chunk.py 无问题
tests/unit_tests/core/foundation/llm/test_model_client_config.py 无问题
tests/unit_tests/core/foundation/llm/test_model_client_profile_routing.py 无问题
tests/unit_tests/core/foundation/llm/test_openai_model_client.py 无问题

整体风险评估:中低风险

核心路由逻辑(create_model_clientnormalize_model_client_config_profile_or_extension_provider)审查后未发现正确性问题。主要的 P2 发现(图像静默丢弃)影响边缘输入,在实际使用中触发概率较低但后果隐蔽。三个 P3 发现均为代码维护性问题或远期风险,不影响当前功能正确性。建议在合入前优先修复 P2 图像丢弃问题。

类型 数量
🔴 阻塞 0
🟡 建议 1

💬 仅评论

@openjiuwen-collaboration-bot

Copy link
Copy Markdown

head_sha: ca46e3235f9d63ad64baf4aefce92ccf32a4619a

任务名称 结果 日志操作
静态检查 ❌FAILED 点此跳转
防投毒检查 ✅SUCCESS 点此跳转
开源合规检查 ✅SUCCESS 点此跳转
UT测试 ✅SUCCESS 点此跳转
ST测试 N/A N/A
build 编译包 N/A N/A
ruff codecheck ✅SUCCESS N/A

image_block = _image_source_block(image_value)
if image_block is not None:
blocks2.append(image_block)
continue

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

head_sha: ca46e3235f9d63ad64baf4aefce92ccf32a4619a

🟡 Medium Priority

变更位置:openjiuwen/core/foundation/llm/model_clients/anthropic_model_client.py 第 237-241 行的 _content_to_blocks 函数。

问题链:

  1. item_type"image_url" / "input_image" / "image" 时,提取 image_value
  2. image_value is not None,调用 _image_source_block(image_value) 进行转换
  3. _image_source_block 返回 None(例如 image_url 的 url 字段缺失或为空字符串),该分支执行 continue,跳过了原有的 blocks2.append(dict(item)) 回退路径
  4. 结果:原始图像项被静默丢弃,消息中不包含任何图像内容

触发条件:image_url 的值为 {}(空 dict)、{"url": ""}(空 URL)、或 {"url": None} 等边缘输入。

失败模式:用户/上游代码以为发送了图像,但实际请求中该图像消失,模型收不到视觉上下文,产生难以排查的结果偏差。

建议:将 continue 移到 if image_block is not None: 块内部,使转换失败时能回退到 blocks2.append(dict(item));或者当 _image_source_block 返回 None 且有 image_value 时抛出明确错误。

Suggested change
continue
if image_value is not None:
image_block = _image_source_block(image_value)
if image_block is not None:
blocks2.append(image_block)
continue

@openjiuwen-collaboration-bot

openjiuwen-collaboration-bot Bot commented Aug 10, 2026

Copy link
Copy Markdown

head_sha: ca46e3235f9d63ad64baf4aefce92ccf32a4619a

代码审查

The indentation confirms the issue: continue (line 241, 20-space indent) is inside the if image_value is not None: block but outside the if image_block is not None: block, so it executes even when conversion fails and skips the fallback blocks2.append(dict(item)) at line 242.


审查完毕

审查发现汇总

  • P0: 0 个
  • P1: 0 个
  • P2: 1 个(_content_to_blocks 图像转换失败时静默丢弃图像项——上一轮审查问题的复现,未修复)
  • P3: 0 个

各变更文件审查结果

文件 结果
openjiuwen/core/foundation/llm/__init__.py 无问题——仅新增 import 与 __all__ 条目
openjiuwen/core/foundation/llm/model_clients/__init__.py 无问题——分发逻辑设计合理
openjiuwen/core/foundation/llm/model_clients/anthropic_model_client.py 1 个 P2 问题(图像丢弃)
openjiuwen/core/foundation/llm/model_clients/base_model_client.py 无问题——auth_mode 校验正确
openjiuwen/core/foundation/llm/model_clients/openai_model_client.py 无问题——鉴权与消息转换处理正确
openjiuwen/core/foundation/llm/schema/config.py 无问题——新枚举与字段定义规范
openjiuwen/core/foundation/llm/schema/message_chunk.py 无问题——metadata 在 __add__ 中正确传播
openjiuwen/core/foundation/llm/utils/endpoint_profiles.py 无问题——新增文件,结构清晰
openjiuwen/core/single_agent/agents/react_agent.py 无问题——metadata 传播路径完整
tests/.../test_anthropic_model_client.py 无问题——测试覆盖全面
tests/.../test_message_chunk.py 无问题——metadata 合并测试正确
tests/.../test_model_client_config.py 无问题——auth 配置测试完备
tests/.../test_model_client_profile_routing.py 无问题——新增路由测试覆盖良好
tests/.../test_openai_model_client.py 无问题——鉴权与 profile 测试正确

整体风险判断

中低风险。唯一的 P2 问题是一个边界条件缺陷(图像 URL 为空时静默丢弃),触发概率较低且影响范围有限。其余变更——包括 Anthropic thinking/replay 机制、端点 profile 路由、auth_mode 校验、metadata 传播——设计合理、实现正确,测试覆盖充分。建议在合入前修复 _content_to_blocks 中的 continue 位置问题。

类型 数量
🔴 阻塞 0
🟡 建议 2

💬 仅评论

image_value = item.get("data_url", item.get("image"))
if image_value is not None:
image_block = _image_source_block(image_value)
if image_block is not None:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

head_sha: ca46e3235f9d63ad64baf4aefce92ccf32a4619a

🟡 Medium Priority

变更位置:openjiuwen/core/foundation/llm/model_clients/anthropic_model_client.py 第 237-241 行。

问题链:

  1. item_type"image_url" / "input_image""image"(无 source)时,image_value 被设置为从 item 中提取的图像值(第 233-236 行)。
  2. image_value is not None(第 237 行),则调用 _image_source_block(image_value) 尝试转换。
  3. 若转换成功(image_block is not None),则追加到 blocks(第 239-240 行),然后执行 continue(第 241 行)跳过通用的 blocks2.append(dict(item))——这是正确的。
  4. 但若转换失败(image_block is None),continue 仍然执行,同样跳过了第 242 行的 blocks2.append(dict(item)),导致该图像项被静默丢弃

触发条件:当 image_value 为非 None 但 _image_source_block 返回 None 时。具体场景包括:

失败模式:用户传入的图像项被静默丢弃,可能导致 API 调用中的内容丢失,且无任何错误提示。

此问题与上一轮审查中指出的问题一致,当前 diff 中未修复continue 仍然在 if image_block is not None: 块外部。

建议:将 continue 移到 if image_block is not None: 块内部,使转换失败时能回退到 blocks2.append(dict(item))。修改后逻辑:若 image_block is not None,追加转换后的块并 continue;否则继续执行到通用的 append。

Suggested change
if image_block is not None:
if image_block is not None:
blocks2.append(image_block)
continue

image_value = item.get("data_url", item.get("image"))
if image_value is not None:
image_block = _image_source_block(image_value)
if image_block is not None:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

head_sha: ca46e3235f9d63ad64baf4aefce92ccf32a4619a

🟡 Medium Priority

变更位置:openjiuwen/core/foundation/llm/model_clients/anthropic_model_client.py 第 237-241 行的 _content_to_blocks 函数。

问题链:

  1. image_value is not None 时进入图像转换分支(第 237 行)
  2. 调用 _image_source_block(image_value) 进行转换(第 238 行)
  3. 若转换成功(image_block is not None),则追加 image_block(第 239-240 行)
  4. 无论转换成功与否,都执行 continue(第 241 行),跳过了底部的兜底逻辑 blocks2.append(dict(item))(第 242 行)
  5. _image_source_block 在以下情况返回 None:传入的是没有 "url" 键的 Mapping、空字符串、或非字符串类型——这些情况下图像项被静默丢弃

触发条件:用户传入类似 {"type": "image_url", "image_url": {}}{"type": "image_url", "image_url": {"url": None}} 的消息内容。

此问题在上一轮审查中已被报告但未修复

建议:将 continue 移到 if image_block is not None: 块内部,使转换失败时能回退到 blocks2.append(dict(item)) 兜底逻辑。或者当 image_block is None 时记录警告并使用兜底。

Suggested change
if image_block is not None:
if image_value is not None:
image_block = _image_source_block(image_value)
if image_block is not None:
blocks2.append(image_block)
continue

@openjiuwen-collaboration-bot

Copy link
Copy Markdown

head_sha: d5193af0fba16663945cdd5c60696b470be3f3cb

任务名称 结果 日志操作
静态检查 ✅SUCCESS 点此跳转
防投毒检查 ✅SUCCESS 点此跳转
开源合规检查 ✅SUCCESS 点此跳转
UT测试 ❌FAILED 点此跳转
ST测试 N/A N/A
build 编译包 N/A N/A
ruff codecheck ✅SUCCESS N/A

@openjiuwen-collaboration-bot

Copy link
Copy Markdown

head_sha: d5193af0fba16663945cdd5c60696b470be3f3cb

任务名称 结果 日志操作
静态检查 ✅SUCCESS 点此跳转
防投毒检查 ✅SUCCESS 点此跳转
开源合规检查 ✅SUCCESS 点此跳转
UT测试 ✅SUCCESS 点此跳转
ST测试 N/A N/A
build 编译包 N/A N/A
ruff codecheck ✅SUCCESS N/A

@openjiuwen-collaboration-bot

Copy link
Copy Markdown

head_sha: 18ab1fbe64a0c4463010fa5f1f2d99e21609b9bf

任务名称 结果 日志操作
静态检查 ✅SUCCESS 点此跳转
防投毒检查 ✅SUCCESS 点此跳转
开源合规检查 ✅SUCCESS 点此跳转
UT测试 ❌FAILED 点此跳转
ST测试 N/A N/A
build 编译包 N/A N/A
ruff codecheck ✅SUCCESS N/A

@openjiuwen-collaboration-bot

Copy link
Copy Markdown

head_sha: 90b9bb6cb1a098c9bdefe252a8b3be574cae2b2a

任务名称 结果 日志操作
静态检查 ✅SUCCESS 点此跳转
防投毒检查 ✅SUCCESS 点此跳转
开源合规检查 ✅SUCCESS 点此跳转
UT测试 ✅SUCCESS 点此跳转
ST测试 N/A N/A
build 编译包 N/A N/A
ruff codecheck ✅SUCCESS N/A

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants