企業平台

AWS Bedrock 第一次呼叫 Claude:boto3 設定、converse 與多輪對話

在 AWS Bedrock 呼叫 Claude 需要三個元件:用 boto3 建立的 Bedrock Runtime 客戶端、指定模型的 model ID、以及帶著文字的 user message。用 client.converse 送出請求,從回應的 output 取出生成文字;跨區域的模型可用性問題,則交給 inference profile 自動路由解決。
AWS Bedrock 第一次呼叫 Claude:boto3 設定、converse 與多輪對話:文章重點卡

AWS Bedrock 第一次呼叫 Claude:boto3 設定、converse 與多輪對話

上一篇看懂了 Bedrock 的定位與請求流程,這一篇正式動手:從建立客戶端、避開「模型不存在」的區域陷阱,到送出第一個 converse 呼叫、把多輪對話的上下文管好。全程用 Python 與 boto3,每一段程式碼都可以直接照著打。

區域可用性這件事特別容易踩雷:明明程式碼一字不差,換個區域就報錯。先把這個坑認識清楚,可以省下你未來一個下午的除錯時間。

你將學到什麼

三個必備元件

客戶端、model ID、使用者訊息,缺一不可。

區域與 inference profile

為什麼模型會「不存在」,以及跨區推論怎麼救。

第一個 converse 呼叫

從送出請求到取出生成文字的完整程式碼。

多輪對話與系統提示

歷史自己保管、角色要交替,再用 system 定調。

起手式:三個必備元件

對 Bedrock 發出第一個請求,你需要三樣東西:連上服務的 Bedrock Runtime 客戶端、指定要跑哪個模型的 model ID、以及裝著輸入文字的 user message。這三樣就是每個 Bedrock 請求的最小組成,之後所有進階功能都是在這個骨架上加東西。接下來一樣一樣建立。

建立 Bedrock 客戶端

用 boto3 建立一個連到 Bedrock Runtime 服務的客戶端,並指定區域:

import boto3

client = boto3.client("bedrock-runtime", region_name="us-west-2")

區域陷阱與 inference profile

這裡就是最容易踩的坑:不是每個模型在每個區域都有。假設某個模型只在 us-west-2 託管,而你從 us-east-1 發請求,就會收到一句很難懂的錯誤訊息,說這個模型不存在。程式沒寫錯,只是模型不在你連的那個區域。

解法是 inference profile(跨區推論設定檔)。它知道你選的模型在哪幾個區域託管,發請求時會自動把你導到模型實際所在的區域,你不必再自己記「哪個模型在哪一區」。

你的程式從 us-east-1 發出Inference Profile自動選路us-west-2模型在這裡us-east-2模型也在這裡
inference profile 幫你選路:不管從哪一區發出,請求都會被導到模型實際託管的區域。
去哪裡找 inference profile ID在 AWS Bedrock 主控台找「Cross-region inference」這個分頁,複製你要用的模型的 inference profile ID。不要抄模型目錄主頁上的 model ID,那個沒有跨區路由能力。

組出訊息,送出第一個請求

使用者訊息有固定的結構,第一眼看起來有點囉唆:

user_message = {
    "role": "user",
    "content": [
        {"text": "What's 1+1?"}
    ]
}

content 之所以是清單,是因為一則訊息可以同時裝多種內容:文字、圖片或其他媒體。這個結構讓多模態請求成為可能,現在多打幾個括號,之後就不用改格式。接著用 converse 方法送出請求,並從回應結構裡取出生成的文字:

response = client.converse(
    modelId=model_id,
    messages=[user_message]
)

response["output"]["message"]["content"][0]["text"]

回傳的 assistant 訊息跟你送出的 user 訊息格式完全相同,只是 role 不同。這個一致性讓串接多輪對話變得很自然。回應裡除了訊息本身還帶著不少中繼資料,開發時把整個 response 印出來看一次,對結構會更有感。

多輪對話:歷史自己保管

關鍵觀念:Bedrock 與 Claude 不儲存任何訊息,每次呼叫完全獨立。你先問「1 加 1 是多少」,再單獨送出「再加 3 呢」,Claude 根本不知道你在指什麼。想維持上下文,就要在程式裡自己維護一份訊息清單,每次請求都把完整歷史一起送出。這裡用三個輔助函式把這件事收乾淨:

def add_user_message(messages, text):
    messages.append({
        "role": "user",
        "content": [{"text": text}]
    })

def add_assistant_message(messages, text):
    messages.append({
        "role": "assistant",
        "content": [{"text": text}]
    })

def chat(messages):
    response = client.converse(
        modelId=model_id,
        messages=messages
    )
    return response["output"]["message"]["content"][0]["text"]

流程是:加入使用者問題、呼叫 chat 拿到回答、把回答用 add_assistant_message 收進清單、再加入追問、帶著整份清單再呼叫一次。這時 Claude 看得到完整脈絡,就能理解「再加 3」指的是接在前一題的結果 2 後面繼續算。

還有一條硬規則:角色必須交替,user 接 assistant 再接 user,不能連續兩則同角色,這是 API 的要求,也符合對話的自然節奏。手動管理訊息一開始覺得囉唆,很快就會習慣,而且所有需要上下文的應用都是這個模式。

加上系統提示,定住角色

想讓 Claude 固定扮演某個角色(例如 AWS 雲端支援專員,只談 AWS 方案、不提競品),與其在每則使用者訊息裡塞規則,不如用 system prompt 一次定調:

system_prompt = """
You are an AWS cloud support specialist. Your job is to answer
user queries related to cloud hosting services on AWS.
"""

response = client.converse(
    modelId=model_id,
    messages=messages,
    system=[{"text": system_prompt}]
)

有了系統提示,同一個問題的回答會整個聚焦到你指定的角色上:問資料庫要怎麼架,它只談 AWS 上的做法;問麵包食譜這種離題問題,它會客氣地婉拒、留在角色裡。比起在每則訊息裡塞規則,這種「給它一個角色」的做法不用預想所有情境,回答自然就守在框內。

注意三件事:系統提示不能是空字串、格式是含 text 鍵的字典清單、對話中途不能更換。

順手認識 temperature

converse 還可以帶一個 inferenceConfig,裡面最常用的是 temperature:0 到 1 之間的小數,控制回答偏穩定還是偏有變化。事實問答、程式協助、資料抽取適合低溫(接近 0,輸出幾乎固定);摘要與教學內容適合中溫;腦力激盪、創意寫作適合高溫(接近 1,變化最大)。預設值是 1.0,需要穩定輸出時記得調低:

def chat(messages, system=None, temperature=1.0):
    params = {
        "modelId": model_id,
        "messages": messages,
        "inferenceConfig": {"temperature": temperature}
    }

    if system:
        params["system"] = [{"text": system}]

    response = client.converse(**params)
    return response["output"]["message"]["content"][0]["text"]

到這裡,你已經有一套能連續對話、有角色設定、可調輸出風格的最小可用架構,下一篇再往進階功能走。

參考出處本文取材自 Anthropic 官方 Claude Academy 免費課程「Claude with Amazon Bedrock」,由酒Ann 消化後以自己的視角重新編寫。想看英文原版課程,可到 Claude Academy 修習。

延伸學習

把這篇文章分享給需要的人FacebookLINEThreadsX

常見問答

為什麼呼叫時說模型不存在?
模型不是每個 AWS 區域都有。若模型只在某些區域託管,而你從別的區域發出請求就會失敗。改用 inference profile,AWS 會自動把請求導到模型所在的區域。
訊息的 content 為什麼是清單?
因為一則訊息可以同時包含多種內容,例如文字加圖片。清單結構讓同一則訊息能承載多模態內容,之後不必改結構。
Claude 會記得上一輪對話嗎?
不會。Bedrock 與 Claude 都不儲存任何訊息,每次 API 呼叫完全獨立。想要有上下文,就要把完整對話歷史隨每次請求一起送出。
系統提示有什麼限制?
不能是空字串,至少要有一個字元;格式是含 text 鍵的字典清單;對話開始後就不能中途更換,要換請開新對話。