Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces support for the Anthropic Claude Messages API by adding the ClaudeChat module and updating the prompter logic to handle Anthropic's specific message format. Key changes include the addition of _generate_prompt_anthropic_impl in the prompter, a new format parameter to replace the deprecated return_dict, and the implementation of ClaudeChat with custom message and tool conversion logic. Feedback highlights potential issues with Python name mangling due to the use of format, the use of an invalid default model name (claude-opus-4-5), and an incorrect API endpoint for key validation.
| VLM_MODEL_PREFIX = [] | ||
| NO_PROXY = True | ||
| __lazyllm_registry_key__ = LLMType.CHAT | ||
| __format__ = 'openai' |
There was a problem hiding this comment.
Using __format__ as a class attribute is problematic because double underscores trigger Python's name mangling. In the forward method (line 138), self.__format__ will always resolve to _LazyLLMOnlineChatModuleBase__format__ (i.e., 'openai'), even if a subclass like ClaudeChat defines its own __format__. Additionally, __format__ is a special Python method name. It should be renamed to something like _format or message_format to allow proper polymorphism.
| __format__ = 'openai' | |
| _format = 'openai' |
| runtime_model = model or self._model_name | ||
|
|
||
| params = {'input': __input, 'history': llm_chat_history, 'return_dict': True} | ||
| params = {'input': __input, 'history': llm_chat_history, 'format': self.__format__} |
There was a problem hiding this comment.
Access the renamed attribute _format instead of the mangled __format__ to ensure subclasses can provide their own format identifier to the prompter.
| params = {'input': __input, 'history': llm_chat_history, 'format': self.__format__} | |
| params = {'input': __input, 'history': llm_chat_history, 'format': self._format} |
|
|
||
| _ANTHROPIC_VERSION = '2023-06-01' | ||
| _DEFAULT_MAX_TOKENS = 4096 | ||
| __format__ = 'anthropic' |
| def __init__(self, base_url: Optional[str] = None, model: Optional[str] = None, | ||
| api_key: str = None, stream: bool = True, return_trace: bool = False, **kwargs): | ||
| base_url = base_url or 'https://api.anthropic.com/v1/' | ||
| model = model or 'claude-opus-4-5' |
There was a problem hiding this comment.
claude-opus-4-5 is not a valid Anthropic model name. The current flagship models are claude-3-opus-20240229 or claude-3-5-sonnet-20241022. Using a non-existent model name as the default will cause API requests to fail with a 404 or 400 error.
| model = model or 'claude-opus-4-5' | |
| model = model or 'claude-3-5-sonnet-20241022' |
| def _validate_api_key(self): | ||
| try: | ||
| models_url = urljoin(self._base_url, 'models') | ||
| response = requests.get(models_url, headers=self._header, timeout=10) | ||
| return response.status_code == 200 | ||
| except Exception: | ||
| return False |
There was a problem hiding this comment.
Anthropic's API does not provide a /v1/models endpoint. This validation logic will consistently return a 404 error, causing API key validation to fail even for valid keys. Consider validating the key by making a minimal request to the /v1/messages endpoint (e.g., with max_tokens=1) or simply verifying that the key is provided in the configuration.
📌 PR 内容 / PR Description
ClaudeChatsupplier insupplier/claude.py— supports chat, streaming, and tool calls via Anthropic native Messages API (/v1/messages)_prepare_request_datahook toOnlineChatModuleBaseso subclasses can transform the request body before sendingformatparameter ('openai'/'anthropic') toLazyLLMPrompterBase.generate_prompt; deprecatereturn_dict=Truewith a one-timeLOG.log_oncewarning_generate_prompt_anthropic_implto produce Anthropic-native prompt format (systemas top-level field, no system message inmessageslist)_message_formatclass variable toOnlineChatModuleBase(default'openai');ClaudeChatsets it to'anthropic'soforwardautomatically picks the right prompt formatClaudeChatdocs (Chinese + English + example) tolazyllm/docs/module.pytest_claude_chatandtest_claude_tool_calltotests/charge_tests/Models/test_chat.py🎯 问题背景 / Problem Context
/v1/messages、独立system字段、input_schema工具格式、SSE 事件类型)与 OpenAI 兼容格式差异较大,无法直接复用现有 supplier。🔍 相关 Issue / Related Issue
✅ 变更类型 / Type of Change
🧪 如何测试 / How Has This Been Tested?
lazyllm.OnlineChatModule(source='claude', stream=False)('你好')returns a non-empty stringlazyllm.OnlineChatModule(source='claude', stream=True)('你好')streams tokens and returns the full merged responsetoolslist; withFunctionCallFormatterthe result is a dict containingtool_callswith correctnameandarguments📷 Demo (Optional)
⚡ 更新后的用法示例 / Usage After Update
🔄 重构对比(如适用)
Before
After
return_dict=Trueingenerate_promptis deprecated; useformat='openai'instead. Existing callers continue to work unchanged (one-time warning emitted)._prepare_request_dataand_message_formatare general-purpose extension points for future non-OpenAI suppliers.x-api-key+anthropic-version), endpoint (/v1/messages),systemas top-level field,max_tokensrequired, tool schema usesinput_schema, stream uses SSE event types (content_block_deltaetc.).🧠 AI 参与情况 / AI Involvement
使用工具 / Tools Used:
🤖 AI 生成过程 / AI Generation Process
初始 Prompt
AI 初始输出质量
问题点:
AI 初始实现直接复用了 OpenAI 兼容路径(
/v1/chat/completions),未处理 Anthropic 原生格式差异,导致请求失败。🔧 人工干预过程 / Human Intervention
第一次修正
修改后的 Prompt / 操作:
原因:
AI 未主动调研 Anthropic API 格式,默认沿用了 OpenAI 路径。需要明确指出端点差异。
第二次修正
修改后的 Prompt / 操作:
原因:
AI 第一版直接重写了整个
forward方法,代码冗余且难以维护。人工指出应通过 hook 方法复用基类逻辑。第三次修正
修改后的 Prompt / 操作:
原因:
人工发现 system 消息格式转换属于 prompt 层的职责,不应放在 request 构造层。通过引入
format参数和_message_format类变量,使架构更清晰、可扩展。最终策略总结
_get_header)、响应解析(_convert_msg_format+_str_to_json)_message_format比运行时判断更清晰,子类只需声明意图📊 AI vs 人工贡献占比
80%20%主要人工修改点:
❌ 失败 Prompt 示例
❌ 问题表现
forward方法,可维护性差__format__命名触发 Python name mangling,子类无法正确覆盖(由 Gemini code review 发现)✅ 改进后 Prompt
🧩 可复用经验 / Reusable Patterns
__xxx__)在 Python 中有特殊含义或触发 name mangling,应使用单下划线前缀(_message_format)