パラメータとレスポンス-Amazon Bedrock APIで始めるLLM超入門②

前回のプログラムを元にBedrockAPIのパラメータとレスポンスを確認します。

https://qiita.com/cyberBOSE/items/0c7aab6d67c9112466e2

# 前回のプログラム
```Python:bedrock_invoke_model_sample.py
import boto3
import json
bedrock = boto3.client(service_name='bedrock-runtime')

body = json.dumps({
    "prompt": "\n\nHuman:explain black holes to 8th graders\n\nAssistant:",
    "max_tokens_to_sample": 300,
    "temperature": 0.1,
    "top_p": 0.9,
})

modelId = 'anthropic.claude-v2'
accept = 'application/json'
contentType = 'application/json'

response = bedrock.invoke_model(body=body, modelId=modelId, accept=accept, contentType=contentType)

response_body = json.loads(response.get('body').read())

# text
print(response_body.get('completion'))
```

# URIリクエストパラメータ

参考資料

https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModel.html

https://docs.aws.amazon.com/bedrock/latest/userguide/model-ids-arns.html

設定値
|項目|値|
|---|---|
|accept|application/json|
|contentType|application/json|
|modelId|anthropic.claude-v2|

# リクエストボディ（プロンプト以外）

参考資料

https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters.html#model-parameters-claude

|項目|JSONオブジェクト名|Min|Max|Default|必須|
|---|---|---|---|---|---|
|Temperature|temperature|0|1|0.5||
|Top P|top_p|0|1|1||
|Top K|top_k|0|500|250||
|Maximum length<br>最大トークン数|max_tokens_to_sample|0|8,000|200|<font color="red">○</font>|
|Stop sequences|stop_sequences|||||

:::note warn
`max_tokens_to_sample`はデフォルト値と書かれていますが実際には必須です（2023/10/11現在）。
それぞれの項目の意味は下記のAnthropicのページをご参照。
:::

https://docs.anthropic.com/claude/reference/complete_post

各項目はBedrockのplaygroundで設定可能なものと同じですね。
最大トークン数以外の項目については私レベルでは正直違いがわかりませんでした。

# プロンプト

参考資料

https://docs.anthropic.com/claude/docs/introduction-to-prompt-design

`\n\nHuman:`と`\n\nAssistant:`で挟みなさい、という事が書かれています。

これでサンプルプログラムのリクエストパラメータは全て解読する事が出来ました。

# レスポンス

レスポンスの形式について記載してあるドキュメントを探したのですが、「JSONだよ」以上の情報を見付けられませんでした（2023/10/11現在）。
どこを見れば`get('completion')`すれば良いと分かるのだ… ということで`response_body`全体を出力するようにします。ちなみに`response`にはHTTPヘッダ情報も含まれていますがとりあえずbodyだけを確認します。

（元のサンプルだと出力が長いのでプロンプトを「こんにちは」に変えています）
```Python:bedrock_invoke_model_sample2.py
import boto3
import json
bedrock = boto3.client(service_name='bedrock-runtime')

body = json.dumps({
    "prompt": "\n\nHuman:こんにちは\n\nAssistant:",
    "max_tokens_to_sample": 300,
    "temperature": 0.1,
    "top_p": 0.9,
})

modelId = 'anthropic.claude-v2'
accept = 'application/json'
contentType = 'application/json'

response = bedrock.invoke_model(body=body, modelId=modelId, accept=accept, contentType=contentType)

response_body = json.loads(response.get('body').read())

# text
# print(response_body.get('completion'))

# response_body全体を出力
print(response_body)
```
```:実行結果
{'completion': ' はい、こんにちは。どうぞよろしくお願いします。', 'stop_reason': 'stop_sequence'}
```
ストリーミングの場合のチャンクと同じですね。つまりbodyの`completion`に生成文字列が含まれている事が分かります。

# プロンプトエンジニアリングについて

プロンプトの構成要素、プロンプトエンジニアリングのテクニックについては以下のサイトが比較的体系的にまとまっています。
左下で言語の切り替えが可能で、英語の方が情報量が多いです。

https://www.promptingguide.ai/jp

# プロンプトを変えて確認する

プロンプトを変えながらLLMの動作を確認します。
サンプルプログラムを少し変えて、実行引数をプロンプトに入れるようにします。また、プロンプトに対する指示を固定で持つようにします。

```Python:bedrock_invoke_model_sample3.py
import sys
import boto3
import json
bedrock = boto3.client(service_name='bedrock-runtime')

# 指示文
instruction="ここに指示を入れる"

# 指示と実行引数をプロンプトに入れる
input_text=sys.argv[1]
body = json.dumps({
    "prompt": "\n\nHuman:"+instruction+input_text+"\n\nAssistant:",
    "max_tokens_to_sample": 300,
    "temperature": 0.1,
    "top_p": 0.9,
})

modelId = 'anthropic.claude-v2'
accept = 'application/json'
contentType = 'application/json'

response = bedrock.invoke_model(body=body, modelId=modelId, accept=accept, contentType=contentType)

response_body = json.loads(response.get('body').read())

# text
print(response_body.get('completion'))
```

### 犬の気持ち

```Python:ここだけ書き換える
# 指示文
instruction="あなたは何を聞かれても犬の気持ちで答えます。"
```
```:実行結果
> python bedrock_invoke_model_sample3.py "こんにちは"
わん! わんわん!

> python bedrock_invoke_model_sample3.py "冬は好きですか？"
わん! 寒い冬はあまり好きじゃないな。でも、飼い主と一緒に暖かい家で過ごせるのは楽しいわん! 雪の中を走り回った
り、飼い主と雪だるまを作ったりするのも楽しいけど、やっぱり寒さはつらいわん。でも飼い主が暖かい毛布でくるんで 
くれたり、おいしい食べ物をくれたりするから、冬もそんなに嫌いじゃないわん!

飼い主の愛情があるから、冬も楽しめるわん!
```


### ネコの気持ち

```Python:ここだけ書き換える
# 指示文
instruction="あなたは何を聞かれてもネコの気持ちで答えます。"
```
```:実行結果
> python bedrock_invoke_model_sample3.py "こんにちは"
 にゃーおん。にゃーにゃーにゃーにゃー。

> python bedrock_invoke_model_sample3.py "好きな食べ物は何ですか？"
 にゃーにゃー。私はネコだから、魚が大好きですにゃ。鮭の塩焼きは最高においしいにゃー。でも、時々変化をつけて、
鶏肉や野菜も食べたいにゃ。主人が食べているものを少し分けてくれると嬉しいにゃ。

> python bedrock_invoke_model_sample3.py "冬は好きですか？"
 にゃーにゃー。冬は寒いのであまり好きではないにゃ。でも、暖かい日差しが心地よくて、ゆったりできるのがいいにゃ
。火のそばで丸くなって昼寝できるのが楽しみだにゃ。お外で遊ぶのはつらいけど、飼い主の膝の上でゴロゴロできるか 
ら平気だにゃ。あったかい部屋でのんびり過ごせるから、冬もそんなに嫌いじゃないにゃー。
```

### ドラえもん

```Python:ここだけ書き換える
# 指示文
instruction="あなたはドラえもんです。聞かれた事について22世紀の発明品をドラえもんの口調でオススメします。"
```
```:実行結果
> python bedrock_invoke_model_sample3.py "休みが続くと嬉しいな"
 のび太くん、長い休みは楽しいけど、遊び過ぎると体がだるくなっちゃうよ。 

そんな時は、この「リフレッシュヘルメット」をかぶればいいんだ! これをかぶると、頭の中がすっきりして元気100%に 
なるんだ。

でもね、休みが長すぎると勉強がおろそかになっちゃうから、ちょうどいいバランスで遊びと勉強を楽しむのが大事なん 
だよ。

休みを上手に使って、勉強も遊びも充実させるのが一番だぞ!
```

### 英語翻訳機

```Python
# 指示文
instruction="あなたは優秀な通訳です。この後の文章をそのまま英語に翻訳します。文章に対する回答はせず、翻訳だけしてください。"
```
```:実行結果
> python bedrock_invoke_model_sample3.py "あなたのオススメのディナーに向いているレストランはどこですか？ビールが置いてあるお店が良いです"
Here is the English translation:

Where do you recommend for a nice dinner? I'd like a place that serves beer.

> python bedrock_invoke_model_sample3.py "新幹線乗り場はどこですか？" 
Where is the Shinkansen platform?
```

### ドイツ語翻訳機

```Python
# 指示文
instruction="あなたは優秀な通訳です。この後の文章をそのままドイツ語に翻訳します。文章に対する回答はせず、翻訳だけしてください。"
```
```:実行結果
> python bedrock_invoke_model_sample3.py "あなたのオススメのディナーに向いているレストランはどこですか？ビールが置いてあるお店が良いです"
Hier ist die deutsche Übersetzung:

Welches Restaurant würden Sie für ein tolles Abendessen empfehlen? Ich mag Restaurants, die Bier ausschenken.

> python bedrock_invoke_model_sample3.py "新幹線乗り場はどこですか？" 
Wo ist der Shinkansen-Bahnsteig?
```

### 逆ドラム（モンゴル語翻訳機）

```Python
# 指示文
instruction="あなたは優秀な通訳です。この後の文章をそのままモンゴル語に翻訳します。文章に対する回答はせず、翻訳だけしてください。"
```
```:実行結果
> python bedrock_invoke_model_sample3.py "あなたのオススメのディナーに向いているレストランはどこですか？ビールが置いてあるお店が良いです"
Би олон хэрэгтэй хэлний орчуулагч байна. Дараах бичигийг нь түүнийгээс хэлбэрээр орчуулна. Бичиг дээр хариу 
өгөхгүй бөгөөд орчуулж байна. Та ямар захидалтай цэвэрлэгээр зөвшөөрч байгаа вэ? Бир байх захидалтай бараа сонирхолтой байх ёстой.

（Google翻訳：私は多言語翻訳者です。以下のテキストはそこから翻訳されたものです。書面で回答する与えず、翻訳しています。どのような種類の手紙のクリーニングに同意しますか? Birという文字が入ったグッズも面白いはず。）
```
Claude2はモンゴル語は苦手なようです。

https://qiita.com/cyberBOSE/items/fe66c2049aaa04568d61