Skip to main content

Amazon Bedrock と W&B Weave をはじめよう

Weave を使って API 呼び出しをトレース・管理し、LLM を最大限に活用する この記事は翻訳版です。訳語の誤りなどがあれば、コメント欄でお知らせください。
Created on August 26|Last edited on August 26
W&B の一般提供開始を発表できることを大変誇りに思います WeaveLLM ベースのアプリケーションを開発し、本番運用まで持っていくためのツール群です。Weave を使うと、次のことができます。
  • ログバージョン開発から本番までの LLM のやり取りと周辺データ
  • 実験プロンプト手法、モデルの切り替え、各種パラメータ
  • 評価モデルを評価し、進捗を測定する
アクセス先 https://wandb.me/weave はじめましょう。
💡
このセクションでは、次の使い方を順に説明しますAmazon BedrockWeights & Biases の Weave とあわせて
さあ、はじめましょう。



Amazon Bedrock:AWS 上の LLM ハブ

Amazon Bedrock は、AI21 Labs、Anthropic、Cohere、Meta、Mistral AI、Stability AI、Amazon の高性能な基盤モデルを単一の API で提供するフルマネージドサービスです。
安全性、プライバシー、責任ある利用に配慮した生成 AI アプリケーションを構築するための機能を提供します。最先端の基盤モデルを試し、カスタマイズできるほか、自社のシステムやデータソースと連携するエージェントを構築し、インフラ管理なしにサーバーレスで AI 機能をデプロイできます。なお、利用にあたっては準備が必要です。 モデルへのアクセスをリクエストする Bedrock の LLM を利用するには
コードを見ていきましょう。

Bedrock で LLM を呼び出す方法

このチュートリアルを進めるには、Weights & Biases と Bedrock の両方にアクセスできる必要があります。上記のリンクからすぐに開始できます。
まず、Weave をインストールします。
!pip install weave
次に、LLM とのやり取りをバージョン管理するための Weave プロジェクトを作成します。
import weave
weave.init('bedrock-weave')
では、呼び出し用の関数にデコレータを付けましょう。 @weave.op() デコレータ:
import json
import boto3

@weave.op() # <- just add this 😎
def generate_text(
model_id: str,
prompt: str,
max_tokens: int=400,
temperature: float=0.7,
) -> dict:
# Check your region model access page, in my case on us-east-1 region:
bedrock = boto3.client(service_name='bedrock-runtime')

body = json.dumps({
"prompt": prompt,
"max_tokens": max_tokens,
"temperature": temperature,
})
response = bedrock.invoke_model(body=body, modelId=model_id)

response_body = json.loads(response.get('body').read())
return response_body.get('outputs')
これでモデルを呼び出し、最後に生成されるリンクをクリックできます。Amazon Bedrock の API でファウンデーションモデルを使うには、その モデル ID
レシピ生成に Mistral 7B モデルを使う例を示します。
model_id = 'mistral.mistral-7b-instruct-v0:2'

# this is the required prompt format for mistral instruct
prompt = """<s>[INST] Create a Vegan Carbonara Recipe[/INST] """

outputs = generate_text(model_id, prompt)

for index, output in enumerate(outputs):

print(f"Output {index + 1}\n----------")
print(f"Text:\n{output['text']}\n")
print(f"Stop reason: {output['stop_reason']}\n")

# Output 1
# ----------
# Text:
# Vegan Carbonara Recipe:

# Ingredients:
# - 12 oz (340g) spaghetti or other long pasta
# - 1/2 cup (120ml) unsweetened almond milk or cashew cream
# - 1/2 cup (100g) nutritional yeast
# - 1/3 cup (80g) cooked and mashed sweet potato or pumpkin
# - 1 tbsp olive oil
# - 1 cup (200g) steamed or roasted vegetables such as zucchini, broccoli, or asparagus
# - 1/2 cup (100g) chopped mushrooms
# - 1/2 cup (100g) chopped onion
# - 1 clove garlic, minced
# - 1/2 cup (100g) chopped walnuts or cashews, toasted
# - 1/2 cup (100g) vegetable bacon or pancetta, cooked and crumbled (optional)
# - Salt and freshly ground black pepper, to taste
# - Red pepper flakes, for serving (optional)
# - Fresh parsley or basil, for serving (optional)

# Instructions:

# 1. Cook the pasta according to package instructions in salted water until al dente. Drain and set aside, reserving 1 cup of the pasta water.

# 2. In a blender or food processor, combine the almond milk or cashew cream, nutritional yeast, mashed sweet potato or pumpkin, and olive oil. Blend until smooth and creamy. Taste and adjust seasoning with salt and pepper as needed.

# 3. In a large skillet, sauté the chopped onion, garlic, and

# Stop reason: length

Weave は何を追跡しますか?

概要としては
  • コード生成 AI の API 呼び出しを囲むすべてのコードがバージョン管理され、保存されるようにする
  • データ可能な限り、データセットやナレッジストアなどをバージョン管理し、保存すること
  • トレース生成 AI 呼び出しを囲む関数のトレースを恒久的に保存する
Weave を使えば簡単です。任意の Python 関数を次のようにラップします @weave.op() すると Weave が関数のコードを取得してバージョン管理し、すべての呼び出しについて入力と出力を含むトレースを記録します。
例としては次のとおりです。

ご覧のとおり、停止理由は length 、そのため、〜を増やす必要があるかもしれません max_tokens 完全な回答を得るには param を調整します。パラメータを変更して関数を再実行すれば対応できます。
すると、完全な出力を含む新しいトレースへのリンクが得られます。


入れ子の呼び出しを追跡する

Python では任意の関数にデコレータを付けられます。たとえば、次のように作成できます。 run 関数にデコレータを付け、プロンプト整形と LLM 呼び出しのトレースを個別に追跡します。
@weave.op()
def format_prompt(prompt: str) -> str:
return f"""<s>[INST] {prompt}[/INST] """

@weave.op()
def run(prompt: str) -> None:
prompt = format_prompt(prompt)

outputs = generate_text(model_id, prompt, max_tokens=1000)
for index, output in enumerate(outputs):

print(f"Output {index + 1}\n----------")
print(f"Text:\n{output['text']}\n")
print(f"Stop reason: {output['stop_reason']}\n")
run("What clothes do I need to pack in winter for a trip to Chamonix?")


モデルを切り替えて試す

Bedrock の大きな強みは、次の設定を変えるだけでモデルを素早く切り替えられる点です モデル IDたとえば、より大きなものを取得できます Mixtral-8x7B そして実験を再実行します。
model_id = 'mistral.mixtral-8x7b-instruct-v0:1'

prompt = """<s>[INST] Create a Vegan Carbonara Recipe[/INST] """

outputs = generate_text(model_id, prompt, max_tokens=1000)

for index, output in enumerate(outputs):

print(f"Output {index + 1}\n----------")
print(f"Text:\n{output['text']}\n")
print(f"Stop reason: {output['stop_reason']}\n")
💡
モデルを切り替える際は、プロンプトの書式が異なる場合がある点に注意してください。今回のケースでは両方のモデルが同じプロンプト構造を共有しているため、更新は不要です。
💡

Anthropic の Claude モデルが Bedrock で利用可能に

Bedrock の主要な特長のひとつは、…が利用可能な点です Anthropic の高性能な Claude モデル群これらのモデルはサイズや性能がさまざまですが、それらを活用するためにコードを大きく変える必要はありません。
@weave.op() # <- just add this 😎
def anthropic_call(
model_id: str,
messages: str,
max_tokens: int=400,
system_prompt: str=None,
) -> dict:
bedrock = boto3.client(service_name='bedrock-runtime')


body = json.dumps({
"system": system_prompt,
"messages": messages,
"max_tokens": max_tokens,
"anthropic_version": "bedrock-2023-05-31"
})
response = bedrock.invoke_model(
body=body,
modelId=model_id
)

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

outputs = response_body.get('content')
return outputs

モデルアクセス

Amazon Bedrock のユーザーは、利用したいモデルへのアクセスをリクエストする必要があります。追加のモデルにアクセスするには、Amazon Bedrock コンソールのナビゲーションペインで「Model access」を選択してください。詳しくは「Model access」を参照してください。
💡
Bedrock ランディングページの左下にあるリンクを確認してください

さらに高度なユースケース:ドキュメント翻訳

Anthropic のモデルは非常に強力で、複雑なタスクの解決が可能です。この例では、Claude を使って翻訳を行います。 Weights & Biases のドキュメントサイト
まず、このモデルはメッセージのリスト形式を想定しているため、プロンプトを少し異なる方法で整形する必要があります。 role および content。システムプロンプトは追加で渡されます kwargs ペイロードに対して:
from pathlib import Path
from dataclasses import dataclass

system_prompt = """
# Instructions

You are a documentation translation assistant from English to {output_language}. We are translating valid docusaurus flavored markdown. Some rules to remember:

- Do not add extra blank lines.
- The results must be valid docusaurus markdown
- It is important to maintain the accuracy of the contents but we don't want the output to read like it's been translated. So instead of translating word by word, prioritize naturalness and ease of communication.
- In code blocks, just translate the comments and leave the code as is.

## Formatting Rules

Do not translate target markdown links. Never translate the part of the link inside (). For instance here [https://wandb.ai/site](https://wandb.ai/site) do not translate anything, but on this, you should translate the [] part:
[track metrics](./guides/track), [create logs](./guides/artifacts).
"""

human_prompt = """
Here is a chunk of documentation in docusaurus Markdown format to translate. Return the translation only, without adding anything else.
<Markdown start>
{md_chunk}
<End of Markdown>
"""

@dataclass
class PromptTemplate:
system_prompt: str
human_prompt: str
language: str
@weave.op() # <- just add this 😎
def format_claude(self, md_chunk):
"A formatting function for Mistral Instruct models"
system_prompt = self.system_prompt.format(output_language=self.language)
human_prompt = self.human_prompt.format(md_chunk=md_chunk)
messages = [{"role":"user", "content":human_prompt}]
return system_prompt, messages
次に、PromptTemplate とモデル呼び出しを内部でリファクタリングできます。 weave.Model object。こうしてコードを整理できます。
from weave import Model

class ClaudeDocTranslator(Model):
model_id: str='anthropic.claude-3-sonnet-20240229-v1:0'
max_tokens: int=2048
prompt_template: PromptTemplate
@weave.op()
def format_doc(self, path: Path) -> str:
"Read and format the document"
doc = Path(path).read_text()
system_prompt, messages = prompt_template.format_claude(doc)
return system_prompt, messages
@weave.op()
def translate(self, path: Path) -> dict:
system_prompt, messages = self.format_doc(path)
output = anthropic_call(
self.model_id,
messages=messages,
system_prompt=system_prompt,
max_tokens=self.max_tokens)
return output[0]['text']
それでは、ドキュメントをひとつ翻訳してみましょう。
model = ClaudeDocTranslator(prompt_template=prompt_template)
out = model.translate(Path("./docs/quickstart.md"))

まとめ

この短いチュートリアルで、Weights & Biases と Bedrock の統合を楽しんでいただけたなら幸いです。はじめるには、いくつかの認証情報が必要です。次のことができます。
楽しいモデリングを!