【AWS SAP 対策講座】APIを作るなら関数URL（Lambda関数）を使えばいいじゃない～API Gatewayって何ですか知りません～

LambdaをAPI化してGETで呼んでみます

# 手順

## 簡易版

Lambdaを選んで

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/61fc9458-0335-4272-865f-8be58fbb2d22.png)

関数　＞　関数の作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/f4898d5f-7068-4fac-9903-0b70adde10c4.png)

こんな感じに

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/43c72de9-bb19-4fcb-ae92-f6b74e0a3e3b.png)

※ポイント
・その他設定から「関数 URL を有効化」を選択してください。
・認証はとりあえずNONE

あとはデフォルトで関数の作成をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/23c651e0-7cf8-463b-aa38-b535e6a33aa2.png)

関数 URLが作成されるのでクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/38dfb8f4-4474-4cfb-bc0d-4b27a0a8c302.png)

はい、こんにちは。
これでおしまいです。簡単ですね、お疲れ様でした！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/4de591dd-3b43-4c67-924b-c658cc8930d0.png)

## ちょっと凝ってみる

こんにちはするAPIじゃ使い物にならないので、GETリクエストでパラメータを受け付けてみましょう。

claude-3-sonnetにコードを作ってもらいましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/487cce60-e009-41cd-9eea-de2e18a09f19.png)

作ってもらったコードを赤枠箇所に張り付けます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/649645da-9015-4cba-92b1-5fd1fc71f48e.png)

Deployします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/571195d9-4deb-4ece-a76a-c4b033d3a7d5.png)

先ほど表示した関数 URLに「？」でパラメータを追加して実行すると表示できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/673f6e57-6d30-4a84-862f-930a02ea5b5f.png)

コードも置いておきます。

```lambda_function.py
import json

def lambda_handler(event, context):
    try:
        # クエリパラメータから'prompt'を取得
        query_params = event.get('queryStringParameters', {}) or {}
        prompt = query_params.get('prompt', '')
        
        # プロンプトの有無をチェック
        if prompt:
            message = f"プロンプトを受け取りました: {prompt}"
        else:
            message = "プロンプトが指定されていません"
        
        # レスポンスの作成
        response = {
            "statusCode": 200,
            "headers": {
                "Content-Type": "application/json"
            },
            "body": json.dumps({
                "message": message,
                "prompt": prompt
            }, ensure_ascii=False)
        }
        
        return response
        
    except Exception as e:
        return {
            "statusCode": 500,
            "headers": {
                "Content-Type": "application/json"
            },
            "body": json.dumps({
                "error": str(e)
            }, ensure_ascii=False)
        }
```


## もう少し凝ってみる

https://qiita.com/Jasmine_teeeeee/items/74eebc784da34c523d1f

もう少し進んで、
ここで作成したBedrockを呼び出せるLambda関数をAPI化してみたいと思います。

以下でコードを書き換えてください。上記手順の設定が完了できていればAPI経由でBedrockを呼び出せます。

```lambda_function.py
import boto3
import json
import urllib.parse

def lambda_handler(event, context):
    try:
        # API Gatewayからのクエリパラメータを取得
        query_params = event.get('queryStringParameters', {}) or {}
        prompt = query_params.get('prompt', '')
        
        # URLエンコードされた日本語プロンプトをデコード
        prompt = urllib.parse.unquote(prompt)
        
        # プロンプトが空の場合はエラーレスポンスを返す
        if not prompt:
            return {
                "statusCode": 400,
                "headers": {
                    "Content-Type": "application/json"
                },
                "body": json.dumps({
                    "error": "プロンプトが指定されていません"
                }, ensure_ascii=False)
            }
            
        # Bedrock Runtime クライアントを初期化
        brt = boto3.client(service_name="bedrock-runtime", region_name="us-west-2")
        
        # Bedrockに送信するリクエストボディを構築
        body = json.dumps({
            "anthropic_version": "bedrock-2023-05-31",
            "messages": [{"role": "user", "content": prompt}],
            "max_tokens": 300,
            "temperature": 0.1,
        })
        
        modelId = "anthropic.claude-3-sonnet-20240229-v1:0"
        accept = "application/json"
        contentType = "application/json"
        
        # Bedrock APIを呼び出し
        response = brt.invoke_model(
            body=body,
            modelId=modelId,
            accept=accept,
            contentType=contentType
        )
        
        # Bedrockからのレスポンスを解析
        response_body = json.loads(response.get("body").read())
        
        # API Gatewayに返すレスポンスを構築
        return {
            "statusCode": 200,
            "headers": {
                "Content-Type": "application/json"
            },
            "body": json.dumps({
                "prompt": prompt,
                "response": response_body
            }, ensure_ascii=False)
        }
        
    except Exception as e:
        # エラーが発生した場合のレスポンス
        return {
            "statusCode": 500,
            "headers": {
                "Content-Type": "application/json"
            },
            "body": json.dumps({
                "error": str(e)
            }, ensure_ascii=False)
        }
```

こんな感じ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/95e783d0-07b3-4e67-9b75-52d360056491.png)