先看现象。Claude 的流式代码用 client.completions.create(stream=True) 遍历 chunk.completion,升到 anthropic 0.40 后报 AttributeError: ‘NoneType’ object has no attribute ‘completion’,换 messages 接口才有内容。
原因不止一个,得分开看。completions 接口在新版里不再是主路径,返回结构也没了 completion 字段。还有一种是流式应该用 messages.stream 上下文管理器拿增量。
少数情况下是事件类型改成 content_block_delta,需要读 delta.text。
不容易想到的是,旧代码读的三个字段在新结构里都不存在。
动手时先把事件类型完整打一遍
python -c "import anthropic;c=anthropic.Anthropic();[print(e.type) for e in c.messages.stream(model='claude-3-5-sonnet-20241022',max_tokens=64,messages=[{'role':'user','content':'hi'}])]"
直接用 text_stream 拼出整段文本
python -c "import anthropic;c=anthropic.Anthropic();print(''.join(c.messages.stream(model='claude-3-5-sonnet-20241022',max_tokens=64,messages=[{'role':'user','content':'hi'}]).text_stream))"
锁住小版本避免再被大版本带走
pip install "anthropic>=0.40,<0.50"
非流式做一次对照
python -c "import anthropic;print(anthropic.Anthropic().messages.create(model='claude-3-5-sonnet-20241022',max_tokens=32,messages=[{'role':'user','content':'ping'}]).content[0].text)"
当时还开着另一个排查窗口,两边日志对照着看才定位到。
同一份数据我导出了两份,一份留底,一份拿来试。
这类问题以前遇到过,但这次的触发条件和上次不一样。
改完先别撤,确认这几项。流式能逐段打印文本,拼接结果与非流式返回的 text 一致,日志里不再出现 AttributeError。
补一句。旧 completions 接口还能调用但字段会变,趁升级一次改到 messages 与 text_stream,别两套都留着。报错文案容易误导,真正的原因往往在相邻那一层的日志里。
