# 20221013 My First SaaS application 學習目標: 1. 在IBM cloud 建立一個 NLU 的 instance 2. 將 Web App 綁定 NLU 服務並部署到雲端 ## Part 0: 預備動作 步驟1: 在本地(local)端建立 Web App 延續[上週的課程內容](https://hackmd.io/@bluemix/S1XgiEMfs), 請確認 Web App 能成功在本地(local)端執行 參考程式碼 ```python= from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return 'Hello, World!' if __name__ == '__main__': app.run() ``` 執行應用程式 ``` PS D:\pythonlab_111_MIG004301\firstApp> python app.py ``` 步驟2: 預備雲端程式(APP)的設定檔 (1): 描述使用的 python 環境 在專案的資料夾中新增一個檔案, 並取名為 runtime.txt ``` python-3.10.7 ``` (2): 描述程式運作所需要的套件 在專案的資料夾中新增一個檔案, 並取名為 requirements.txt ``` Flask gunicorn ``` Notes: gunicorn 是為了在 heroku 啟動專案用的套件 (3): 如何啟動/執行程式 在專案的資料夾中新增一個檔案, 並取名為 Procfile ``` web gunicorn app:app ``` 第一個 app 指的是主程式.py 的名稱. 因為我們的主程式取名為app.py, 所以, 冒號前面的變數用app 第二個 app, 指的是主程式中, 設定 Flask 應用程式的物件的變數. 因為我們取變數為 app, 所以, 冒號後面的變數用app ``` app = Flask(__name__) ``` 如果電腦沒有安裝 GIT TOOL, 請在下一個步驟前, 安裝 git, 並設定 Git 使用者帳號. ``` > git config --global user.email "you@example.com" > git config --global user.name "Your Name" ``` 步驟3: 將網站伺服器部署到 Heroku (1): Create new app ![](https://i.imgur.com/hkvvsLQ.png) 輸入 app 名稱, 取的名字必須是 "唯一" 的; 然後選擇主機地區, 按 "Create app" (2): 登入 heroku, 輸入 email 及 password ``` heroku login ``` (3): 初始化專案, 這個指令只有當你部署新的專案(new app)的第一次的時候, 才需要做的動作 ``` git init heroku git:remote -a 專案名稱 ``` (4): 部署專案 ``` git add . git commit -m "First Deploy" git push heroku master ``` (5): 以後每次修改程式之後, 需要用下列命令重新部署 ``` git add . git commit -m "Second Deploy" git push heroku master ``` ## Part 1: 在IBM cloud 建立一個 NLU 的 instance ### 建立一個 Watson NLU 服務 步驟 1: Login IBM Cloud https://cloud.ibm.com/login 步驟 2: 點選 "型錄" , 然後在左邊的選單中, 點選 "服務" 後,再勾點選 "型錄" , 然後在左邊的選單中, 點選 "服務" 後,再勾選 "AI / 機器學習", 就可以看到 AI services 相關的服務. 步驟 3: 點選 "Natural Language Understanding" 服務. "選取地區" 用預設值 "達拉斯", 服務名稱可以採用預設的值, 然後點選右邊的 "建立" 按鈕. 步驟 4: 點選剛建立好的 instance. 基本上, NLU 服務會自動產生一組連線的憑證(service credential), 因此, 我們不需要自己手動建立. ### 修改程式碼 步驟1: 新增static 目錄,再新增 index.html 檔案 ```htmlmixed= <html> <body> <h1 style="color:blue;">Watson Author Finder</h1> <p>To get information about the author of an article, enter the URL of that article.</p> <form action="author" method="post"> <input type="text" name="url" /> <input type="submit" value="Submit" /> </form> </body> </html> ``` 步驟2: 修改 app.py 檔案, 並定義 route by using decorator ```python= @app.route('/') def root(): return app.send_static_file('index.html') ``` ```python= @app.route('/author', methods = ['POST']) def metadata(): url_input = request.form.get('url') return url_input ``` 步驟3 利用 IBM Watson NLU 服務來分析文章 meta data (1) ``` pip install --upgrade "ibm-watson>=6.1.0" ``` (2) 連線 IBM Watson NLU ```python= import json from ibm_watson import NaturalLanguageUnderstandingV1 from ibm_cloud_sdk_core.authenticators import IAMAuthenticator from ibm_watson.natural_language_understanding_v1 import Features authenticator = IAMAuthenticator('{apikey}') natural_language_understanding = NaturalLanguageUnderstandingV1( version='2022-04-07', authenticator=authenticator ) natural_language_understanding.set_service_url('{url}') ``` (3) 用 metadata option 來分析文章 ```python= # return url_input response = natural_language_understanding.analyze( url=url_input, features=Features(metadata= {})).get_result() print(json.dumps(response, indent=2)) return response ``` (4) 從 response 中取出 authors 的欄位 ```python= #return response author = json.dumps(response.get("metadata").get("authors")) return author ``` (5) Update requirements.txt 檔案 ``` Flask gunicorn ibm_watson ``` (6) 先在本地端做測試, 如果都沒有問題, 就可以部署到 Heroku Cloud. 可用這個網址做測試: https://www.ibm.com/blogs/think/2017/01/cognitive-grid/ ## Part 2: 將 Web App 綁定 NLU 服務並部署到雲端 登入 heroku, 輸入 email 及 password ``` heroku login ``` 以後每次修改程式之後, 需要用下列命令重新部署 ``` git add . git commit -m "Second Deploy" git push heroku master ``` ========================================== 參考資料: 1. Flask 官網: https://flask.palletsprojects.com/en/2.0.x/tutorial/layout 2. IBM Watson API document: https://cloud.ibm.com/apidocs/natural-language-understanding?code=python 3. IBM Watson NLU for metadata https://cloud.ibm.com/apidocs/natural-language-understanding?code=python#metadata ```python= import json from ibm_watson import NaturalLanguageUnderstandingV1 from ibm_cloud_sdk_core.authenticators import IAMAuthenticator from ibm_watson.natural_language_understanding_v1 \ import Features authenticator = IAMAuthenticator('{apikey}') natural_language_understanding = NaturalLanguageUnderstandingV1( version='2022-04-07', authenticator=authenticator ) natural_language_understanding.set_service_url('{url}') response = natural_language_understanding.analyze( url='www.ibm.com', features=Features(metadata= MetadataOptions())).get_result() print(json.dumps(response, indent=2)) ``` 第17行有 Bug. 應該改為下面的呼叫方式: ``` features=Features(metadata= {})).get_result() ``` 程式碼參考: app.py ```python= from flask import Flask, request import os import json from ibm_watson import NaturalLanguageUnderstandingV1 from ibm_cloud_sdk_core.authenticators import IAMAuthenticator from ibm_watson.natural_language_understanding_v1 import Features app = Flask(__name__) authenticator = IAMAuthenticator('{apikey}') natural_language_understanding = NaturalLanguageUnderstandingV1( version='2022-04-07', authenticator=authenticator ) natural_language_understanding.set_service_url('{url}') # @app.route('/') # def hello(): # return 'Hello, World!' @app.route('/') def root(): return app.send_static_file('index.html') @app.route('/author', methods = ['POST']) def metadata(): url_input = request.form.get('url') # return url_input response = natural_language_understanding.analyze( url=url_input, # features=Features(metadata= MetadataOptions())).get_result() features=Features(metadata={})).get_result() # for debuging print("------------------------") print(json.dumps(response, indent=2)) print("------------------------") # return response author = json.dumps(response.get("metadata").get("authors")) return author if __name__ == '__main__': app.run() ```