はじめに
以前の記事では、Command R/R+のsearch_queries_only:trueを利用し、入力テキストを検索クエリに適した表現へと書き換えて検索を行いました。例えば、「SQLインジェクションはどのようにして発生するのか。その原因と対策を解説してください。Web開発者がSQLインジェクションを防ぐために取るべき対策は何ですか。」という質問に対して「SQLインジェクション 原因 対策」という検索クエリが生成されました。同様の方式(Rewrite-Retrieve-Read)をClaude3.5 Sonnetを利用して実装した場合、実装方法や出力にどのような違いがるか比較してみました。
参考情報
出力結果
比較用コードを実行しCommand RとCloude 3.5 Sonnetのそれぞれで検索クエリを出力してみました。
Claude3.5 Sonnetを利用した処理では、生成する検索クエリの個数やフォーマットを後述のプロンプトで詳細に指定しました。一方、Command Rではそのような指定が行えなえないようなのでなにも指定していません。preambleパラメータでプロンプトを指定できるかと考え試しましたが、出力内容に変化がありませんでした。search_queries_only:Trueの場合、このパラメータは無視されるのかもしれません。
2024-06-29 16:48:25,021 [INFO] Found credentials in shared credentials file: ~/.aws/credentials
origin_query: 代表的なLLMを列挙し、それぞれの特徴を箇条書きで列挙してください。
********************************************************************************
Command Rの検索クエリ:
LLMの種類と特徴
********************************************************************************
Cloude 3.5 Sonnetの検索クエリ:
LLM 代表的 特徴 比較
大規模言語モデル 種類 特徴 list
AI language models comparison features GPT-4 PaLM LLaMA
Command R/R+
Command Rを使った検証では、入力テキストに対し常に「LLMの種類と特徴」という出力でした。temperature:1でも出力は変化しませんでした。 また、以下の記事で取り上げられている入力テキスト「S3とEFSの暗号化方式を比較してください」で試したところ、記事とまったく同じ検索クエリが生成されました。
今回のユーザー入力テキスト「S3とEFSの暗号化方式を比較してください」からは、「S3 encryption」「EFS encryption」という2つの検索クエリーが生成されました。
これらのことから、Command Rの検索クエリ生成は、temperatureパラメータの設定ではなく入力テキストの内容に強く依存しているようです。
Command R+ (cohere.command-r-plus-v1:0) を使用した場合は、入力テキスト「代表的なLLMを列挙し、それぞれの特徴を箇条書きで列挙してください。」に対する出力は「代表的なLLM」でした。 Command R/R+のいずれにしても、出力が入力テキストに対して固定されてしまっている印象です。
Command R/R+を使った検索クエリの出力結果
LLMの種類と特徴
代表的なLLM
Claude3.5 Sonnet
Claude3.5 Sonnetでは、入力テキストに対する出力は以下のように実行のたびに変化しました。この程度の単語のばらつきがあればRAGの精度向上が期待できそうです。また、検索クエリの長さや言語、フォーマットはプロンプトにより制御できるため、後続の検索処理も柔軟に対処できそうです。
コード内のプロンプトテンプレートは、Amazon Kendra と Amazon Bedrock で構成した RAG システムに対する Advanced RAG 手法の精度寄与検証にあるものを基にしました。
Claude3.5 Sonnetを使った検索クエリの出力結果例
LLM models comparison
代表的な大規模言語モデル 特徴 比較
ChatGPT GPT-4 PaLM BERT LLaMA 機能 性能 違い
LLM 代表的モデル 特徴 比較
大規模言語モデル 種類 特徴 一覧 comparison
人工知能 AI 言語モデル GPT BERT LLaMA 特徴 pros cons
サンプルコード
# Command R+とClaude3.5 Sonnetでの検索クエリ生成の比較
import json
import logging
from typing import Any, Dict, List
import boto3
logging.basicConfig(
format="%(asctime)s [%(levelname)s] %(message)s",
level=logging.INFO
)
logger = logging.getLogger(__name__)
bedrock_client = boto3.client("bedrock-runtime")
MODEL_ID = "anthropic.claude-3-5-sonnet-20240620-v1:0"
MODEL_ID_SEARCH_QUERY = "cohere.command-r-v1:0"
def create_search_query_commandr(input_text: str):
request_body = {
"message": input_text,
"search_queries_only": True, # 検索クエリーのみを生成する
"max_tokens": 500,
"temperature": 0,
}
response = _invoke_bedrock_model(request_body, MODEL_ID_SEARCH_QUERY)
response_body = json.loads(response["body"].read())
search_queries = response_body["search_queries"]
print("\n" + "*" * 80)
print("Command Rの検索クエリ:")
for query in search_queries:
query_text = query.get("text")
print(query_text)
def create_search_query_claude(input_text: str):
# 生成する検索クエリの数
n_queries = 3
# 検索クエリの生成するためのプロンプト
system_instruction = _create_system_instruction(n_queries)
request_body = {
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 500,
"temperature":0,
"system": system_instruction,
"messages": [
{
"role": "user",
"content": input_text,
},
],
}
response = _invoke_bedrock_model(request_body, MODEL_ID)
response_body = json.loads(response["body"].read())
search_queries = response_body["content"][0]['text'].split(',')
print("\n" + "*" * 80)
print("Cloude 3.5 Sonnetの検索クエリ:")
for query_text in search_queries:
print(query_text)
def _create_system_instruction(n_queries: int) -> str:
return f'''
検索エンジンに入力するクエリを最適化し、様々な角度から検索を行うことで、より適切で幅広い検索結果が得られるようにします。
具体的には、類義語や日本語と英語の表記揺れを考慮し、多角的な視点からクエリを生成します。
ユーザーの入力した質問文に基づいて、{n_queries}個の検索用クエリを生成してください。
<example>タグ内にあるように、各検索用クエリは30トークン以内とし、日本語と英語を適切に混ぜて使用することで、広範囲の文書が取得できるようにしてください。
生成されたクエリは、<format>タグ内のフォーマットに従って出力してください。
<format>タグの内容を参考にするが、回答に<format>タグを含めないこと。
<example>
question: Knowledge Bases for Amazon Bedrock ではどのベクトルデータベースを使えますか?
query 1: Knowledge Bases for Amazon Bedrock vector databases engine DB
query 2: Amazon Bedrock ナレッジベース ベクトルエンジン vector databases DB
query 3: Amazon Bedrock RAG 検索拡張生成 埋め込みベクトル データベース エンジン
</example>
<format>
for文でクエリを取得できるようカンマで区切ってください。
クエリには改行コードを含めないでください。
クエリ以外の文章を含めないでください。
</format>
'''
def _invoke_bedrock_model(request_body: Dict[str, Any], model_id: str) -> Dict[str, Any]:
return bedrock_client.invoke_model(
body=json.dumps(request_body),
contentType="application/json",
accept="application/json",
modelId=model_id,
)
def main():
input_text = "代表的なLLMを列挙し、それぞれの特徴を箇条書きで列挙してください。"
print(f"origin_query: {input_text}")
# Command Rで検索クエリーを生成する
create_search_query_commandr(input_text)
# Claude 3.5 Sonnet で検索クエリーを生成する
create_search_query_claude(input_text)
if __name__ == "__main__":
main()
まとめ
Amazon BedrockでCommand R/R+とClaude3.5 Sonnetで検索クエリ生成を比較しました。 Command R/R+はsearch_queries_onlyパラメータのみで検索クエリ生成を行える手軽さがあるものの、出力内容が乏しくプロンプトなどで制御できませんでした。
一方、Claude3.5 Sonnetを使った場合(もちろん他のモデルでも可)は、プロンプトで検索クエリの出力を制御できるため後続の処理を含め柔軟に対応できそうです。