アプリケーションに制限付き AI リクエストを追加する

AWSBeginner
オンラインで実践に進む

はじめに

文書要約コマンドには、AI 依存先に対する予測可能な制限が必要です。提供されたアプリケーションに制限付き Bedrock クライアントを追加し、長すぎる入力を推論前に拒否して、サービス障害や遅い応答を元の例外を公開せず処理します。

Python 入門と前のラボの構造化出力検証を理解している必要があります。コマンドのインターフェースと解析器は提供済みなので、リクエスト境界に集中できます。この新規 VM は専用の文書、設定済み ID、推論枠を持ちます。

認定試験との関連

認定 試験タスク 演習
AI Practitioner (AIF-C01) タスク 3.1、3.2 推論出力を制限し、アプリケーション内で生成応答を処理する。

draw.io で作成した概念図:アプリケーションは制限付き Converse リクエストの前に文書長を確認し、確認すべき要約または安全な診断エラーを返します。

制限付き Bedrock クライアントを接続する

このステップではコマンドのクライアントを実装し、実際の構造化要約を生成します。

ワークスペースに移動します:

cd /home/labex/project

元の文書とコマンドオプションを読みます:

cat incident.txt
/opt/labex/aws/venv/bin/python application.py --help

インシデントは INC-204 です。application.py は文書を読み JSON を表示します。client.request_summary を呼び、提供された response_parser.py が終了理由と前に学んだ 3 つの文字列を確認します。初期の client.py は未実装を報告し、リクエストを送りません。

入力上限は推論枠を使う前にアプリケーションを保護します。この例は空でない 1–1000 文字を受け入れ、出力を 768 トークンに固定し、SDK の接続と読み取りに明示的なタイムアウトを設定します。total_max_attempts: 1 は最初の 1 回のみで、自動再試行はありません。読み取りタイムアウトは接続上の待機を制限し、すべての操作がその時刻ちょうどに終わる保証ではありません。

初期クライアントを次の実装に置き換えます。ClientError はサービスのエラー応答、ReadTimeoutError は読み取り待機の期限切れを示します。どちらも短い診断 JSON になります。元の例外、リクエストヘッダー、認証情報は結果に含めません:

cat > client.py <<'EOF'
import boto3
from botocore.config import Config
from botocore.exceptions import BotoCoreError, ClientError, ReadTimeoutError
from response_parser import summarize_response


def request_summary(document, endpoint_url, read_timeout):
    if not document.strip() or len(document) > 1000:
        return {'status': 'rejected', 'reason': 'input_limit'}
    client = boto3.client('bedrock-runtime', endpoint_url=endpoint_url,
        config=Config(proxies={}, connect_timeout=3, read_timeout=read_timeout,
                      retries={'total_max_attempts': 1}))
    try:
        response = client.converse(
            modelId='labex.text-v1:0',
            system=[{'text': 'Summarize only facts supplied in the incident document. Return exactly one JSON object with string fields incident_id, impact and next_action. No Markdown fences, extra keys or surrounding prose. Do not turn planned work into completed work.'}],
            messages=[{'role': 'user', 'content': [{'text': document}]}],
            inferenceConfig={'maxTokens': 768, 'temperature': 0})
    except ReadTimeoutError:
        return {'status': 'unavailable', 'reason': 'read_timeout'}
    except ClientError as error:
        code = error.response.get('Error', {}).get('Code')
        reason = 'busy' if code == 'ThrottlingException' else 'service_unavailable'
        return {'status': 'unavailable', 'reason': reason}
    except BotoCoreError:
        return {'status': 'unavailable', 'reason': 'connection_failed'}
    return summarize_response(response)
EOF

正常に設定された Bedrock エンドポイントに対して実行します。> accepted.json は表示結果を保存します:

/opt/labex/aws/venv/bin/python application.py > accepted.json

読みます:

cat accepted.json

status: ok と 3 つの要約フィールドを期待します。文書と意味を照合します。上部の AWS View で実際の完了リクエストを展開してテキストを比較します。出力上限は生成トークンを制限し、入力文字数は独立した方針です。キャッシュは実際のモデル出力を再利用し、追加の credits 消費がない場合があります。

実際の AWS View チェックポイント:完了したリクエストに使用量、終了理由、生成要約が表示されます。数値や表現は変わる場合があります。

推論前に長すぎる入力を拒否する

このステップでは入力予算を超える文書が拒否されることを確認します。

提供された oversized.txt は 1000 文字を超えます。wc -m で文字数を数えます:

wc -m oversized.txt

同じアプリケーションにこのファイルを渡します:

/opt/labex/aws/venv/bin/python application.py --document oversized.txt > too-long.json

この意図的な拒否は終了コード 2 です。echo $? は直前のコマンドの終了コードを表示します:

echo $?

安全な結果を読みます:

cat too-long.json

status: rejected と reason: input_limit を期待します。クライアントは推論リクエストの構築前に確認するため、AWS View は以前の完了リクエスト 1 つのままです。入力拒否は追加消費を防ぎますが、結果ファイルの削除では過去の消費を取り消せません。

サービス障害と読み取りタイムアウトを処理する

このステップでは明示された 2 つのローカル通信テストサービスでエラー境界を確認します。

次のエンドポイントは意図的にエラーを返すか応答を遅らせます。モデルを呼ばず、推論 credits を使いません。テスト用依存先であり、成功推論の代替提供者ではありません。

ポート 5001 のサービス利用不可テストを使います:

/opt/labex/aws/venv/bin/python application.py --endpoint-url http://127.0.0.1:5001 > unavailable.json

期待された失敗は終了コード 3 です。診断結果を確認します:

cat unavailable.json

status: unavailable と reason: service_unavailable を期待します。スタックトレース、SDK 例外の文章、認証情報はありません。

ポート 5002 は 3 秒待ちます。このテストでは読み取り待機を 1 秒に変更します:

/opt/labex/aws/venv/bin/python application.py --endpoint-url http://127.0.0.1:5002 --read-timeout 1 > timed-out.json

結果を読みます:

cat timed-out.json

status: unavailable と reason: read_timeout を期待します。SDK の試行は 1 回です。タイムアウトは上流の推論が取り消された、または無料だった証拠ではありません。実際の上流はクライアントが待機をやめた後も完了する場合があります。再試行前に処理中・失敗のリクエストと枠を確認し、無条件の再試行ループは追加しないでください。

AWS View にはステップ 1 の実際のリクエストのみが残るはずです。通常の 150 秒の読み取り待機は、この演習での有限の選択です。実際のアプリケーションでは遅延予算に応じてタイムアウト、再試行方針、ユーザーへの表示を決めます。公式 Config 参照は接続、読み取り、試行回数の別々の制御を説明しています。

テスト出力を削除し、動作するアプリケーションを残す

このステップでは動作するクライアントと提供されたアプリケーションを残し、4 つのローカル結果を削除します。

削除前に正常動作と失敗の確認を通してください。指定された出力のみを削除します:

rm accepted.json too-long.json unavailable.json timed-out.json

残ったファイルを一覧にします:

ls

application.py、client.py、response_parser.py、文書、テストケースを残します。Converse は永続的なワークロードを作っておらず、出力削除で credits は戻りません。ソースは VM 終了まで追加練習に使えます。

まとめ

実際の Bedrock リクエストを要約コマンドに接続し、入出力を制限し、自動再試行を無効にして有限の待機時間を設定しました。既定の成功結果で推論を置き換えずに障害とタイムアウトをテストし、安全な診断を返してローカル出力のみを削除しました。