Natural Language AIを試してみた。

# Natural Language AIとは?
テキストを抽出、分析、保存する機械学習を使用して、示唆に富んだテキスト分析を行います。
[doc](https://cloud.google.com/natural-language#documentation)

## 主な機能
1. AutoML
    高品質な独自のカスタム機械学習モデルを**トレーニング**し、感情の分類、抽出、検出が可能
    [doc](https://cloud.google.com/vertex-ai/docs/beginner/beginners-guide?hl=ja)
1. Natural Language API
    デベロッパーがアプリケーションに自然言語理解（NLU)を簡単に適用し、**感情分析**、**エンティティ分析**、**エンティティ感情分析**、**コンテンツ分類**、**構文解析**などの機能を利用可能
    [doc](https://cloud.google.com/natural-language/docs/reference/rest)
    [quick start](https://www.cloudskillsboost.google/focuses/582?catalog_rank=%7B%22rank%22:1,%22num_filters%22:0,%22has_search%22:true%7D&parent=catalog&search_id=31485341?utm_source=cgc-site&utm_medium=et&utm_campaign=FY24-Q2-global-website-skillsboost&utm_content=developers&utm_term=-)
1. Healthcare Natural Language AI
    構造化されていない**医療文書**に保存された知見をリアルタイムで分析可能

## 料金
調査中です
[doc](https://cloud.google.com/vertex-ai/docs/beginner/beginners-guide?hl=ja)

## Cloud Natural Language API: Qwik Start をやってみた
[link](https://www.cloudskillsboost.google/focuses/582?catalog_rank=%7B%22rank%22:1,%22num_filters%22:0,%22has_search%22:true%7D&parent=catalog&search_id=31485341?utm_source=cgc-site&utm_medium=et&utm_campaign=FY24-Q2-global-website-skillsboost&utm_content=developers&utm_term=-)

### Cloud Natural Language API の特徴
1. Entity Recognition
    テキストにおける**エンティティ** (人、場所、ものなど)を理解する
1. Sentiment Analysis
    テキストの**sentiment** (positiveかnegativeかneutralか)を分析する
1. Information Extraction
    テキストから**日付**、**時刻**、**価格**などを抽出する
1. Question Answering
    テキストに関する**質問**に答える
1. Integrated REST API
    テキストは、**リクエスト**に含めてアップロードすることも、**Cloud Storage** と統合することも可能

## cloud shellをアクティブにする
- Acticve Cloud Shellで **cloud shell**をアクティブにします
    基本的に操作は、cloud shell上で行います。
    ![スクリーンショット 2025-01-24 15.56.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579576/631a5de2-945c-31ab-92ce-a737f32d9928.png)
- cloud shell が立ち上がります
    画面下にcloud shellが存在していることがわかります。
    ![スクリーンショット 2025-01-24 15.57.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579576/5c34f537-a2f1-8601-4640-e3db0b55df51.png)

- 認証を与える
    ![スクリーンショット 2025-01-24 15.59.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579576/902c91da-c4cd-e55f-9f69-2e29f999e92d.png)
    ```
    student_00_35959780410c@cloudshell:~ (qwiklabs-gcp-00-b50f0ea75b7a)$ gcloud auth list
    Credentialed Accounts
    
    ACTIVE: *
    ACCOUNT: student-00-35959780410c@qwiklabs.net
    
    To set the active account, run:
        $ gcloud config set account `ACCOUNT`
    ```

- プロジェクトの一覧表示
    ```
    student_00_35959780410c@cloudshell:~ (qwiklabs-gcp-00-b50f0ea75b7a)$ gcloud config list project
    [core]
    project = qwiklabs-gcp-00-b50f0ea75b7a
    
    Your active configuration is: [cloudshell-22506]
    ```

### タスク1. APIキーの作成
1. 環境変数の設定
1. Natural Language API にアクセスするための新しい**サービス アカウント**を作成
    **my-natlang-sa**という名前で作成
1. 作成した新しいサービス アカウントにログインするための**認証情報**を作成
    /home/student_00_35959780410c/key.jsonに**jsonの鍵**が作成される
1. **GOOGLE_APPLICATION_CREDENTIALS 環境変数**を設定します。
    この環境変数は、作成した認証情報 JSON ファイルのフルパスに設定
```
student_00_35959780410c@cloudshell:~ (qwiklabs-gcp-00-b50f0ea75b7a)$ export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value core/project)
Your active configuration is: [cloudshell-22506]
student_00_35959780410c@cloudshell:~ (qwiklabs-gcp-00-b50f0ea75b7a)$ gcloud iam service-accounts create my-natlang-sa \
  --display-name "my natural language service account"
Created service account [my-natlang-sa].
student_00_35959780410c@cloudshell:~ (qwiklabs-gcp-00-b50f0ea75b7a)$ gcloud iam service-accounts keys create ~/key.json \
  --iam-account my-natlang-sa@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com
created key [5dd4940a5cc14f9fc84dc66bea80f1a0e49ea4eb] of type [json] as [/home/student_00_35959780410c/key.json] for [my-natlang-sa@qwiklabs-gcp-00-b50f0ea75b7a.iam.gserviceaccount.com]
student_00_35959780410c@cloudshell:~ (qwiklabs-gcp-00-b50f0ea75b7a)$ export GOOGLE_APPLICATION_CREDENTIALS="/home/USER/key.json"
student_00_35959780410c@cloudshell:~ (qwiklabs-gcp-00-b50f0ea75b7a)$ 
```
### タスク 2. エンティティ分析リクエストを行う
compute engineにsshで接続します
![スクリーンショット 2025-01-24 16.11.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579576/2ea38b95-de37-330b-81ad-569eb3ed07d0.png)
<details><summary> 使用例1</summary>

"Michelangelo Caravaggio, Italian painter, is known for 'The Calling of Saint Matthew'."を構文解析しています。
入力
```
    student-00-35959780410c@linux-instance:~$ gcloud ml language analyze-entities --content="Michelangelo Caravaggio, Italian painter, is known for 'The Calling of Saint Matthew'." > result.json
```
結果
```
    student-00-35959780410c@linux-instance:~$ cat result.json
    {
      "entities": [
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 0,
                "content": "Michelangelo Caravaggio"
              },
              "type": "PROPER"
            },
            {
              "text": {
                "beginOffset": 33,
                "content": "painter"
              },
              "type": "COMMON"
            }
          ],
          "metadata": {
            "mid": "/m/020bg",
            "wikipedia_url": "https://en.wikipedia.org/wiki/Caravaggio"
          },
          "name": "Michelangelo Caravaggio",
          "salience": 0.82904786,
          "type": "PERSON"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 25,
                "content": "Italian"
              },
              "type": "PROPER"
            }
          ],
          "metadata": {},
          "name": "Italian",
          "salience": 0.13981608,
          "type": "LOCATION"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 56,
                "content": "The Calling of Saint Matthew"
              },
              "type": "PROPER"
            }
          ],
          "metadata": {
            "mid": "/m/085_p7",
            "wikipedia_url": "https://en.wikipedia.org/wiki/The_Calling_of_Saint_Matthew"
          },
          "name": "The Calling of Saint Matthew",
          "salience": 0.031136045,
          "type": "EVENT"
        }
      ],
      "language": "en"
    }
    student-00-35959780410c@linux-instance:~$ 
```
</details>

<details><summary>使用例2</summary>

"iPhone（アイフォーン[注 1][注 2]）は、Appleが設計・販売しているスマートフォン[注 3]。初代iPhoneは2007年1月9日に発表され[16][17]、同年6 月29日にアメリカ合衆国で販売が開始された[18][19]。「通信キャリア」とのシームレスな通話をも可能にしたこと、当初はアプリケーションも自社限定であり機能は多くなかったが、GPSも内蔵していたことで話題になった。'."
をエンティティ分析します。

iPhoneがPROPERとなっています。

- 入力
    ```
        student-00-35959780410c@linux-instance:~$ gcloud ml language analyze-entities --content="iPhone（アイフォーン[注 1][注 2]）は、Appleが設計・販売しているスマートフォン[注 3]。初代iPhoneは2007年1月9日に発表され[16][17]、同年6 月29日にアメリカ合衆国で販売が開始された[18][19]。「通信キャリア」とのシームレスな通話をも可能にしたこと、当初はアプリケーションも自社限定であり機能は多くなかったが、GPSも内蔵していたことで話題になった。'." > result2.json
    ```

- 出力
    ```
    student-00-35959780410c@linux-instance:~$ cat result2.json 
    {
      "entities": [
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 0,
                "content": "iPhone"
              },
              "type": "PROPER"
            },
            {
              "text": {
                "beginOffset": 9,
                "content": "アイフォーン"
              },
              "type": "COMMON"
            },
            {
              "text": {
                "beginOffset": 122,
                "content": "iPhone"
              },
              "type": "PROPER"
            }
          ],
          "metadata": {
            "mid": "/m/027lnzs",
            "wikipedia_url": "https://en.wikipedia.org/wiki/IPhone"
          },
          "name": "iPhone",
          "salience": 0.30917555,
          "type": "CONSUMER_GOOD"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 50,
                "content": "Apple"
              },
              "type": "PROPER"
            }
          ],
          "metadata": {
            "mid": "/m/0k8z",
            "wikipedia_url": "https://en.wikipedia.org/wiki/Apple_Inc."
          },
          "name": "Apple",
          "salience": 0.11915708,
          "type": "ORGANIZATION"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 58,
                "content": "設計"
              },
              "type": "COMMON"
            }
          ],
          "metadata": {},
          "name": "設計",
          "salience": 0.08993218,
          "type": "EVENT"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 85,
                "content": "スマートフォン"
              },
              "type": "COMMON"
            }
          ],
          "metadata": {},
          "name": "スマートフォン",
          "salience": 0.08993218,
          "type": "CONSUMER_GOOD"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 214,
                "content": "販売"
              },
              "type": "COMMON"
            }
          ],
          "metadata": {},
          "name": "販売",
          "salience": 0.05309472,
          "type": "EVENT"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 342,
                "content": "アプリケーション"
              },
              "type": "COMMON"
            }
          ],
          "metadata": {},
          "name": "アプリケーション",
          "salience": 0.050610293,
          "type": "CONSUMER_GOOD"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 190,
                "content": "アメリカ合衆国"
              },
              "type": "PROPER"
            }
          ],
          "metadata": {
            "mid": "/m/09c7w0",
            "wikipedia_url": "https://en.wikipedia.org/wiki/United_States"
          },
          "name": "アメリカ合衆国",
          "salience": 0.044786528,
          "type": "LOCATION"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 447,
                "content": "こと"
              },
              "type": "COMMON"
            }
          ],
          "metadata": {},
          "name": "こと",
          "salience": 0.04379497,
          "type": "OTHER"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 324,
                "content": "こと"
              },
              "type": "COMMON"
            }
          ],
          "metadata": {},
          "name": "こと",
          "salience": 0.039109956,
          "type": "OTHER"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 369,
                "content": "自社限定"
              },
              "type": "COMMON"
            }
          ],
          "metadata": {},
          "name": "自社限定",
          "salience": 0.029772716,
          "type": "OTHER"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 390,
                "content": "機能"
              },
              "type": "COMMON"
            }
          ],
          "metadata": {},
          "name": "機能",
          "salience": 0.029772716,
          "type": "OTHER"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 423,
                "content": "GPS"
              },
              "type": "COMMON"
            }
          ],
          "metadata": {},
          "name": "GPS",
          "salience": 0.029772716,
          "type": "OTHER"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 297,
                "content": "通話"
              },
              "type": "COMMON"
            }
          ],
          "metadata": {},
          "name": "通話",
          "salience": 0.028532702,
          "type": "EVENT"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 456,
                "content": "話題"
              },
              "type": "COMMON"
            }
          ],
          "metadata": {},
          "name": "話題",
          "salience": 0.024035947,
          "type": "OTHER"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 252,
                "content": "通信キャリア"
              },
              "type": "COMMON"
            }
          ],
          "metadata": {},
          "name": "通信キャリア",
          "salience": 0.018519735,
          "type": "ORGANIZATION"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 131,
                "content": "2007年1月9日"
              },
              "type": "TYPE_UNKNOWN"
            }
          ],
          "metadata": {
            "day": "9",
            "month": "1",
            "year": "2007"
          },
          "name": "2007年1月9日",
          "salience": 0.0,
          "type": "DATE"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 178,
                "content": "6月29日"
              },
              "type": "TYPE_UNKNOWN"
            }
          ],
          "metadata": {
            "day": "29",
            "month": "6"
          },
          "name": "6月29日",
          "salience": 0.0,
          "type": "DATE"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 32,
                "content": "1"
              },
              "type": "TYPE_UNKNOWN"
            }
          ],
          "metadata": {
            "value": "1"
          },
          "name": "1",
          "salience": 0.0,
          "type": "NUMBER"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 39,
                "content": "2"
              },
              "type": "TYPE_UNKNOWN"
            }
          ],
          "metadata": {
            "value": "2"
          },
          "name": "2",
          "salience": 0.0,
          "type": "NUMBER"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 111,
                "content": "3"
              },
              "type": "TYPE_UNKNOWN"
            }
          ],
          "metadata": {
            "value": "3"
          },
          "name": "3",
          "salience": 0.0,
          "type": "NUMBER"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 131,
                "content": "2007"
              },
              "type": "TYPE_UNKNOWN"
            }
          ],
          "metadata": {
            "value": "2007"
          },
          "name": "2007",
          "salience": 0.0,
          "type": "NUMBER"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 138,
                "content": "1"
              },
              "type": "TYPE_UNKNOWN"
            }
          ],
          "metadata": {
            "value": "1"
          },
          "name": "1",
          "salience": 0.0,
          "type": "NUMBER"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 142,
                "content": "9"
              },
              "type": "TYPE_UNKNOWN"
            }
          ],
          "metadata": {
            "value": "9"
          },
          "name": "9",
          "salience": 0.0,
          "type": "NUMBER"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 162,
                "content": "16"
              },
              "type": "TYPE_UNKNOWN"
            }
          ],
          "metadata": {
            "value": "16"
          },
          "name": "16",
          "salience": 0.0,
          "type": "NUMBER"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 166,
                "content": "17"
              },
              "type": "TYPE_UNKNOWN"
            }
          ],
          "metadata": {
            "value": "17"
          },
          "name": "17",
          "salience": 0.0,
          "type": "NUMBER"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 178,
                "content": "6"
              },
              "type": "TYPE_UNKNOWN"
            }
          ],
          "metadata": {
            "value": "6"
          },
          "name": "6",
          "salience": 0.0,
          "type": "NUMBER"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 182,
                "content": "29"
              },
              "type": "TYPE_UNKNOWN"
            }
          ],
          "metadata": {
            "value": "29"
          },
          "name": "29",
          "salience": 0.0,
          "type": "NUMBER"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 239,
                "content": "18"
              },
              "type": "TYPE_UNKNOWN"
            }
          ],
          "metadata": {
            "value": "18"
          },
          "name": "18",
          "salience": 0.0,
          "type": "NUMBER"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 243,
                "content": "19"
              },
              "type": "TYPE_UNKNOWN"
            }
          ],
          "metadata": {
            "value": "19"
          },
          "name": "19",
          "salience": 0.0,
          "type": "NUMBER"
        }
      ],
      "language": "ja"
    }
    student-00-35959780410c@linux-instance:~$ 
    ```
</details>

<details><summary> 使用例3 </summary>

"私の名前は加藤です。年 齢は25歳です。"をエンティティ解析しています。
名前がCOMMON, 加藤がPEOPLE, 年齢がCOMMON, 25はTYPE_UNKNOWNになっています。

- 入力
    ```
    student-00-35959780410c@linux-instance:~$ gcloud ml language analyze-entities --content="私の名前は加藤です。年 齢は25歳です。" > result3.json
    ```
- 出力
    ```
    student-00-35959780410c@linux-instance:~$ cat result3.json 
    {
      "entities": [
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 6,
                "content": "名前"
              },
              "type": "COMMON"
            }
          ],
          "metadata": {},
          "name": "名前",
          "salience": 0.43785238,
          "type": "OTHER"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 15,
                "content": "加藤"
              },
              "type": "PROPER"
            }
          ],
          "metadata": {},
          "name": "加藤",
          "salience": 0.3908405,
          "type": "PERSON"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 30,
                "content": "年齢"
              },
              "type": "COMMON"
            }
          ],
          "metadata": {},
          "name": "年齢",
          "salience": 0.17130712,
          "type": "OTHER"
        },
        {
          "mentions": [
            {
              "text": {
                "beginOffset": 39,
                "content": "25"
              },
              "type": "TYPE_UNKNOWN"
            }
          ],
          "metadata": {
            "value": "25"
          },
          "name": "25",
          "salience": 0.0,
          "type": "NUMBER"
        }
      ],
      "language": "ja"
    }
    student-00-35959780410c@linux-instance:~$ 
    ```
</details>

## Pythonで動かす
### 1. IAMユーザーの作成と権限付与
Google Cloud PlatformのIAM（Identity and Access Management）で、Natural Language APIを使用するためのカスタムロールを作成し、そのロールをユーザーに割り当てます。

### 2. サービスアカウントの作成とキーの生成
Natural Language APIにアクセスするためのサービスアカウントを作成し、そのサービスアカウントのキーをJSON形式でダウンロードします。

### 3. 環境変数の設定
ダウンロードしたJSONキーのパスを、環境変数`GOOGLE_APPLICATION_CREDENTIALS`に設定します。

```bash
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/key.json"
```

### 4. 実行
- `pipenv run python natural-language.py`

```python:natural-language.py
import os
import google.cloud.language_v1 as language

def analyze_sentiment(text):
    """テキストの感情を分析する"""
    client = language.LanguageServiceClient()
    document = language.Document(
        content=text,
        type_=language.Document.Type.PLAIN_TEXT
    )

    sentiment = client.analyze_sentiment(document=document).document_sentiment
    print("Text: {}".format(text))
    print("Sentiment: {}, {}".format(
        sentiment.score, sentiment.magnitude))

def main():
    print(os.getenv("GOOGLE_APPLICATION_CREDENTIALS"))  # jsonファイルのパス
    text = "この製品はとても良いです。"
    analyze_sentiment(text)

if __name__ == "__main__":
    main()
```

```pip:Pipfile
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
google-cloud-language = "*"

[dev-packages]

[requires]
python_version = "3.10"
```

```bash:結果
taketo@MacBook-Pro-4 natural-langauge-api % pipenv run python natural-language.py
Loading .env environment variables...
/Users/taketo/Downloads/naturallanguageapipractice-1372273acbf4.json
Text: この製品はとても良いです。
Sentiment: 0.8999999761581421, 0.8999999761581421
taketo@MacBook-Pro-4 natural-langauge-api % 
```
scoreとmagnitudeが取れることが確認可能です。

# まとめ
Qwik StartでNatural Language APIを利用しました。
エンティティ分析のみ利用しました。