Anthropicプロバイダの不要な「単一システムメッセージ」警告を削除
Anthropicプロバイダが複数の :system ロールメッセージを受け取るたびに出力していた誤った警告ログを削除しました。Anthropicの system パラメータは既にテキストコンテンツブロックの配列を受け付けており、gemの実装も正しく動作していたため、警告だけが実態と乖離した状態になっていました。
背景
Anthropic::Chat#build_system_content には、複数の :system メッセージが渡されたときに警告を出力するコードが残存していました。警告の内容は「Anthropicは単一のシステムメッセージしかサポートしておらず、複数のメッセージは結合される」というものでしたが、これは現状の実装と一致しない記述でした。
実際には、メソッド内の flat_map による実装は各 :system メッセージを独立したテキストブロックとしてシリアライズしており、cache_control 付きのブロックも正しく保持されます。Anthropicの system パラメータはテキストコンテンツブロックの配列を受け付けるため、複数のシステムメッセージは「結合」ではなく「配列の各要素」として送信されていました。
Issue #767 で報告されたように、静的プロンプトとセッションごとのコンテキストを別々の :system メッセージとして分割するユースケース(プロンプトキャッシングのためのブロック分割など)では、リクエストのたびに誤った警告がログに出力されていました。高スループットなエージェント環境では、この誤警告がログを大量に埋め尽くす問題になっていました。また、Bedrockプロバイダ (lib/ruby_llm/providers/bedrock/chat.rb) では同じケースを警告なしで処理しており、プロバイダ間で挙動に一貫性がない状態でもありました。
技術的な変更
lib/ruby_llm/providers/anthropic/chat.rb の build_system_content メソッドから、system_messages.length > 1 の条件分岐と RubyLLM.logger.warn の呼び出しを削除しました。
変更前:
def build_system_content(system_messages)
return [] if system_messages.empty?
if system_messages.length > 1
RubyLLM.logger.warn(
"Anthropic's Claude implementation only supports a single system message. " \
'Multiple system messages will be combined into one.'
)
end
system_messages.flat_map do |msg|
content = msg.content
# ...
end
end
変更後:
def build_system_content(system_messages)
return [] if system_messages.empty?
# Anthropic's `system` parameter accepts an array of text content blocks
# (each optionally with cache_control); each :system message becomes its
# own block in the resulting array.
system_messages.flat_map do |msg|
content = msg.content
# ...
end
end
この変更はワイヤフォーマットに影響しません。APIリクエストのペイロード形式は変わらず、既存のVCRカセットも引き続き有効です。
テストカバレッジとして、spec/ruby_llm/providers/anthropic/chat_spec.rb に build_system_content の直接ユニットテストが追加されました。追加された6つのテストケースは以下のシナリオをカバーします:
- システムメッセージがゼロのとき
[]を返す - 1つのメッセージから1つのブロックを返す
- 2つのメッセージから2つのブロックを順序通りに返す
- 複数の
:systemメッセージが渡されてもwarnが呼ばれない -
Content::Rawブロックのcache_controlを保持する -
Content::Rawと平文文字列が混在する場合を正しくフラット化する
設計判断
警告の削除のみを行い、flat_map によるシリアライズロジックには手を加えない最小限の変更が選ばれました。
コードの挙動自体は正しかったため、修正対象は誤った前提に基づくログ出力のみです。コメントで「system パラメータが cache_control 付きのテキストコンテンツブロックの配列を受け付ける」という正しい仕様を明示することで、将来の開発者が同じ誤解をしないよう配慮されています。
また、今回追加されたユニットテストは build_system_content をクラスメソッドとして直接呼び出す形式を採用しています。これにより、HTTPリクエストやVCRカセットを必要とせず、メソッドの契約を独立して検証できる構造になっています。
まとめ
実装は正しく動作していたにもかかわらず、ログに誤ったメッセージを出力し続けていた負債を解消した変更です。警告の削除という最小限の修正でプロバイダ間の挙動の一貫性も回復しており、正確なユニットテストの追加によってメソッドの正しい契約が明文化されました。