--- title: 1207 對話機器人(4/5) tags: GCP, 筆記 --- https://annieshing.pixnet.net/blog/post/460198511 AI:高運算力 資料 私有機房 共享機房 ->雲服務 驗證可行 colab 環境快速重來過 :套件可追朔 要用就瞬間開起來 不要用就瞬間關掉 資源不浪費 GCP 3個月300美金 AI跟雲服務有很大的相關性 雲原生 雲服務體驗流程 --- ## gcp的三大核心服務: ### 資料儲存:cloud storage 無限資料 (儲存) ### 資料運算:compute engine (操作) ### 權限應用: IAM (權限) --- ## 實作: ![](https://i.imgur.com/J7rks5A.jpg) ### 1 .搜尋GCP ![](https://i.imgur.com/q5glKN0.png) ### 2. 頁面右上方點選『控制台』後會進入到下列畫面⬇︎ ![](https://i.imgur.com/Rfusdgc.jpg) ### ->按下紅框區域,創建新的專案 ![](https://i.imgur.com/e4qHUC1.png) ### 3. 專案取名,記得是無機構->建立 ![](https://i.imgur.com/V8dH0nx.png) ### 若要更換語言:右上方『偏好設定』裡設定成英文 ### 建立完成後,點選上方如圖->點選剛創好的專案 ![](https://i.imgur.com/gUiMvFy.png) ### 點選左欄位的->Storage->Browser ![](https://i.imgur.com/1lT0uRG.png) ### 創建Bucket才能裝所需服務 ![](https://i.imgur.com/9UIYouF.png) ### 命名Bucket->continue ![](https://i.imgur.com/ENnUNq0.png) ### 決定資料儲存地區:通常選Region->asia-east-taiwan存台灣比較便宜->continue ![](https://i.imgur.com/uk5yvBS.png) ### 越常存取選上方 不常存取選下方 這邊先選Standard ![](https://i.imgur.com/owUaeWO.png) ### 資料權限:有兩種 精細跟統一 這邊示範統一:權限統一收管 ![](https://i.imgur.com/TNgIbQ4.png) ### 加密->create ![](https://i.imgur.com/KQMjAkP.png) ### 成功創建Bucket->上傳檔案 upload files ![](https://i.imgur.com/i101vww.png) ### 操作GCP可用內部的編輯器 跟外部程式來操作 這邊示範內建的:按右上方開啟 cloud shell ![](https://i.imgur.com/JTpNfxU.png) ### 開啟後按下open editor 之後往上拉 ![](https://i.imgur.com/BXmkEZW.png) ### 建立一個py檔 用此來操作查看gcp內的檔案 ![](https://i.imgur.com/2O3PcNS.png) ![](https://i.imgur.com/BoHntnl.png) ### 使用程式碼查看list objects 輸入以下程式碼->可從下方網站找到程式碼->更改bucket name(專案名稱) #### 1. 進入網站 選python 複製下方程式碼至cloud shell * [Listing objects  |  Cloud Storage  |  Google Cloud](https://cloud.google.com/storage/docs/listing-objects#code-samples) #### 2. 如圖示 ![](https://i.imgur.com/c7SwTrw.png) #### 3. 複製到cloud shell 縮排 更改bucket name(跟專案名稱) In GCP 內的範例程式碼 ``` # 我要用python 去瀏覽桶子內有什麼檔案 # python cloud storage list all object in bucket from google.cloud import storage """Lists all the blobs in the bucket.""" bucket_name = "自己的bucket名稱id:ai-cxcxc-demo" storage_client = storage.Client() # Note: Client.list_blobs requires at least package version 1.17.0. blobs = storage_client.list_blobs(bucket_name) for blob in blobs: print(blob.name) ``` ![](https://i.imgur.com/DgJEdiJ.png) ### 開啟terminal ![](https://i.imgur.com/QZxdGMd.png) ![](https://i.imgur.com/vws8rxk.png) ### 輸入下方指令:把shell加進服務內(名稱是專案名的ID) ![](https://i.imgur.com/pAS1J3k.png) p.s可以查看ID 名字小寫 不重複 ![](https://i.imgur.com/3MjIeuS.png) ### 授權 ![](https://i.imgur.com/p3Goo2i.png) ### 程式碼在專案中才可以執行(有黃色專案名稱表示有加進去 ->這邊是示範專案內操作使用 ![](https://i.imgur.com/wCNKTQW.png) ### IAM權限使用: #### 選擇IAM->Service Accounts->+create service account ![](https://i.imgur.com/m8FDU5A.png) ![](https://i.imgur.com/uhUkeLa.png) ### 創service account ![](https://i.imgur.com/khVi6yR.png) ### 給出有cloud storage的管理之權 > 權限管理可以有很細部的討論,同學在專題後可以再花時間研究 > 這邊先示範選cloud storage->storage admin ### p.s storage admin是最高權限 通常不會給到這麼大 這邊是示範 ![](https://i.imgur.com/I8zuan5.png) ![](https://i.imgur.com/CYP6SpL.png) ### 未來其他使用者要操作時 可加入 課堂先不示範 ![](https://i.imgur.com/zPmMeNK.png) ### 有了service accunt還要有key才能調度資料:新增key #### 點剛剛創的名稱 ![](https://i.imgur.com/CdV8Tie.png) ### 點選create new key ![](https://i.imgur.com/8523Ipy.png) ### 按create ![](https://i.imgur.com/OoI6ECw.png) ### key會存成一個json檔->改名成service_account(之後好操作) ![](https://i.imgur.com/eGesMje.png) ![](https://i.imgur.com/lDzGsp5.png) ### 使用外部程式操作:colab 要給json檔 +輸入》程式碼 才能從外部操作GCP 程式碼可參考共筆:* [004-2020-1207-第四天 - Google 文件](https://docs.google.com/document/d/1F7hN_VAtn-VzZeO5l1wyhhMX6ebvimyFAXVwBYcRoTw/edit)找到第二段有加上from_service_account_json('service_account.json')這段⬇︎ ``` # 我要用python 去瀏覽桶子內有什麼檔案 # python cloud storage list all object in bucket from google.cloud import storage """Lists all the blobs in the bucket.""" bucket_name = "ai-cxcxc-demo" storage_client = storage.Client.from_service_account_json('service_account.json') # Note: Client.list_blobs requires at least package version 1.17.0. blobs = storage_client.list_blobs(bucket_name) for blob in blobs: print(blob.name) --- ``` ### colab 執行:查看cloud storage內的檔案 1. 程式碼 2. 上傳service_account.json至colab 3. 執行後可以查看cloud storage內的檔案 換句話說 在外部也可使用程式的操作來使用GCP ![](https://i.imgur.com/Rhmrgpp.png) ------ ![](https://i.imgur.com/TbwrS7u.jpg) 已媒人為例,跟遠端服務溝通,都有隔壁大媽(客戶端)來溝通 要跟外部做互動 找程式碼先找客戶端 ## 017 檔案操作示範 ## 跟cloud storage作互動 * 先建個客戶端 * 用客戶端去: 上傳物件 瀏覽物件 下載物件 刪除物件 https://github.com/BingHongLi/ai-chatbot-tutorial/blob/main/017_%E8%8D%8A%E7%84%A1%E5%91%BD%E7%9A%84%E5%B7%A6%E6%89%8B%E5%8A%8D.ipynb ## 1. 建立客戶端 (必須要上傳service_account.json檔) ``` # step1 建立客戶端 # gcp cloud storage client python example # 017就有了啦(以下複製017) from google.cloud import storage # 創建客戶端,由於在專案外,必須給一個service_account.json檔 storage_client = storage.Client.from_service_account_json('service_account.json') ``` ![](https://i.imgur.com/pYd1Mdr.png) ## 2.用客戶端去上傳物件:圖中圈出來的要更改 ``` # 用cloud storage的客戶端上傳物件 # python cloud storage upload object example # 017就有了啦 # 上傳到指定的桶子內 # https://cloud.google.com/storage/docs/uploading-objects#storage-upload-object-code-sample bucket_name='要改成自己的 如:ai-cxcxc-demo' source_file_name= '要上傳檔案的名字13080001127357.jpg' # object的名子 destination_blob_name= '上傳雲端要叫檔案名為:123/456.jpg' # 指定桶子 bucket = storage_client.bucket(bucket_name) # 指定本地檔案 blob = bucket.blob(destination_blob_name) # 指定遠端位置 blob.upload_from_filename(source_file_name) print( "File {} uploaded to {}.".format( source_file_name, destination_blob_name ) ) ``` ![](https://i.imgur.com/WCZnc2Q.png) ## 3 瀏覽物件: 執行完成後,至GCP確認檔案是否有成功上傳 ### Storage->Browser ![](https://i.imgur.com/pORrT3D.png) ### 點選123資料夾 ![](https://i.imgur.com/OS9TRFC.png) ### 資料有成功上傳 ![](https://i.imgur.com/U6XIlqJ.png) ## 4. 下載物件:先設定權限公開 才可以下載 ``` 精細:每個檔案有一個權限 統一:檔案都統一權限 雲端資料預設都是不公開 ``` ### 選擇premission來調整權限 ![](https://i.imgur.com/srzrGFL.png) ### 下方黃色區域表示在專案中擁有權限的人->按下ADD ![](https://i.imgur.com/bZKZXAI.png) ### 讓所有人都可以看到物件:選擇AllUsers->選擇Cloud Storage->Storage object viewer ![](https://i.imgur.com/W5J8SA8.png) AllUsers 只能看 不能設定有操作權限 ![](https://i.imgur.com/iNgB0ZZ.png) ### 確認:此動作後資料會公開 ![](https://i.imgur.com/EPIjwSQ.png) ### 完成後,會顯示資料是公開狀態(因前面是設定統一,所以設定後所有檔案都會是公開) ![](https://i.imgur.com/28pTNju.png) ![](https://i.imgur.com/MGK0jCV.png) ### 這邊選擇任一檔案進入後,就能獲得public url,進入頁面後就可以下載資料了 ![](https://i.imgur.com/TD1mr2p.png) ``` 物件的權限調整 調整公開之後,物件都會有一個https連結 https://storage.googleapis.com/ai-cxcxc-demo/123/456.jpg 得到的url規律: https://storage.googleapis.com/ + bucket_name + object_name ``` ## 5 刪除物件: 新增程式碼:更改bucket_name和要刪除的檔案名稱 ![](https://i.imgur.com/HhTi1NU.png) ``` # 刪除桶子內的物件 # https://cloud.google.com/storage/docs/deleting-objects bucket_name = "這邊要改your-bucket-name" blob_name = "這邊要改your-object-name" bucket = storage_client.bucket(bucket_name) blob = bucket.blob(blob_name) blob.delete() print("Blob {} deleted.".format(blob_name)) ``` ---- ## 示範LineChatBot 與GCP結合 <!-- google 估得好 工程師當到老 --> :::info #### 用戶上傳照片到我方的機器人裡面,機器人將照片傳入cloud storge 內,並依照用戶id做資料夾 程式碼pattern: * 安裝套件 * 引用套件 * 應用伺服器準備 * 消息素材準備 * 應用方法設計 * 伺服器起啟動 ::: ### 1.安裝套件 ``` !pip install line-bot-sdk flask flask-ngrok ``` ![](https://i.imgur.com/RHvMwcF.png) --- ### 2.引用套件 ``` ''' 引用套件 ''' # 引用Web Server套件 from flask import Flask, request, abort, jsonify # 載入json處理套件 import json # 外部連結自動生成套件 from flask_ngrok import run_with_ngrok # 從linebot 套件包裡引用 LineBotApi 與 WebhookHandler 類別 from linebot import ( LineBotApi, WebhookHandler ) # 引用無效簽章錯誤 from linebot.exceptions import ( InvalidSignatureError ) ``` ---- ![](https://i.imgur.com/51GsGpD.png) ---- ### 3.應用伺服器準備:app, handler,line-bot-api,storage-client 登入line api 更改CHANNEL_SECRET/CHANNEL_ACCESS_TOKEN * [Messaging API 介紹 | LINE Developers](https://developers.line.biz/zh-hant/docs/messaging-api/overview/) ``` ''' 建置主程序 建置handler與 line_bot_api ''' # 設定Server啟用細節 app = Flask(__name__,static_url_path = "/material" , static_folder = "./material/") run_with_ngrok(app) # 生成實體物件 line_bot_api = LineBotApi("要改CHANNEL_ACCESS_TOKEN“) handler = WebhookHandler("要改CHANNEL_SECRET") from google.cloud import storage # 本地端才如此作為,最好改用環境變數 storage_client = storage.Client.from_service_account_json('service_account.json') ``` ![](https://i.imgur.com/BZHJyX1.png) --- ### 4.主程序的入口:讓line把消息傳過來,並依照我們設定處理 ``` ''' 建置主程序的API入口 接受Line傳過來的消息 並取出消息內容 將消息內容存在google drive的檔案內 並請handler 進行消息驗證與轉發 ''' # 啟動server對外接口,使Line能丟消息進來 @app.route("/", methods=['POST']) def callback(): # get X-Line-Signature header value signature = request.headers['X-Line-Signature'] # get request body as text body = request.get_data(as_text=True) print(body) # 記錄用戶log,請去查更正確的logging作法 f = open("./ai-event.log", "a") f.write(body) f.close() # handle webhook body try: handler.handle(body, signature) except InvalidSignatureError: abort(400) return 'OK' ``` ![](https://i.imgur.com/UqIj1PF.png) ---- ### 5.業務方法處理:收到圖片消息的時候,把圖片抓回來,再上傳到cloud storage內(bucket_name要改GCP要存的專案id名稱) ``` ''' 若收到圖片消息時, 先回覆用戶文字消息,並從Line上將照片拿回。 ''' from linebot.models import( MessageEvent,ImageMessage, TextSendMessage ) # 吿知handler 收到消息事件時 且為圖片消息 做下面的方法 @handler.add(MessageEvent, message=ImageMessage) def handle_message(event): #回覆用戶 line_bot_api.reply_message( event.reply_token, TextSendMessage(text='Image has Upload'+ ' ' + event.message.id)) #請line_bot-api把圖片抓回來 message_content = line_bot_api.get_message_content(event.message.id) with open(event.message.id+'.jpg', 'wb') as fd: for chunk in message_content.iter_content(): fd.write(chunk) #指定上傳位置 bucket_name='your_gcp_bucket_name' source_file_name= event.message.id+'.jpg' destination_blob_name= event.source.user_id +'/'+ event.message.id+'.jpg' bucket = storage_client.bucket(bucket_name) blob = bucket.blob(destination_blob_name) blob.upload_from_filename(source_file_name) ``` ![](https://i.imgur.com/HbyKbas.png) ### 6.伺服器啟動(將更新網址回傳到Line Webhook URL使用) ![](https://i.imgur.com/NJCdYAp.png) ### 7.執行後,用戶從line機器人上傳照片會出現在左邊以及在Cloud Storage內會自動依照用戶id存成資料夾。 ![](https://i.imgur.com/phc8gNQ.png) ----- ## 解析google Text-to-Speech使用,若要直接應用在Line Chatbot可看老師019程式碼 ### 1.先到GCP搜尋->按下啟用 ![](https://i.imgur.com/xJV87NA.png) ![](https://i.imgur.com/n043alP.png) ### 2. 調度ai的範例 (參考老師019範例或共筆4內程式碼) 將下方程式碼複製至colab ``` # 安裝之後,點擊重新執行階段 !pip install google-cloud-texttospeech from google.cloud import texttospeech # Instantiates a client client = texttospeech.TextToSpeechClient.from_service_account_json('service_account.json') # Set the text input to be synthesized synthesis_input = texttospeech.SynthesisInput(text="班代,每次都拍你,你是不是很開心?") # Build the voice request, select the language code ("en-US") and the ssml # voice gender ("neutral") voice = texttospeech.VoiceSelectionParams( language_code='zh-TW', ssml_gender=texttospeech.SsmlVoiceGender.NEUTRAL) # Select the type of audio file you want returned audio_config = texttospeech.AudioConfig( audio_encoding=texttospeech.AudioEncoding.LINEAR16) # Perform the text-to-speech request on the text input with the selected # voice parameters and audio file type response = client.synthesize_speech(input=synthesis_input, voice=voice, audio_config=audio_config) # The response's audio_content is binary. with open('output.wav', 'wb') as out: # Write the response to the output file. out.write(response.audio_content) print('Audio content written to file "output.wav"') ``` ### 重新啟動並執行 ![](https://i.imgur.com/BNXZDbT.png) ![](https://i.imgur.com/aGmU0VG.png) ### 按下圖中按鈕 ![](https://i.imgur.com/awQmQWs.png) ## 執行成功後 檔案內會出現剛剛文字輸入的音檔 ![](https://i.imgur.com/Ity1sjX.png) ----- ## 更換聲音:從SsmlVoiceGender查看原始碼 ![](https://i.imgur.com/W1RRio3.png) 若要女聲,將程式碼從 ``` ssml_gender=texttospeech.SsmlVoiceGender.NEUTRAL) 更改成 ``` ``` ssml_gender=texttospeech.SsmlVoiceGender.FEMALE) ``` ![](https://i.imgur.com/yiHAhRf.png) ----- ## 將AI導入Line Chatbot:google Text-to-Speech:使用019實際操作,將需要改的名稱填上,就能使用了! * [ai-chatbot-tutorial/019_GCP與Chatbot_2.ipynb at main · BingHongLi/ai-chatbot-tutorial](https://github.com/BingHongLi/ai-chatbot-tutorial/blob/main/019_GCP%E8%88%87Chatbot_2.ipynb) ``` !pip install line-bot-sdk flask flask-ngrok # 安裝後必須點擊Runtime -> Restart Runtime !pip install google-cloud-texttospeech ``` ``` ''' 引用套件 ''' # 引用Web Server套件 from flask import Flask, request, abort, jsonify # 載入json處理套件 import json # 外部連結自動生成套件 from flask_ngrok import run_with_ngrok # 從linebot 套件包裡引用 LineBotApi 與 WebhookHandler 類別 from linebot import ( LineBotApi, WebhookHandler ) # 引用無效簽章錯誤 from linebot.exceptions import ( InvalidSignatureError ) ``` ``` ''' 建置主程序 建置handler與 line_bot_api ''' # 設定Server啟用細節 app = Flask(__name__,static_url_path = "/material" , static_folder = "./material/") run_with_ngrok(app) # 生成實體物件 line_bot_api = LineBotApi("CHANNEL_ACCESS_TOKEN") handler = WebhookHandler("CHANNEL_SECRET") from google.cloud import storage from google.cloud import texttospeech # 本地端才如此作為,最好改用環境變數 storage_client = storage.Client.from_service_account_json('service_account.json') bucket_name='GCP Cloud Storage Bucket name' # Instantiates a client speech_client = texttospeech.TextToSpeechClient.from_service_account_json('service_account.json') ``` ``` ''' 建置主程序的API入口 接受Line傳過來的消息 並取出消息內容 將消息內容存在google drive的檔案內 並請handler 進行消息驗證與轉發 ''' # 啟動server對外接口,使Line能丟消息進來 @app.route("/", methods=['POST']) def callback(): # get X-Line-Signature header value signature = request.headers['X-Line-Signature'] # get request body as text body = request.get_data(as_text=True) print(body) # 記錄用戶log,請去查更正確的logging作法 f = open("./ai-event.log", "a") f.write(body) f.close() # handle webhook body try: handler.handle(body, signature) except InvalidSignatureError: abort(400) return 'OK' ``` ``` ''' 若收到圖片消息時, 先回覆用戶文字消息,並從Line上將照片拿回。 ''' from linebot.models import( MessageEvent,ImageMessage, TextSendMessage ) @handler.add(MessageEvent, message=ImageMessage) def handle_message(event): line_bot_api.reply_message( event.reply_token, TextSendMessage(text='Image has Upload'+ ' ' + event.message.id)) message_content = line_bot_api.get_message_content(event.message.id) with open(event.message.id+'.jpg', 'wb') as fd: for chunk in message_content.iter_content(): fd.write(chunk) source_file_name= event.message.id+'.jpg' destination_blob_name= event.source.user_id +'/'+ event.message.id+'.jpg' bucket = storage_client.bucket(bucket_name) blob = bucket.blob(destination_blob_name) blob.upload_from_filename(source_file_name) ``` ``` ''' 若收到文字消息時 將文字傳給GCP,轉譯成音訊後 放到cloud storage,並組合成AudioSendMessage,傳回給用戶 Podcast ''' from linebot.models import( MessageEvent,TextMessage, AudioSendMessage ) @handler.add(MessageEvent, message=TextMessage) def handle_text_message(event): # Set the text input to be synthesized synthesis_input = texttospeech.SynthesisInput(text=event.message.text) # Build the voice request, select the language code ("en-US") and the ssml # voice gender ("neutral") voice = texttospeech.VoiceSelectionParams( language_code="zh-TW", ssml_gender=texttospeech.SsmlVoiceGender.NEUTRAL ) # Select the type of audio file you want returned audio_config = texttospeech.AudioConfig( audio_encoding=texttospeech.AudioEncoding.MP3 ) # Perform the text-to-speech request on the text input with the selected # voice parameters and audio file type response = speech_client.synthesize_speech( input=synthesis_input, voice=voice, audio_config=audio_config ) # The response's audio_content is binary. voice_mp3_file_path=event.message.id+".mp3" with open(voice_mp3_file_path, "wb") as out: # Write the response to the output file. out.write(response.audio_content) print('Audio content written to file '+voice_mp3_file_path) # 上傳檔案 destination_blob_name= event.source.user_id +'/'+ event.message.id+'.mp3' bucket = storage_client.bucket(bucket_name) blob = bucket.blob(destination_blob_name) blob.upload_from_filename(voice_mp3_file_path) # 回話 line_bot_api.reply_message( event.reply_token, AudioSendMessage( original_content_url ="https://storage.googleapis.com/"+bucket_name+'/'+destination_blob_name, duration=60000 ) ) ``` ``` # 主程序運行 app.run() ``` Google ML 參考 https://colab.research.google.com/github/robeartoe/APIWorkshop/blob/master/MLWorkshop.ipynb#scrollTo=Snq8ehAu7JkD ----- ## 用Json檔轉成消息給用戶 ``` !pip install line-bot-sdk flask flask-ngrok ``` ``` ''' 引用套件 ''' # 引用Web Server套件 from flask import Flask, request, abort, jsonify # 載入json處理套件 import json # 外部連結自動生成套件 from flask_ngrok import run_with_ngrok # 從linebot 套件包裡引用 LineBotApi 與 WebhookHandler 類別 from linebot import ( LineBotApi, WebhookHandler ) # 引用無效簽章錯誤 from linebot.exceptions import ( InvalidSignatureError ) ``` ``` '' 建置主程序 建置handler與 line_bot_api ''' # 設定Server啟用細節 app = Flask(__name__,static_url_path = "/material" , static_folder = "./material/") run_with_ngrok(app) # 生成實體物件 line_bot_api = LineBotApi("CHANNEL_ACCESS_TOKEN") handler = WebhookHandler("CHANNEL_SECRET") ``` ``` ''' 建置主程序的API入口 接受Line傳過來的消息 並取出消息內容 將消息內容存在google drive的檔案內 並請handler 進行消息驗證與轉發 ''' # 啟動server對外接口,使Line能丟消息進來 @app.route("/", methods=['POST']) def callback(): # get X-Line-Signature header value signature = request.headers['X-Line-Signature'] # get request body as text body = request.get_data(as_text=True) print(body) # 記錄用戶log,請去查更正確的logging作法 f = open("./ai-event.log", "a") f.write(body) f.close() # handle webhook body try: handler.handle(body, signature) except InvalidSignatureError: abort(400) return 'OK' ``` ``` ''' line bot designer 的json字串檔 我們能不能判斷 json的type欄位 ''' demo_message_json_string=''' { "type":"location", "title":"test", "address":"test", "latitude":35.65910807942215, "longitude":139.70372892916203 } ''' ``` ``` import json demo_message_json=json.loads(demo_message_json_string) ``` ``` ''' 判斷Json檔的type格式 如果為text 那就用TextSendMessage 回應 如果為location 那就用LocationSendMessage回應 ''' from linebot. models import (ImageSendMessage, TextSendMessage, LocationSendMessage) from linebot.models import (TextSendMessage,LocationSendMessage) if demo_message_json.get('type')=='text': reply_text_send_message=TextSendMessage.new_from_json_dict(demon_message_json) elif demo_message_json.get('type')=='location': reply_send_message=LocationSendMessage.new_from_json_dict(demon_message_json) elif demo_message_json.get('type')=='image': reply_send_message= ImageSendMessage.new_from_json_dict(demon_message_json) ``` ``` from linebot.models import (MessageEvent, TextMessage) @handler.add(MessageEvent, message=TextMessage) def handle_text_message(event): line_bot_api.reply_message( event.reply_token, text_send_message ) ``` ``` app.run() ``` line bot designer 的json字串檔 上方程式碼執行後,當用戶端傳訊息給機器人後,下方會出現json檔 把這些程式碼丟到Json Formatter可以方便看出格式 * [JSON Formatter & Validator](https://jsonformatter.curiousconcept.com/#) * ![](https://i.imgur.com/IquQCRj.png) ![](https://i.imgur.com/y8NAjpH.png) ------ ### 小補充 * 創立專案: 名稱 跟ID通常一樣 除非有特別改 project 任何服務都不能執行!(空盤子)!換成無機構 不要用學校的 * 公司一個項目 建立一個GCP專案 * 設立預算 (以防被盜後有些保障) * 預算與快訊-> 設定預算 * service account 需要key 才能操作 ---- ### cloud storage 應用場景 巨量資料 空間無限的儲存服務 設計思路 核心名詞 資源object 裝載容器 bucket 水 水杯 錢 錢包 鉛筆 鉛筆盒 創桶子 資料所在地 storage-level 1 取用權限 加密 --- ![](https://i.imgur.com/pBPXivu.jpg) # END