# 第四週 SaaS 初體驗 學習目標: 1. 在本地端建立 Web App 2. 將 Web App 部署到雲端 3. Bind a Watson service with your application ## Part 1: Python Flask - 建立 Web App 步驟1: 打開 Visual Studio Code 並點選 workspace 步驟2: 建立一個新的專案, find_author, 並建立該專案專屬的資料夾 步驟3: 打開 terminal 安裝 flask ``` PS D:\python_lab>mkdir find_author PS D:\python_lab>cd find_author PS D:\python_lab\find_author> pip install flask ``` 步驟4: 如何驗證 flask 有安裝成功 ``` $ python >>> import flask >>> exit() ``` 步驟5: 在專案的資料夾中新增檔案, 並取名為 app.py (Ref: https://flask.palletsprojects.com/en/2.0.x/tutorial/layout/) ```python= from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return 'Hello, World!' ``` 步驟6: 執行應用程式 ``` PS D:\python_lab>cd find_author PS D:\python_lab\find_author> set FLASK_APP=app.py PS D:\python_lab\find_author> flask run ``` 附註: 如果是使用 Mac 的同學, ``` PS D:\python_lab\find_author> set FLASK_APP=app.py 要換成 $ export FLASK_APP=app.py ``` ## Part 2: 用 Command Line Interface (CLI) 部署 App 到雲端 (IBM Cloud) 步驟1: 新增 manifest.yml 檔案 ```yaml= applications: - path: . name: ntust1021demo environment_json: {} memory: 128M instances: 1 disk_quota: 1024M services: [] ``` 步驟2: 新增 requirements.txt 檔案 ``` Flask>=1.0.0 ``` 步驟3: Read port selected by the cloud for our application ```python= port = int(os.getenv('PORT', 8080)) ``` 步驟4: Get public IP to run the application ```python= if __name__ == '__main__': app.run(host='0.0.0.0', port=port) ``` 步驟5: 新增 "Procfile" 檔案, 定義 application 如何被執行 ``` web: python app.py ``` 步驟6: ``` step 1: ibmcloud login step 2: ibmcloud target --cf step 3: ibmcloud cf push ``` ## Part 3: Bind a Watson service with your application ### 建立一個 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>=5.2.3" ``` (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, MetadataOptions authenticator = IAMAuthenticator('{apikey}') natural_language_understanding = NaturalLanguageUnderstandingV1( version='2021-08-01', 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= MetadataOptions())).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>=1.0.0 ibm-watson>=5.2.3 ``` (6) 先在本地端做測試, 如果都沒有問題, 就可以部署到 IBM Cloud. 測試網址: https://www.ibm.com/blogs/think/2017/01/cognitive-grid/ 參考資料: 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 IBM Cloud CLI 部署應用程式的範例 ``` PS D:\python_G_Lab\myTest> ibmcloud login API endpoint: https://cloud.ibm.com Region: us-south Email> ntustcs110@gmail.com Password> Authenticating... OK Targeted account Rebecca Chen's Account (ee055448f30447bba6d782f2641c9a15) API endpoint: https://cloud.ibm.com Region: us-south User: ntustcs110@gmail.com Account: Rebecca Chen's Account (ee055448f30447bba6d782f2641c9a15) Resource group: No resource group targeted, use 'C:\Program Files\IBM\Cloud\bin\ibmcloud.exe target -g RESOURCE_GROUP' CF API endpoint: Org: Space: PS D:\python_G_Lab\myTest> ibmcloud target --cf Targeted Cloud Foundry (https://api.us-south.cf.cloud.ibm.com) Targeted org ntustcs110@gmail.com Targeted space dev API endpoint: https://cloud.ibm.com Region: us-south User: ntustcs110@gmail.com Account: Rebecca Chen's Account (ee055448f30447bba6d782f2641c9a15) Resource group: No resource group targeted, use 'C:\Program Files\IBM\Cloud\bin\ibmcloud.exe target -g RESOURCE_GROUP' CF API endpoint: https://api.us-south.cf.cloud.ibm.com (API version: 2.169.0) Org: ntustcs110@gmail.com Space: dev PS D:\python_G_Lab\myTest> ibmcloud cf push Invoking 'cf push'... Pushing from manifest to org ntustcs110@gmail.com / space dev as ntustcs110@gmail.com... Using manifest file D:\python_G_Lab\myTest\manifest.yml Getting app info... Creating app with these attributes... + name: ntust1021demo path: D:\python_G_Lab\myTest + disk quota: 1G + instances: 1 + memory: 128M routes: + ntust1021demo.mybluemix.net Creating app ntust1021demo... Mapping routes... Comparing local files to remote cache... Packaging files to upload... Uploading files... 1.13 KiB / 1.13 KiB [====================================================================] 100.00% 1s Waiting for API to complete processing files... Staging app and tracing logs... Downloading liberty-for-java_v3_62-20210922-1852... Downloaded noop-buildpack Downloading liberty-for-java... Downloading nodejs_buildpack... Downloading noop-buildpack... Downloading xpages_buildpack... Downloaded nodejs_buildpack Downloading staticfile_buildpack... Downloading java_buildpack... Downloaded liberty-for-java Downloading ruby_buildpack... Downloaded xpages_buildpack Downloading go_buildpack... Downloaded staticfile_buildpack Downloading python_buildpack... Downloaded liberty-for-java_v3_62-20210922-1852 Downloading php_buildpack... Downloaded java_buildpack Downloading binary_buildpack... Downloaded php_buildpack Downloading nginx_buildpack... Downloaded python_buildpack Downloading r_buildpack... Downloaded go_buildpack Downloading dotnet_core_buildpack... Downloaded binary_buildpack Downloading liberty-for-java_v3_61-20210826-1015... Downloaded nginx_buildpack Downloaded dotnet_core_buildpack Downloaded r_buildpack Downloaded liberty-for-java_v3_61-20210826-1015 Downloaded ruby_buildpack Cell 46f28da9-7e84-4f70-8fed-e82fd80baa65 creating container for instance 9cec61c3-135d-4f11-9a16-c65e0c0d013f Cell 46f28da9-7e84-4f70-8fed-e82fd80baa65 successfully created container for instance 9cec61c3-135d-4f11-9a16-c65e0c0d013f Downloading app package... Downloaded app package (1.1K) -----> Python Buildpack version 1.7.45 -----> Supplying Python -----> Installing python 3.8.11 Download [https://buildpacks.cloudfoundry.org/dependencies/python/python_3.8.11_linux_x64_cflinuxfs3_e57abfea.tgz] -----> Installing pip-pop 0.1.5 Download [https://buildpacks.cloudfoundry.org/dependencies/manual-binaries/pip-pop/pip-pop-0.1.5-b32efe86.tar.gz] -----> Running Pip Install Collecting Flask>=1.0.0 Downloading Flask-2.0.2-py3-none-any.whl (95 kB) Collecting Werkzeug>=2.0 Downloading Werkzeug-2.0.2-py3-none-any.whl (288 kB) Collecting itsdangerous>=2.0 Downloading itsdangerous-2.0.1-py3-none-any.whl (18 kB) Collecting click>=7.1.2 Downloading click-8.0.3-py3-none-any.whl (97 kB) Collecting Jinja2>=3.0 Downloading Jinja2-3.0.2-py3-none-any.whl (133 kB) Collecting MarkupSafe>=2.0 Downloading MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (30 kB) Installing collected packages: MarkupSafe, Werkzeug, Jinja2, itsdangerous, click, Flask WARNING: The script flask is installed in '/tmp/contents489990871/deps/0/python/bin' which is not on PATH. Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location. Successfully installed Flask-2.0.2 Jinja2-3.0.2 MarkupSafe-2.0.1 Werkzeug-2.0.2 click-8.0.3 itsdangerous-2.0.1 Exit status 0 Uploading droplet, build artifacts cache... Uploading droplet... Uploading build artifacts cache... Uploaded build artifacts cache (56.5M) Uploaded droplet (57.4M) Uploading complete Cell 46f28da9-7e84-4f70-8fed-e82fd80baa65 stopping instance 9cec61c3-135d-4f11-9a16-c65e0c0d013f Cell 46f28da9-7e84-4f70-8fed-e82fd80baa65 destroying container for instance 9cec61c3-135d-4f11-9a16-c65e0c0d013f Waiting for app to start... name: ntust1021demo requested state: started routes: ntust1021demo.mybluemix.net last uploaded: Thu 21 Oct 08:44:21 CST 2021 stack: cflinuxfs3 buildpacks: python type: web instances: 1/1 memory usage: 128M start command: python app.py state since cpu memory disk details #0 running 2021-10-21T00:47:40Z 0.0% 31.5M of 128M 207.6M of 1G PS D:\python_G_Lab\myTest> ```