Claudeでレイテンシとコスト削減が見込めるプロンプトキャッシュを試してみた

## はじめに
本日、Anthropicからプロンプトキャッシュ機能がAnthropic APIのベータ版で利用可能になった旨の発表がありました！プロンプトキャッシュを使用することで長いプロンプトのコストやレイテンシの削減が見込めるとのことで早速試してみました。

https://www.anthropic.com/news/prompt-caching

## 主なメリット

### コスト削減
使用事例では100,000トークンをキャッシュさせてチャットを行った場合、最大で90％のコスト削減が実現できると紹介されていました。

| モデル | 基本入力トークン | キャッシュ書き込み | キャッシュヒット | 出力トークン |
|--------|------------------|---------------------|------------------|--------------|
| クロード 3.5 ソネット | $3 / MTok | $3.75 / MTok | $0.30 / MTok | $15 / MTok |
| クロード 3.0 俳句 | $0.25 / MTok | $0.30 / MTok | $0.03 / MTok | $1.25 / MTok |
| クロード 3.0 Opus (近日公開) | $15 / MTok | $18.75 / MTok | $1.50 / MTok | $75 / MTok |

**※キャッシュによる書き込みトークンは、標準の入力トークンより25%高くなる代わりに、キャッシュされた読み取りトークンは、標準の入力トークンより90%安くなります。**

### 応答速度の向上
同様の事例ではキャッシュ時のレイテンシ(最初のトークンまでの時間)において11.5秒から2.4秒と79%も向上したとのことです。

![スクリーンショット 2024-08-15 15.16.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354022/54ff22c6-0ce2-78cb-cb41-1f3b0d1c70ff.png)

キャッシュトークン数が少ない場合でもコスト削減効果やレイテンシの向上が見込めることもあり、アプリケーションの運用コストを大幅に削減しつつ、ユーザー体験を向上させることが期待できそうです。

## 対応モデル
現在、``Claude 3.5 Sonnet``と``Claude 3 Haiku``がパブリックベータで利用可能とのことです。※Opusのサポートは近日中に開始予定とのこと。

## 試してみた

契約書のサンプルを``contract_sample.txt``として用意し、これをプロンプトに読み込ませて同じ質問を投げることでキャッシュされているか確認してみました。

``APIキー``には自身の環境に合わせて入力してください。

```python
import anthropic
import time
import os
import base64

client = anthropic.Anthropic(api_key="APIキー")

def read_contract():
    with open('contract_sample.txt', 'r', encoding='utf-8') as file:
        return file.read()

def measure_response_time(query):
    start_time = time.time()
    
    contract_text = read_contract()
    
    response = client.beta.prompt_caching.messages.create(
        model="claude-3-5-sonnet-20240620",
        max_tokens=4096,
        system=[
            {
                "type": "text",
                "text": f"以下は法的契約書の全文です：{contract_text}",
                "cache_control": {"type": "ephemeral"}
            }
        ],
        messages=[
            {
                "role": "user",
                "content": query
            }
        ]
    )
    
    end_time = time.time()
    elapsed_time = end_time - start_time
    
    return response, elapsed_time

test_query = "この契約書の主要な条件と条項は何ですか？"

num_repetitions = 3

for i in range(num_repetitions):
    response, elapsed_time = measure_response_time(test_query)
    print(f"実行 {i+1}:")
    print(f"質問内容: {test_query}")
    print(f"応答時間: {elapsed_time:.2f} 秒")
    print(f"応答:\n{response.content[0].text}")
    print(f"cache_creation_input_tokens: {response.usage.cache_creation_input_tokens}")
    print(f"cache_read_input_tokens: {response.usage.cache_read_input_tokens}")
    print(f"input_tokens: {response.usage.input_tokens}")
    print(f"output_tokens: {response.usage.output_tokens}")
    print("\n" + "-"*50 + "\n")
```

```contract_sample.txt
業務提携契約書

株式会社A（以下「甲」という）と株式会社B（以下「乙」という）は、以下のとおり業務提携契約（以下「本契約」という）を締結する。

第1条 （目的）
本契約は、甲と乙が相互の事業発展を目的として、各々の経営資源を有効に活用し、業務提携を行うことについて必要な事項を定めるものとする。

第2条 （業務提携の内容）
甲と乙は、以下の項目について業務提携を行うものとする。
1. 製品開発に関する技術協力
2. 販売チャネルの相互活用
3. マーケティング情報の共有
4. 人材交流

第3条 （秘密保持）
1. 甲及び乙は、本契約に基づき相手方から開示された情報（以下「秘密情報」という）を厳に秘密として保持し、相手方の事前の書面による承諾なしに第三者に開示、漏洩してはならない。
2. 前項の規定にかかわらず、次の各号のいずれかに該当する情報は、秘密情報に含まれないものとする。
   (1) 開示時に既に公知であった情報
   (2) 開示後に受領者の責めによらずして公知となった情報
   (3) 開示時に受領者が既に保有していた情報
   (4) 正当な権限を有する第三者から秘密保持義務を負うことなく入手した情報
3. 本条の義務は、本契約終了後も3年間存続するものとする。

第4条 （知的財産権）
1. 本契約に基づき生じた知的財産権は、甲乙協議の上、その帰属を定めるものとする。
2. 前項の協議が整わない場合、当該知的財産権は甲乙の共有とし、その持分は均等とする。
3. 共有の知的財産権について、甲又は乙が単独で実施する場合は、相手方の事前の書面による承諾を得るものとし、その実施料については別途協議して定めるものとする。

第5条 （有効期間）
1. 本契約の有効期間は、契約締結日から3年間とする。
2. 前項の期間満了の3ヶ月前までに、甲乙いずれからも書面による契約終了の意思表示がないときは、本契約は同一条件でさらに1年間更新されるものとし、以後も同様とする。

第6条 （契約の解除）
甲又は乙は、相手方が次の各号のいずれかに該当する場合、相手方に対して書面による通知をもって、直ちに本契約を解除することができる。
1. 本契約に違反し、相当の期間を定めて催告したにもかかわらず、その違反が是正されないとき
2. 差押、仮差押、仮処分、強制執行、競売の申立て、又は公租公課の滞納処分を受けたとき
3. 破産、民事再生、会社更生又は特別清算の申立てを受け、又は自ら申立てをしたとき
4. 解散、事業の廃止、事業の全部又は重要な一部の譲渡を決議したとき
5. 監督官庁から営業許可の取消、停止等の処分を受けたとき
6. その他財産状態が悪化し、又はそのおそれがあると認められる相当の事由があるとき

第7条 （損害賠償）
甲又は乙は、本契約に違反して相手方に損害を与えた場合、その損害を賠償する責任を負うものとする。

第8条 （反社会的勢力の排除）
1. 甲及び乙は、自己又はその役員、従業員、主要な株主若しくは取引先が、暴力団、暴力団員、暴力団関係企業・団体又はその関係者、その他反社会的勢力（以下総称して「反社会的勢力」という）に該当しないこと、及び次の各号のいずれにも該当しないことを表明し、保証する。
   (1) 反社会的勢力が経営を支配していると認められる関係を有すること
   (2) 反社会的勢力が経営に実質的に関与していると認められる関係を有すること
   (3) 自己、自社若しくは第三者の不正の利益を図る目的又は第三者に損害を加える目的をもってするなど、不当に反社会的勢力を利用していると認められる関係を有すること
   (4) 反社会的勢力に対して資金等を提供し、又は便宜を供与するなどの関与をしていると認められる関係を有すること
   (5) 役員又は経営に実質的に関与している者が反社会的勢力と社会的に非難されるべき関係を有すること
2. 甲又は乙は、相手方が前項の表明・保証に違反した場合、又は自ら若しくは第三者を利用して、相手方に対して、詐術、暴力的行為、脅迫的言辞を用いる行為、法的な責任を超えた不当な要求行為、相手方の信用を毀損し又は相手方の業務を妨害する行為、その他これらに準ずる行為をした場合、何らの催告を要さずに、本契約の全部又は一部を解除することができるものとする。
3. 甲及び乙は、前項の規定により本契約を解除した場合、相手方に損害が生じても、これを一切賠償する責任を負わないものとする。

第9条 （譲渡禁止）
甲及び乙は、相手方の事前の書面による承諾なくして、本契約上の地位又は本契約に基づく権利義務の全部又は一部を第三者に譲渡し、又は担保に供してはならない。

第10条 （協議事項）
本契約に定めのない事項又は本契約の解釈に疑義が生じた場合は、甲乙誠意をもって協議し、解決するものとする。

第11条 （準拠法及び管轄裁判所）
1. 本契約の準拠法は日本法とする。
2. 本契約に関して紛争が生じた場合は、東京地方裁判所を第一審の専属的合意管轄裁判所とする。

本契約の成立を証するため、本書2通を作成し、甲乙記名押印の上、各1通を保有する。

  年  月  日

甲：東京都千代田区＊＊＊
   株式会社A
   代表取締役 ＊＊＊＊  印

乙：大阪府大阪市＊＊＊
   株式会社B
   代表取締役 ＊＊＊＊  印
```

## 実行結果
```sh
実行 1:
質問内容: この契約書の主要な条件と条項は何ですか？
応答時間: 9.56 秒
応答:
この業務提携契約書の主要な条件と条項は以下の通りです：

1. 目的（第1条）：相互の事業発展を目的とした業務提携
2. 業務提携の内容（第2条）：
   - 製品開発に関する技術協力
   - 販売チャネルの相互活用
   - マーケティング情報の共有
   - 人材交流

3. 秘密保持（第3条）：相手方から開示された情報の厳格な秘密保持義務
4. 知的財産権（第4条）：共同で生み出された知的財産権の帰属と使用に関する取り決め
5. 契約期間（第5条）：3年間の契約期間と自動更新条項
6. 契約解除（第6条）：契約解除が可能となる条件の明示
7. 損害賠償（第7条）：契約違反による損害賠償責任
8. 反社会的勢力の排除（第8条）：反社会的勢力との関係排除の保証
9. 譲渡禁止（第9条）：契約上の権利義務の第三者への譲渡禁止
10. 準拠法と管轄裁判所（第11条）：日本法を準拠法とし、東京地方裁判所を第一審の専属的合意管轄裁判所とする

これらの条項は、両社の業務提携の枠組み、権利義務関係、リスク管理、そして紛争解決の方法を定めています。
cache_creation_input_tokens: 2154
cache_read_input_tokens: 0
input_tokens: 26
output_tokens: 466

--------------------------------------------------

実行 2:
質問内容: この契約書の主要な条件と条項は何ですか？
応答時間: 9.83 秒
応答:
この業務提携契約書の主要な条件と条項は以下の通りです：

1. 目的（第1条）: 相互の事業発展を目的とした業務提携。
2. 業務提携の内容（第2条）: 
   - 製品開発に関する技術協力
   - 販売チャネルの相互活用
   - マーケティング情報の共有
   - 人材交流
3. 秘密保持（第3条）: 相手方から開示された情報の秘密保持義務。
4. 知的財産権（第4条）: 契約に基づき生じた知的財産権の帰属や共有に関する規定。
5. 有効期間（第5条）: 契約締結日から3年間、自動更新あり。
6. 契約解除（第6条）: 契約解除が可能な条件の列挙。
7. 損害賠償（第7条）: 契約違反による損害賠償責任。
8. 反社会的勢力の排除（第8条）: 反社会的勢力との関係がないことの保証と、違反時の契約解除権。
9. 譲渡禁止（第9条）: 契約上の地位や権利義務の譲渡禁止。
10. 協議事項（第10条）: 契約に定めのない事項や解釈の疑義に関する協議。
11. 準拠法と管轄裁判所（第11条）: 日本法を準拠法とし、東京地方裁判所を第一審の専属的合意管轄裁判所とする。

これらの条項は、両社の業務提携の枠組み、権利義務関係、リスク管理などを定めています。
cache_creation_input_tokens: 0
cache_read_input_tokens: 2154
input_tokens: 26
output_tokens: 521

--------------------------------------------------
実行 3:
質問内容: この契約書の主要な条件と条項は何ですか？
応答時間: 10.13 秒
応答:
この業務提携契約書の主要な条件と条項は以下の通りです：

1. 目的（第1条）: 相互の事業発展のための業務提携。
2. 業務提携の内容（第2条）: 
   - 製品開発に関する技術協力
   - 販売チャネルの相互活用
   - マーケティング情報の共有
   - 人材交流
3. 秘密保持（第3条）: 相手方から開示された情報の秘密保持義務。
4. 知的財産権（第4条）: 契約に基づき生じた知的財産権の帰属と実施に関する取り決め。
5. 有効期間（第5条）: 契約締結日から3年間、以後1年ごとの自動更新。
6. 契約解除（第6条）: 契約解除が可能となる条件の規定。
7. 損害賠償（第7条）: 契約違反による損害賠償責任。
8. 反社会的勢力の排除（第8条）: 反社会的勢力との関係がないことの保証と違反時の対応。
9. 譲渡禁止（第9条）: 契約上の地位や権利義務の第三者への譲渡禁止。
10. 協議事項（第10条）: 契約に定めのない事項や解釈の疑義に関する協議。
11. 準拠法と管轄裁判所（第11条）: 日本法を準拠法とし、東京地方裁判所を第一審の専属的合意管轄裁判所とする。

これらの条項は、両社の業務提携の枠組み、責任、権利、そして紛争解決の方法を定めています。
cache_creation_input_tokens: 0
cache_read_input_tokens: 2154
input_tokens: 26
output_tokens: 529
```

### 1回目の実行結果抜粋
```
応答時間: 9.56 秒
cache_creation_input_tokens: 2154
cache_read_input_tokens: 0
input_tokens: 26
output_tokens: 466
```

### 2回目の実行結果抜粋
```
応答時間: 9.83 秒
cache_creation_input_tokens: 0
cache_read_input_tokens: 2154
input_tokens: 26
output_tokens: 521
```

### 3回目の実行結果抜粋
```
応答時間: 10.13 秒
cache_creation_input_tokens: 0
cache_read_input_tokens: 2154
input_tokens: 26
output_tokens: 529
```

初回実行時に``cache_creation_input_tokens``でキャッシュが作られており、2回目以降は``cache_read_input_tokens``でキャッシュが読み込まれていることが確認できました！

一方で今回のケースではキャッシュさせたトークン数が少ないのもあって応答全体には影響は与えられませんでした。10万トークン規模で試したかったのですが、APIの``TOKENS PER MINUTE``のレートリミットに抵触するので今回は断念。。

## 考慮事項
### 最小トークン数
プロンプトキャッシュを利用する場合、最小トークン数が定められています。
- Claude 3.5 SonnetとClaude 3 Opusの場合、1024tokens
- Claude 3.5 Haikuの場合、2048 tokens

最小トークン数を満たしていない場合、以下のエラーが出力されるので注意してください。

```
anthropic.BadRequestError: Error code: 400 - {'type': 'error', 'error': {'type': 'invalid_request_error', 'message': 'The message up to and including the first cache-control block must be at least 1024 tokens
```

### キャッシュ時間とキャッシュ削除
キャッシュの有効期限は確認したところ5分間で、また手動での削除は出来ませんでした。
キャッシュされたトークンが使用される度に有効期限の5分は更新されます。

## おわりに
今回は一先ずキャッシュ作成とキャッシュ読み取りの動作を確認しました。まだベータ版ではありますが、プロンプトキャッシュによって論文や内部資料などを用いたロングコンテキストによるチャットコミュニケーションや長めの会話におけるUXやコスト改善が期待できるので、Anthropic API上はもちろんですがAWSのにおけるBedrockなどでも手軽に利用できるようになるとなお嬉しいですね。