# 第四週 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>
```