できないと思ってたらできた。
通常のConverse API呼び出し
Cohere Command Rを使って、簡単なテキストを渡してみます。
import json
import boto3
client = boto3.client("bedrock-runtime")
result = client.converse(
    modelId="cohere.command-r-v1:0",
    messages=[
        {
            "role": "user",
            "content": [{"text": "こんにちは。ダジャレを言ってみて"}],
        }
    ],
)
print(json.dumps(result, indent=2, ensure_ascii=False))
実行します。
python app.py
{
  "ResponseMetadata": {
    "RequestId": "156cd130-f7b9-4b7f-b7fc-91d379d51706",
    "HTTPStatusCode": 200,
    "HTTPHeaders": {
      "date": "Thu, 11 Jul 2024 14:36:19 GMT",
      "content-type": "application/json",
      "content-length": "248",
      "connection": "keep-alive",
      "x-amzn-requestid": "156cd130-f7b9-4b7f-b7fc-91d379d51706"
    },
    "RetryAttempts": 0
  },
  "output": {
    "message": {
      "role": "assistant",
      "content": [
        {
          "text": "こんにちは! 夏が来ると、海に「行きたし貝」!"
        }
      ]
    }
  },
  "stopReason": "end_turn",
  "usage": {
    "inputTokens": 13,
    "outputTokens": 19,
    "totalTokens": 32
  },
  "metrics": {
    "latencyMs": 531
  }
}
ダジャレかどうかはさておき、動作しました。
Command R固有のパラメーター
Command Rシリーズは、search_queries_onlyパラメーターを指定することで、通常のテキスト生成ではなく、検索クエリー生成を行うことができます。
Invoke Modelで呼び出す場合はこのような感じです。
response = client.invoke_model(
    modelId="cohere.command-r-v1:0",
    body=json.dumps(
        {
            "message": "KendraとBedrockが両方とも使えるリージョンを知りたいです。",
            "search_queries_only": True,
        }
    ),
)
response_body = json.loads(response.get("body").read())
print(json.dumps(response_body["search_queries"], indent=2, ensure_ascii=False))
[
  {
    "text": "Kendra available regions",
    "generation_id": "648f6d66-d0f7-48f4-b3e1-d2c970ad833c"
  },
  {
    "text": "bedrock available regions",
    "generation_id": "648f6d66-d0f7-48f4-b3e1-d2c970ad833c"
  }
]
詳細な使い方は、以前投稿したこちらを参照ください。
Amazon BedrockにCohere Command R と Command R+ が来たよ!RAGがすげーよ!
https://qiita.com/moritalous/items/16797ea9d82295f40b5e
Converse APIでモデル固有のパラメーターを指定する
Converse APIではパラメーターの共通化が図られているため、モデル固有のパラメーターを渡せないと思っていたのですが、実はできました。
「additionalModelRequestFields」と「additionalModelResponseFieldPaths」の2つを追加します。
- additionalModelRequestFields: 追加で指定するリクエストパラメーターをセット
- additionalModelResponseFieldPaths: レスポンスに追加したいJSONポインター
result = client.converse(
    modelId="cohere.command-r-v1:0",
    additionalModelRequestFields={"search_queries_only": True},
    additionalModelResponseFieldPaths=["/search_queries"],
    messages=[
        {
            "role": "user",
            "content": [
                {"text": "KendraとBedrockが両方とも使えるリージョンを知りたいです。"}
            ],
        }
    ],
)
print(result)
こうすることで、「additionalModelResponseFields」の項目としてsearch_queriesを取得できます。
{
  "ResponseMetadata": {
    "RequestId": "271d3b01-6fdd-4159-9a66-58ab574c9867",
    "HTTPStatusCode": 200,
    "HTTPHeaders": {
      "date": "Thu, 11 Jul 2024 14:47:32 GMT",
      "content-type": "application/json",
      "content-length": "416",
      "connection": "keep-alive",
      "x-amzn-requestid": "271d3b01-6fdd-4159-9a66-58ab574c9867"
    },
    "RetryAttempts": 0
  },
  "output": {
    "message": {
      "role": "assistant",
      "content": [
        {
          "text": ""
        }
      ]
    }
  },
  "stopReason": "end_turn",
  "usage": {
    "inputTokens": 19,
    "outputTokens": 8,
    "totalTokens": 27
  },
  "metrics": {
    "latencyMs": 475
  },
  "additionalModelResponseFields": {
    "search_queries": [
      {
        "text": "Kendra available regions",
        "generation_id": "6edb49eb-3175-4f76-89a3-efd44379a57e"
      },
      {
        "text": "bedrock available regions",
        "generation_id": "6edb49eb-3175-4f76-89a3-efd44379a57e"
      }
    ]
  }
}
通常のテキスト生成の際にセットされる["output"]["message"]["content"][0]["text"]には、空の値が返却されます。
おまけ:Command Rにドキュメントを渡してRAGしてもらうやつのConverse版
以前投稿した内容のConverse API版ができました。
import json
import boto3
from duckduckgo_search import DDGS
client = boto3.client("bedrock-runtime")
model_id = "cohere.command-r-plus-v1:0"
question = "AWS上でRAGを構築するときのおすすめのLLMは?検索はどうするといいの?フレームワークも教えて"
# 検索クエリを生成
result = client.converse(
    modelId=model_id,
    additionalModelRequestFields={"search_queries_only": True},
    additionalModelResponseFieldPaths=["/search_queries"],
    messages=[
        {
            "role": "user",
            "content": [{"text": question}],
        }
    ],
)
search_queries = result["additionalModelResponseFields"]["search_queries"]
# 検索クエリを使って検索
documents = []
for search_query in search_queries:
    text = search_query["text"]
    search_results = DDGS().text(text, max_results=5)
    documents.extend(search_results)
# 回答生成
result = client.converse(
    modelId=model_id,
    additionalModelRequestFields={"documents": documents},
    additionalModelResponseFieldPaths=["/chat_history", "/citations"],
    messages=[
        {
            "role": "user",
            "content": [{"text": question}],
        }
    ],
)
print(json.dumps(result, indent=2, ensure_ascii=False))
