# 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

輸入 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()
```