---
# System prepended metadata

title: 1110 Hands-on workshop 指南

---

1110 Hands-on workshop 指南
===
歡迎來到初入 Gen AI 與影像辨識：打造下一代 AI 應用工作坊 ~ 在進行操作之前，請確認以下事項是否已完成歐~
1. 註冊 AWS Educate 帳號: https://awseducate.tw/3
2. 下載工作坊用到的圖片們: https://drive.google.com/drive/folders/1mNpEL9GTSeD7CDd4mdeeHNFiudPEpP4Z?usp=sharing
3. 進入主控台首頁 (Console Home)
    - 實體參加者 -> 進入 event engine 主控台首頁 
    - 線上參加者 -> 進入 AWS console 主控台首頁 (Region: us-east-1)
![image.png](https://hackmd.io/_uploads/r1S88VHmT.png)

---

Hands-On 1: Textbook Translator
---
:::success 
### 效果展示
| 處理 | 成果 |
| -------- | -------- |
| 原圖 | ![HandsOn1_os.png](https://hackmd.io/_uploads/BJSyp_UXp.png) |
| 文字提取 | An operating system is software that manages a computer's hardware. It also provides a basis for application programs and acts as an intermediary between the computer user and the computer hardware. An amazing aspect of operating systems is how they vary in accomplishing these tasks in a wide variety of computing environments. Operating systems are everywhere, from cars and home appliances that include "Internet of Things" devices, to smart phones, personal computers, enterprise computers, and cloud computing envi- ronments.|
| 翻譯 | 作業系統是管理計算機硬件的軟件。它還為應用程序提供了基礎，並作為計算機用戶和計算機硬件之間的中介。作業系統的一個令人驚嘆的方面是它們在各種運算環境中完成這些任務方面的各種不同。從包括「物聯網」裝置的汽車和家用電器，到智能手機、個人電腦、企業電腦以及雲端運算環境，無處不在。  |


:::
### 將需要的檔案上傳至 AWS S3
> **AWS S3**
> 簡單雲端儲存服務，可以想像成雲端硬碟，可以在 bucket (儲存桶) 裡面放 objects (檔案)

| 示意圖 | 說明 |
| -------- | -------- |
| ![1.png](https://hackmd.io/_uploads/BkTB9VSm6.png) | 1. 搜尋 S3<br>2. 點擊 S3 圖標 |
| ![2.png](https://hackmd.io/_uploads/Byn1T4SXa.png) | Create bucket |
| ![3.png](https://hackmd.io/_uploads/rJijT4r7p.png) | 1. 填入**全世界獨一無二**的 bucket name<br>2. 選擇 **us-east-1** region<br>3. 滑到最底按 create bucket |
| ![4.png](https://hackmd.io/_uploads/rk_71HSXa.png) | 進入 bucket |
| ![5.png](https://hackmd.io/_uploads/HkXFkSrQa.png) | Upload files |
| ![6.png](https://hackmd.io/_uploads/SJW6VrSQ6.png) | 點擊 Add files，將先前下載的圖片全部上傳，滑到最底按 Upload |

### 進入 Lambda 打扣
> **AWS Lambda**
> 事件驅動無伺服器運算服務，可以想成是打 code 的地方
```
# HandsOn1: textbookTranslator

import json
import boto3

s3_client = boto3.client('s3')
tt_client = boto3.client('textract')
ts_client = boto3.client('translate')

def lambda_handler(event, context):
    
    # 需改為自己的 bucket_name 和 file_name
    bucket_name = "workshop-yuna-1110-tw"
    file_name = "HandsOn1_os.png"
    
    result = ""
    result_file_name = 'result.txt'
    
    # 要求 textract 偵測圖片中的文字
    tt_response = tt_client.detect_document_text(
        Document = { 
          'S3Object': {
                'Bucket': bucket_name,
                'Name': file_name
            }
      }
    )
    
    # 處理 textract 回傳的內容
    for item in tt_response['Blocks']:
        if item['BlockType'] == 'LINE':
            result += item['Text'] + ' '
    print('\n\n---文字偵測結果---\n' + result)
    
    # 要求 translate 翻譯文字
    ts_response = ts_client.translate_text(
        Text = result,
        SourceLanguageCode = 'en',
        TargetLanguageCode = 'zh-TW'
    )
    
    # 處理 Translate 回傳結果
    result += ts_response['TranslatedText']
    print('\n\n---文字翻譯結果---\n' + ts_response['TranslatedText'])
    
    # 將結果以文檔形式存入 s3
    s3_client.put_object(
        Body = result,
        Bucket = bucket_name,
        Key = result_file_name,
        ContentType=' text/plain;charset=utf-8'
    )
```

| 示意圖<div style="width: 320pt"> | 說明 |
| -------- | -------- |
| ![7.png](https://hackmd.io/_uploads/SkP8LSBmT.png) | 搜尋 Lambda 並點擊進入 |
| ![8.png](https://hackmd.io/_uploads/SygFH8SmT.png) | |
| ![9.png](https://hackmd.io/_uploads/rJ7NUUrQa.png) | 1. 取一個 function name<br>2. **選擇 python 3.11**<br>3. 滑到底按 create function |
| ![10.png](https://hackmd.io/_uploads/HJAeO8r76.png) | 1. 滑到下方 code 的地方<br>2. 把 code 複製貼上到 lambda_function<br>3. 把 bucket_name 改成自己的<br>4. 按 Deploy<br><br>**記得每次修改 code 都要按 Deploy!!** |
| ![11.png](https://hackmd.io/_uploads/r1uI7dIQT.png) | 1. 按 Deploy 旁邊的 Test 按鈕<br>2. 取個 Event name<br>3. Save |
| ![12.png](https://hackmd.io/_uploads/rJOhmd8mT.png)<br>![13.png](https://hackmd.io/_uploads/HySpX_Ump.png) | 按下 Test 後發現出錯，往右拉可以看到下方顯示的錯誤: "textbookTranslator is not authorized to perform: textract" <br><br>-> 代表存取 textract 時沒有獲得授權 |

### 取得授權
| 示意圖<div style="width: 320pt"> | 說明 |
| -------- | -------- |
|![14.png](https://hackmd.io/_uploads/HJvsU_LX6.png) | 1. 按 Configuration<br>2. 按 Permissions<br>3. 按 Role name 底下的連結進入 IAM |
| ![15.png](https://hackmd.io/_uploads/By7xtu876.png) | 在 IAM 中滑到底下的 Permission<br>1. Add permission<br>2. Attach policies |
| ![16.png](https://hackmd.io/_uploads/Sy4yYdU7p.png) | 把會用到的都授權一下<br>1. 搜尋 textract<br>2. 勾選 policy<br>3. 確定以下三個都勾到<br>**__1) AmazonS3FullAccess<br>__2) TranslateReadOnly<br>__3) AmazonTextractFullAccess**<br>4. Add permission |

### 回到 Lambda 重新測試，到 S3 看成果
| 示意圖<div style="width: 320pt"> | 說明 |
| -------- | -------- |
| ![17.png](https://hackmd.io/_uploads/BJIdodLQT.png) | 回到 Lambda 按 Test，成功啦~ |
| ![18.png](https://hackmd.io/_uploads/SJyG3_LQp.png) | 前往 S3，bucket 中也多出了 result.txt |
| ![19.png](https://hackmd.io/_uploads/ByWY3_8Qp.png) | 進入 result.txt，按 Open 就能看到成果 |

---
Hands-On 2: Where Is My Wife?
---
:::success 
### 效果展示
| 我婆 | 目標圖片 | 框出我婆 |
| -------- | -------- | -------- |
| ![HandsOn2_Sakura.jpg](https://hackmd.io/_uploads/Sk41r9UmT.jpg) | ![HandsOn2_Target_1.jpg](https://hackmd.io/_uploads/S10bBqL7a.jpg) | ![HandsOn2_Result_1.jpg](https://hackmd.io/_uploads/BJqXBqUma.jpg) |
:::

### 將需要的檔案上傳至 S3
剛剛跟 Hands-on 1 一起處理了，省略~~

### 進入 Lambda 打扣
```
# 實作 2. whereIsMyWife
import json
import boto3
from PIL import Image, ImageDraw
import PIL.Image
from io import BytesIO

s3_client = boto3.client('s3')
rk_client = boto3.client('rekognition')

def lambda_handler(event, context):
    
    # 需改為自己的 bucket_name
    bucket_name = "workshop-yuna-1110-tw"
    source_image = "HandsOn2_Sakura.jpg"
    
    for i in range(1, 7):
        
        target_image = "HandsOn2_Target_" + str(i) + ".jpg"
        result_image = "HandsOn2_Result_" + str(i) + ".jpg"
        
        # 要求 Rekognition 進行圖片比對
        rk_response = rk_client.compare_faces(
            TargetImage = {
                'S3Object': {
                    'Bucket': bucket_name,
                    'Name': target_image
                }
            },
            SourceImage = {
                'S3Object': {
                    'Bucket': bucket_name,
                    'Name': source_image
                }
            },
            SimilarityThreshold = 0
        )
        
        # 接下來要把 Rekognition 抓出來的 BoundingBox 畫到圖片上
        
        # 從 S3 把 Target 圖片抓來準備畫圖
        s3_response = s3_client.get_object(
            Bucket = bucket_name,
            Key = target_image
        )
        image_content = s3_response['Body'].read()
        image = Image.open(BytesIO(image_content))
        draw = ImageDraw.Draw(image)
        
        
        # 處理剛才 Rekognition 抓到的 BoundingBox
        # Rekognition 回傳的是 "左、上、寬、高" 相對於原本圖片的 "比例"
        # 畫圖需轉換為 "左上角、右下角" 的 "像素"
        position = []
        image_width, image_height = image.size
        for faceMatch in rk_response['FaceMatches']:
            if faceMatch['Similarity'] >= 90:
                box = faceMatch['Face']['BoundingBox']
                position = [
                    box['Left'] * image_width,
                    box['Top'] * image_height, 
                    (box['Left'] + box['Width']) * image_width,
                    (box['Top'] + box['Height']) * image_height
                ]
        
        # 畫出框框並存成圖片
        draw.rectangle(position, outline="red", width=2)
        modified_image = BytesIO()
        image.save(modified_image, format="JPEG")
        modified_image.seek(0)
        
        s3_client.put_object(Body=modified_image, Bucket=bucket_name, Key=result_image)
```
| 示意圖<div style="width: 320pt"> | 說明 | 
| -------- | -------- |
| ![2-1.png](https://hackmd.io/_uploads/rk5MQtUQT.png) | 回到 Lambda 創建新的 function |
| ![2-2.png](https://hackmd.io/_uploads/HyvpQYLQp.png) |
| ![2-3.png](https://hackmd.io/_uploads/ryOwVtUXa.png) | 1. 滑到底下<br>2. 把 code 複製貼上 **(記得修改 bucket name)** <br>3. Deploy<br>4. Test |
| ![2-4.png](https://hackmd.io/_uploads/H1oaEtLXT.png) | |
| ![2-5.png](https://hackmd.io/_uploads/r17EHY8Xp.png)<br>![2-6.png](https://hackmd.io/_uploads/ByRQUY876.png) | 按 Test 發現出錯:<br>"Unable to import module 'lambda_function': No module named 'PIL'"<br><br>引入函式庫失敗 |

### 引入函式庫的方法 -> Lamda Layer

| 示意圖<div style="width: 320pt"> | 說明 | 
| -------- | -------- |
|![2-7.png](https://hackmd.io/_uploads/HyxpItL7a.png) | 滑到上面去點 Layers (其實往下滑也可以啦) |
| ![2-8.png](https://hackmd.io/_uploads/rJEXvK8mT.png) | 按 Add a layer |
| ![2-9.png](https://hackmd.io/_uploads/rJvuKtL7p.png) | 1. 選 Specify an ARN<br>2. 貼上 **arn:aws:lambda:us-east-1:770693421928:layer:Klayers-p311-Pillow:2** (參考下方黃色框框資訊)<br>3. Verify<br>4. Add|
| ![2-10.png](https://hackmd.io/_uploads/S1gE9tU7T.png) | 按一下 Test，換出別的錯啦~ 熟悉的 AccessDeniedException，又是存取權限問題~ |
:::warning
引用函式庫需要的 ARN 請參考: [這裡 (記得選符合的 Runtime 版本和 Region)](https://github.com/keithrozario/Klayers)
:::

### 取得授權
| 示意圖<div style="width: 320pt"> | 說明 | 
| -------- | -------- |
| ![2-11.png](https://hackmd.io/_uploads/ByBysKImp.png) |  |
| ![2-12.png](https://hackmd.io/_uploads/H1CNiKLQ6.png) |  |
| ![2-13.png](https://hackmd.io/_uploads/Hkpr3F8X6.png) | 把會用到的都授權一下<br>1. 搜尋 Rekognition<br>2. 勾選 policy<br>3. 確定以下兩個都勾到<br>**__1) AmazonS3FullAccess<br>__2) AmazonRekognitionReadOnly**<br>4. Add permission |
| ![2-14.png](https://hackmd.io/_uploads/Bk756tU7a.png) | 回到 Lambda 按 Test，又換出別的錯啦~<br>-> 程式跑超過三秒被 Lambda 擋掉了~  |

### 修改 Timeout
| 示意圖<div style="width: 320pt"> | 說明 | 
| -------- | -------- |
| ![2-15.png](https://hackmd.io/_uploads/SyywRKIXp.png) | 1. 選擇 Configuration<br>2. General configuration<br>3. Edit |
| ![2-16.png](https://hackmd.io/_uploads/rkfJEawXT.png) | Timeout 改成 15 秒，滑到底下 Save |
| ![2-17.png](https://hackmd.io/_uploads/B1MAb9L7a.png) | Test 測試成功 |
| ![2-18.png](https://hackmd.io/_uploads/S1c7f5UXT.png) | 回到 S3 bucket 中，成功多出了六個 HandsOn2_Result 的圖片檔 |
| ![HandsOn2_Result_6.jpg](https://hackmd.io/_uploads/SkIKV5L7p.jpg) | 下載下來就能看見我婆成功被框出來啦~ |

# Bedrock 服務介紹
## 簡介
在接下來的段落，我們將為您著重介紹 Bedrcok，並展示一個「文檔生圖 API」，但由於 Bedrock 屬於比較新的服務 (2023/04 GA)，且現在也沒有 Free tier，因此在使用上務必要詳加了解該服務是如何計費的

> 因為 Bedrock 是比較新的服務，要使用 Bedrock 建議 Region 選擇 us-east-1 (N. Virginia)，享受最新的功能！

## Bedrock 是什麼?
![aws-bedrock](https://github.com/sh1un/bedrock-workshop/assets/85695943/7443c1af-6f44-4edc-8b94-7366e1b4a361)

### Amazon Bedrock 是一個全受管的服務，旨在簡化生成式人工智能（AI）應用程式的建立和擴充過程。以下是 Bedrock 的主要特點：

- 領先的基礎模型選項：Amazon Bedrock 提供多種高效能的基礎模型（FM），來自 AI21 Labs、Anthropic、Cohere、Meta、Stability AI 和 Amazon 等領先 AI 公司。這些模型可以透過單一 API 進行推論，並在最少的程式碼變更下獲得最新模型版本​​。

- 使用者數據自訂模型：使用者可以透過視覺化界面，利用自己的數據私有自訂這些模型。這涉及選取儲存在 Amazon S3 中的訓練和驗證數據集，並調整超參數以最佳化模型效能​​。
    > 注意！截至 2023/11/20 資訊，目前只有 Titan 模型可以 Fine Tuning

- 全受管代理程式：Bedrock 使開發者能夠創建可執行複雜業務任務的代理程式，例如預訂差旅、處理保險索賠、建立廣告宣傳活動等。這些代理程式透過動態呼叫公司系統和 API 來擴展 FM 的推理功能​​。

- 原生支援 RAG：Bedrock 支援擷取擴增產生（RAG）技術，允許將 FM 連接到資料來源，以擴展其功能，從而使模型更深入了解特定的領域和組織​​。
    > 可以想像成一位廚師在準備一道特別的菜餚。這位廚師（代表基礎模型）擁有廣泛的烹飪知識和技巧，但當他需要準備一道特定國家的特色菜時，他會參考那個國家的食譜（這裡的食譜代表連接到的數據源）。通過查閱這些特定的食譜，廚師不僅能夠利用他原本的廣泛烹飪知識，還能加入特定文化的獨特風味和技巧，從而創造出更符合該文化特色的菜餚。這就像是 Bedrock 利用 RAG 技術將基礎模型與特定的數據源相連接，使得模型能夠更深入地理解和應對特定領域或組織的需求。

- 資料安全與合規認證：Bedrock 提供多種功能以支援安全和隱私要求，並達到 HIPAA 資格和 GDPR 合規性。所有數據在傳輸和靜態期間均被加密，並且不會與第三方模型供應商共享​​。

- 簡化開發流程：Bedrock 是無伺服器的，因此開發者不需要管理任何基礎設施。它還可以使用熟悉的 AWS 服務，安全地整合並部署生成式 AI 功能到應用程式中​​。
    > 重要！！後續的我將要展示的應用是完全 Serverless(無伺服器)，所有應用都在 AWS 雲上打造好，透過這個優勢，我省去了很多配置底層基礎建設的煩惱，要構建出一個能運作得應用真的相當快速

總之，Amazon Bedrock 提供了一個全面的解決方案，以簡化生成式 AI 應用程式的開發，同時確保資料的安全和合規性。

### Use cases
- 虛擬助理
- 智能客服
- 文字歸納與摘要
- 搜索
- 圖片生成
- 真的非常非常多種應用…



## 相關時事 - 2023 Summit Taiwan([連結](https://www.inside.com.tw/article/32357-AWSSummit2023_GenAIMusic))

![image](https://github.com/sh1un/bedrock-workshop/assets/85695943/8711ceec-6719-4231-b589-2bb9ebc237e7)

> Amazon Bedrock 提供的資源可用於多種應用，包括創作社交媒體貼文、網頁副本、開發聊天機器人和虛擬助理，以及在大型資料集中進行搜索和問題解答。




## 畫面
![BedrockScreeshot-1](https://github.com/sh1un/bedrock-workshop/assets/85695943/8625ff25-66e6-4701-b690-5c6e2d05f4d5)


## Model Providers
目前總共有 6 間公司提供基礎模型(FM)，但本工作坊在後面的應用只有用到 Claude, Stable Diffusion，因此只會著重介紹此兩個 FMs 
| 公司名稱     | AI 模型名稱      |
|------------|----------------|
| AI21 Labs  | Jurassic-2 series |
| Anthropic  | Claude         |
| Cohere     | Command        |
| Meta       | Llama 2        |
| Stability AI | Stable Diffusion |
| Amazon     | Titan          |


## Anthropic 公司介紹 
![apple-icon](https://github.com/sh1un/bedrock-workshop/assets/85695943/d27513ee-c8b1-4817-a8f6-15d3be1cd0af)

- Anthropic是一家總部位於美國的AI研發公司，於2021年1月創立。
- 創辦人是前 OpenAI 員工
- 主要產品就是「聊天機器人 Claude」([Claude 連結](https://claude.ai/login?returnTo=%2F))
- Claude 是目前公認 ChatGPT 的最大競爭對手


## Stability AI 公司介紹
![stabilityAI](https://github.com/sh1un/bedrock-workshop/assets/85695943/5964aa1e-87b6-4803-9b9c-b1d50560ef5a)

- Stability 是一家專注於 AI 研發公司，於2021年創立。
- 主要產品就是「Stable Diffusion」([Stable Diffusion 連結](https://stablediffusionweb.com/))
- 近期推出了 AI 音樂生成工具「Stable Audio」([連結](https://www.stableaudio.com/))
    > 大家可以去玩看看 Stable Audio! 現在 AWS 上還沒有 Stable Audio 的 FM，筆者期待未來有機會能在 AWS Bedrock 上使用到 Stable Audio!


## Bedrock vs. Claude (or Others)
這邊主要是想比較，我今天身為一名開發者，在 AWS 上透過 Bedrock 使用 Claude 與直接從 Claude 獲取 API 之間的差異。
先講結論：**一般的獨立開發者我建議您直接去看看其他供應商是否有提供 API！然後使用該供應商提供的 API 即可**
| 特點             | Bedrock                                        | Claude (or Others)                    |
|----------------|------------------------------------------------|--------------------------------------|
| 目標用戶群        | 企業級用戶、開發者                                 | 一般消費級個人用戶                          |
| 平台性質         | 完整的 AI 開發和運行平台                               | 側重於娛樂、交流、資訊獲取的聊天機器人           |
| 服務整合         | 整合 AWS 各項服務，提供豐富的客製化彈性                     | 提供基本功能，缺乏進階客製化選項                    |
| 主要應用         | 適用於專業開發和商業應用                             | 主要用於個人用途，如娛樂和資訊交流                 |

## Pricing
### What is token?
![ClaudeV2MaxToken](https://github.com/sh1un/bedrock-workshop/assets/85695943/c658de1e-a3b7-4cff-99ec-4edaf9bfe87d)

**用來處理和理解自然語言的基本單位。** 
也就是說輸入的文字會先被轉換為 tokens 再進行分析，讓系統更好地理解並回應輸入
每個字耗費的平均 token數
    - 繁體中文 2.03	
    - 英文 1.25
 > 推薦大家可以去 OpenAI tokenizer([連結](https://platform.openai.com/tokenizer)) 感覺一下

> Claude V2 Max 100k tokens 差不多就是 40,000 ~ 60,000 個繁體中文字

## Demo
### 文檔生圖
本工作坊所展示的應用，會將一個 pdf 檔上傳，透過 Textract 解析文字作為 promt 傳送給 Claude，Claude 會歸納重點產生合適的 prompt，再將 Claude 產生的 prompt 傳給 Stable Diffusion 產生出圖片

![BedrockDemo3](https://github.com/sh1un/bedrock-workshop/assets/85695943/075ae312-1f86-4f14-959f-50007b02a43f)


## Tools
![image](https://github.com/sh1un/bedrock-workshop/assets/85695943/83d0072c-58fd-464e-8d67-a1eabb701538)

## Architechture
![image](https://github.com/sh1un/bedrock-workshop/assets/85695943/6b7d710a-ed7f-4e07-82be-28f62fd3ca5f)

> 本工作坊為了簡化教學，在架構方面才把所有業務邏輯集中在單一 Lambda Function，建議可以將其各功能獨立在不同的 Lambda Function 或是將共用邏輯拆出來放在 Lambda Layer 內會更好喔

## 其他資源
AWS Partyrock: https://partyrock.aws/


















