Zenn
Closed10

Google Cloud Natural Language APIで感情分析など

kun432kun432

ローカルのMacで。

作業ディレクトリ作成

mkdir cloud-natural-language-api-test && cd cloud-natural-language-api-test

Python仮想環境作成。最近はuvになりつつある。

uv pip install google-cloud-language
出力
Installed 17 packages in 26ms
(snip)
 + google-cloud-language==2.17.0
(snip)

できること

  • 構文解析
  • エンティティ分析
  • 感情分析
  • エンティティ感情分析
  • コンテンツ分類
  • テキストモデレーション

冒頭のクラメソさんの記事には、コンテンツ分類は日本語非対応、あと、テキストモデレーションがないようだが、2025/2/17時点で以下を見ると、

https://cloud.google.com/natural-language/docs/languages

  • モデルにはv1とv2がある
    • v1ではコンテンツ分類のサポートは英語のみだったが、v2では日本語もサポート
    • コンテンツ分類以外は全部v1で日本語をサポートしている
  • テキストモデレーションは日本語もサポート(v1)

ように見えるので、一通り全部できそう。ただちょっとこのモデルの違いがどういうものなのかを見つけられなかった。

以降でそれぞれのサンプルコードを見ていくが、認証等は実施済みという前提で。

kun432kun432

構文解析

https://cloud.google.com/natural-language/docs/analyzing-syntax?hl=ja

構文解析では、指定されたテキストを一連の文とトークン(通常は単語)に分解して、それらのトークンに関する言語情報を提供します。

from google.cloud import language_v1


def sample_analyze_syntax(text_content):
    """
    文字列の構文解析を行う

    Args:
      text_content 解析するテキスト内容
    """

    client = language_v1.LanguageServiceClient()

    # 利用可能なタイプ: PLAIN_TEXT, HTML
    type_ = language_v1.Document.Type.PLAIN_TEXT

    # オプション。指定されていない場合、言語は自動的に検出される。
    # サポートされている言語のリストは以下:
    # https://cloud.google.com/natural-language/docs/languages
    language = "ja"
    document = {"content": text_content, "type_": type_, "language": language}

    # 利用可能な値: NONE, UTF8, UTF16, UTF32
    encoding_type = language_v1.EncodingType.UTF8

    response = client.analyze_syntax(
        request={"document": document, "encoding_type": encoding_type}
    )
    # APIから返されたトークンをループ処理
    for token in response.tokens:
        # このトークンのテキスト内容を取得。通常は単語または句読点。
        text = token.text
        print(f"トークン文字列: {text.content}")
        print(f"文書全体におけるトークンの位置: {text.begin_offset}")
        # トークンの品詞情報を取得。品詞の定義は以下:
        # http://www.lrec-conf.org/proceedings/lrec2012/pdf/274_Paper.pdf
        part_of_speech = token.part_of_speech
        # タグを取得、例: NOUN(名詞), ADJ(形容詞)など
        print(
            "品詞タグ: {}".format(
                language_v1.PartOfSpeech.Tag(part_of_speech.tag).name
            )
        )
        # 態を取得、例: ACTIVE(能動態)または PASSIVE(受動態)
        print(
            "態: {}".format(
                language_v1.PartOfSpeech.Voice(part_of_speech.voice).name
            )
        )
        # 時制を取得、例: PAST(過去), FUTURE(未来), PRESENT(現在)など
        print(
            "時制: {}".format(
                language_v1.PartOfSpeech.Tense(part_of_speech.tense).name
            )
        )
        # 追加の品詞情報についてはAPIリファレンスを参照。
        # トークンのレンマを取得。Wikipediaのレンマの説明:
        # https://en.wikipedia.org/wiki/Lemma_(morphology)
        print(f"レンマ: {token.lemma}")
        # トークンの依存関係ツリーの解析情報を取得。依存関係ラベルの詳細については以下:
        # http://www.aclweb.org/anthology/P13-2017
        dependency_edge = token.dependency_edge
        print(f"ヘッドトークンインデックス: {dependency_edge.head_token_index}")
        print(
            "ラベル: {}".format(
                language_v1.DependencyEdge.Label(dependency_edge.label).name
            )
        )
        print("--------------------------------")
        
    # テキストの言語を取得。通常、リクエストで指定された言語と同じか、指定されていない場合は自動検出された言語。
    print(f"テキストの言語: {response.language}")


if __name__ == "__main__":
    sample_analyze_syntax("こんにちは!今日はいいお天気ですね。絶好の競馬観戦日和ですね。")
出力
トークン文字列: こんにちは
文書全体におけるトークンの位置: 0
品詞タグ: CONJ
態: VOICE_UNKNOWN
時制: TENSE_UNKNOWN
レンマ: こんにちは
ヘッドトークンインデックス: 0
ラベル: ROOT
--------------------------------
トークン文字列: !
文書全体におけるトークンの位置: 15
品詞タグ: PUNCT
態: VOICE_UNKNOWN
時制: TENSE_UNKNOWN
レンマ: !
ヘッドトークンインデックス: 0
ラベル: P
--------------------------------
トークン文字列: 今日
文書全体におけるトークンの位置: 18
品詞タグ: NOUN
態: VOICE_UNKNOWN
時制: TENSE_UNKNOWN
レンマ: 今日
ヘッドトークンインデックス: 6
ラベル: NSUBJ
--------------------------------
トークン文字列: は
文書全体におけるトークンの位置: 24
品詞タグ: PRT
態: VOICE_UNKNOWN
時制: TENSE_UNKNOWN
レンマ: は
ヘッドトークンインデックス: 2
ラベル: PRT
--------------------------------
トークン文字列: いい
文書全体におけるトークンの位置: 27
品詞タグ: ADJ
態: VOICE_UNKNOWN
時制: TENSE_UNKNOWN
レンマ: いい
ヘッドトークンインデックス: 6
ラベル: AMOD
--------------------------------
トークン文字列: お
文書全体におけるトークンの位置: 33
品詞タグ: AFFIX
態: VOICE_UNKNOWN
時制: TENSE_UNKNOWN
レンマ: お
ヘッドトークンインデックス: 6
ラベル: PREF
--------------------------------
トークン文字列: 天気
文書全体におけるトークンの位置: 36
品詞タグ: NOUN
態: VOICE_UNKNOWN
時制: TENSE_UNKNOWN
レンマ: 天気
ヘッドトークンインデックス: 6
ラベル: ROOT
--------------------------------
トークン文字列: です
文書全体におけるトークンの位置: 42
品詞タグ: VERB
態: VOICE_UNKNOWN
時制: TENSE_UNKNOWN
レンマ: だ
ヘッドトークンインデックス: 6
ラベル: AUX
--------------------------------
トークン文字列: ね
文書全体におけるトークンの位置: 48
品詞タグ: PRT
態: VOICE_UNKNOWN
時制: TENSE_UNKNOWN
レンマ: ね
ヘッドトークンインデックス: 6
ラベル: PRT
--------------------------------
トークン文字列: 。
文書全体におけるトークンの位置: 51
品詞タグ: PUNCT
態: VOICE_UNKNOWN
時制: TENSE_UNKNOWN
レンマ: 。
ヘッドトークンインデックス: 6
ラベル: P
--------------------------------
トークン文字列: 絶好
文書全体におけるトークンの位置: 54
品詞タグ: NOUN
態: VOICE_UNKNOWN
時制: TENSE_UNKNOWN
レンマ: 絶好
ヘッドトークンインデックス: 13
ラベル: NN
--------------------------------
トークン文字列: の
文書全体におけるトークンの位置: 60
品詞タグ: PRT
態: VOICE_UNKNOWN
時制: TENSE_UNKNOWN
レンマ: の
ヘッドトークンインデックス: 10
ラベル: PRT
--------------------------------
トークン文字列: 競馬
文書全体におけるトークンの位置: 63
品詞タグ: NOUN
態: VOICE_UNKNOWN
時制: TENSE_UNKNOWN
レンマ: 競馬
ヘッドトークンインデックス: 13
ラベル: NN
--------------------------------
トークン文字列: 観戦
文書全体におけるトークンの位置: 69
品詞タグ: NOUN
態: VOICE_UNKNOWN
時制: TENSE_UNKNOWN
レンマ: 観戦
ヘッドトークンインデックス: 15
ラベル: NN
--------------------------------
トークン文字列: 日
文書全体におけるトークンの位置: 75
品詞タグ: AFFIX
態: VOICE_UNKNOWN
時制: TENSE_UNKNOWN
レンマ: 日
ヘッドトークンインデックス: 13
ラベル: SUFF
--------------------------------
トークン文字列: 和
文書全体におけるトークンの位置: 78
品詞タグ: NOUN
態: VOICE_UNKNOWN
時制: TENSE_UNKNOWN
レンマ: 和
ヘッドトークンインデックス: 15
ラベル: ROOT
--------------------------------
トークン文字列: です
文書全体におけるトークンの位置: 81
品詞タグ: VERB
態: VOICE_UNKNOWN
時制: TENSE_UNKNOWN
レンマ: だ
ヘッドトークンインデックス: 15
ラベル: AUX
--------------------------------
トークン文字列: ね
文書全体におけるトークンの位置: 87
品詞タグ: PRT
態: VOICE_UNKNOWN
時制: TENSE_UNKNOWN
レンマ: ね
ヘッドトークンインデックス: 15
ラベル: PRT
--------------------------------
トークン文字列: 。
文書全体におけるトークンの位置: 90
品詞タグ: PUNCT
態: VOICE_UNKNOWN
時制: TENSE_UNKNOWN
レンマ: 。
ヘッドトークンインデックス: 15
ラベル: P
--------------------------------
テキストの言語: ja
kun432kun432

エンティティ分析

https://cloud.google.com/natural-language/docs/analyzing-entities?hl=ja

エンティティ分析は、指定されたテキストに既知のエンティティ(著名人、ランドマークなどの固有名詞)が含まれていないかどうかを調べて、それらのエンティティに関する情報を返します。

from google.cloud import language_v2


def sample_analyze_entities(text_content: str = "California is a state.") -> None:
    """
    文字列内のエンティティを解析する。

    Args:
      text_content: 解析するテキスト内容
    """

    client = language_v2.LanguageServiceClient()

    # 利用可能なタイプ: PLAIN_TEXT, HTML
    document_type_in_plain_text = language_v2.Document.Type.PLAIN_TEXT

    # オプション。指定されていない場合、言語は自動的に検出される。
    # サポートされている言語のリストは以下:
    # https://cloud.google.com/natural-language/docs/languages
    language_code = "ja"
    document = {
        "content": text_content,
        "type_": document_type_in_plain_text,
        "language_code": language_code,
    }

    # 利用可能な値: NONE, UTF8, UTF16, UTF32.
    # 詳細は以下を参照:
    # https://cloud.google.com/natural-language/docs/reference/rest/v2/EncodingType.
    encoding_type = language_v2.EncodingType.UTF8

    response = client.analyze_entities(
        request={"document": document, "encoding_type": encoding_type}
    )

    for entity in response.entities:
        print(f"エンティティの代表名: {entity.name}")

        # エンティティタイプを取得、例: PERSON(人物), LOCATION(場所), ADDRESS(住所), NUMBER(数字)など
        # 詳細は以下を参照:
        # https://cloud.google.com/natural-language/docs/reference/rest/v2/Entity#type.
        print(f"エンティティタイプ: {language_v2.Entity.Type(entity.type_).name}")

        # エンティティに関連するメタデータをループ処理。
        # 一部のエンティティタイプは追加のメタデータを持つ場合がある、例: ADDRESS(住所)エンティティは
        # 住所のstreet_name(通り名), postal_code(郵便番号)などのメタデータを持つ場合がある。
        for metadata_name, metadata_value in entity.metadata.items():
            print(f"{metadata_name}: {metadata_value}")

        # 入力文書内のこのエンティティの言及をループ処理。
        # APIは現在、固有名詞の言及をサポートしている。
        for mention in entity.mentions:
            print(f"言及テキスト: {mention.text.content}")

            # 言及タイプを取得、例: PROPER(固有名詞)
            print(f"言及タイプ: {language_v2.EntityMention.Type(mention.type_).name}")

            # エンティティの最初の言及に関連する確率スコアを取得(範囲: (0, 1.0])。
            print(f"確率スコア: {mention.probability}")
        print("--------------------------------")

    # テキストの言語を取得。通常、リクエストで指定された言語と同じか、指定されていない場合は自動検出された言語。
    print(f"テキストの言語: {response.language_code}")


if __name__ == "__main__":
    sample_analyze_entities("はじめまして、山田太郎です。東京都千代田区永田町に住んでいます。連絡は000-1111-2222までお願いします。")
出力
エンティティの代表名: 000
エンティティタイプ: NUMBER
value: 0
言及テキスト: 000
言及タイプ: TYPE_UNKNOWN
確率スコア: 1.0
--------------------------------
エンティティの代表名: 1111
エンティティタイプ: NUMBER
value: 1111
言及テキスト: 1111
言及タイプ: TYPE_UNKNOWN
確率スコア: 1.0
--------------------------------
エンティティの代表名: 2222
エンティティタイプ: NUMBER
value: 2222
言及テキスト: 2222
言及タイプ: TYPE_UNKNOWN
確率スコア: 1.0
--------------------------------
エンティティの代表名: 千代田区
エンティティタイプ: LOCATION
言及テキスト: 千代田区
言及タイプ: PROPER
確率スコア: 0.8939999938011169
--------------------------------
エンティティの代表名: 山田太郎
エンティティタイプ: PERSON
言及テキスト: 山田太郎
言及タイプ: PROPER
確率スコア: 0.925000011920929
--------------------------------
エンティティの代表名: 東京都
エンティティタイプ: LOCATION
言及テキスト: 東京都
言及タイプ: PROPER
確率スコア: 0.9490000009536743
--------------------------------
エンティティの代表名: 永田町
エンティティタイプ: LOCATION
言及テキスト: 永田町
言及タイプ: PROPER
確率スコア: 0.9409999847412109
--------------------------------
エンティティの代表名: 連絡
エンティティタイプ: EVENT
言及テキスト: 連絡
言及タイプ: COMMON
確率スコア: 0.828000009059906
--------------------------------
テキストの言語: ja
kun432kun432

感情分析

https://cloud.google.com/natural-language/docs/analyzing-sentiment?hl=ja

感情分析は、指定されたテキストを調べて、そのテキストの背景にある感情的な考え方を分析します。具体的には、執筆者の考え方がポジティブか、ネガティブか、ニュートラルかを判断します。

from google.cloud import language_v2


def sample_analyze_sentiment(text_content: str = "I am so happy and joyful.") -> None:
    """
    文字列内の感情を分析する。

    Args:
      text_content: 分析するテキスト内容
    """

    client = language_v2.LanguageServiceClient()

    # text_content = 'I am so happy and joyful.'

    # 利用可能なタイプ: PLAIN_TEXT, HTML
    document_type_in_plain_text = language_v2.Document.Type.PLAIN_TEXT

    # オプション。指定されていない場合、言語は自動的に検出される。
    # サポートされている言語のリストは以下:
    # https://cloud.google.com/natural-language/docs/languages
    language_code = "ja"
    document = {
        "content": text_content,
        "type_": document_type_in_plain_text,
        "language_code": language_code,
    }

    # 利用可能な値: NONE, UTF8, UTF16, UTF32
    # 詳細は以下を参照:
    # https://cloud.google.com/natural-language/docs/reference/rest/v2/EncodingType.
    encoding_type = language_v2.EncodingType.UTF8

    response = client.analyze_sentiment(
        request={"document": document, "encoding_type": encoding_type}
    )
    # 入力文書全体の感情を取得
    print(f"文書の感情スコア: {response.document_sentiment.score}")
    print(f"文書の感情の大きさ: {response.document_sentiment.magnitude}")
    print("================================")
    # 文書内のすべての文の感情を取得
    for sentence in response.sentences:
        print(f"文のテキスト: {sentence.text.content}")
        print(f"文の感情スコア: {sentence.sentiment.score}")
        print(f"文の感情の大きさ: {sentence.sentiment.magnitude}")
        print("--------------------------------")

    print("================================")
    # テキストの言語を取得。通常、リクエストで指定された言語と同じか、指定されていない場合は自動検出された言語。
    print(f"テキストの言語: {response.language_code}")

if __name__ == "__main__":
    sample_analyze_sentiment("こんにちは!今日はいいお天気ですね。昨日の競馬は全然予想がダメダメで、ボロ負けでした・・・。来週は頑張りますよ!")
出力
文書の感情スコア: 0.19599999487400055
文書の感情の大きさ: 2.744999885559082
================================
文のテキスト: こんにちは!
文の感情スコア: 0.10100000351667404
文の感情の大きさ: 0.1809999942779541
--------------------------------
文のテキスト: 今日はいいお天気ですね。
文の感情スコア: 0.9300000071525574
文の感情の大きさ: 0.9599999785423279
--------------------------------
文のテキスト: 昨日の競馬は全然予想がダメダメで、ボロ負けでした・・・。
文の感情スコア: -0.871999979019165
文の感情の大きさ: 0.9300000071525574
--------------------------------
文のテキスト: 来週は頑張りますよ!
文の感情スコア: 0.628000020980835
文の感情の大きさ: 0.6740000247955322
--------------------------------
================================
テキストの言語: ja
kun432kun432

エンティティ感情分析

https://cloud.google.com/natural-language/docs/analyzing-entity-sentiment?hl=ja

エンティティ感情分析とは、エンティティ分析と感情分析の両方を組み合わせたものであり、テキスト内でエンティティについて表現された感情(ポジティブかネガティブか)の特定を試みることです。

from google.cloud import language_v1


def sample_analyze_entity_sentiment(text_content):
    """
    文字列内のエンティティの感情を分析する

    Args:
      text_content: 分析するテキスト内容
    """

    client = language_v1.LanguageServiceClient()

    # text_content = 'Grapes are good. Bananas are bad.'

    # 利用可能なタイプ: PLAIN_TEXT, HTML
    type_ = language_v1.Document.Type.PLAIN_TEXT

    # オプション。指定されていない場合、言語は自動的に検出される。
    # サポートされている言語のリストは以下:
    # https://cloud.google.com/natural-language/docs/languages
    language = "ja"
    document = {"content": text_content, "type_": type_, "language": language}

    # 利用可能な値: NONE, UTF8, UTF16, UTF32
    encoding_type = language_v1.EncodingType.UTF8

    response = client.analyze_entity_sentiment(
        request={"document": document, "encoding_type": encoding_type}
    )
    # APIから返されたエンティティをループ処理
    for entity in response.entities:
        print(f"エンティティの代表名: {entity.name}")
        # エンティティタイプを取得、例: PERSON(人物), LOCATION(場所), ADDRESS(住所), NUMBER(数字)など
        print(f"エンティティタイプ: {language_v1.Entity.Type(entity.type_).name}")
        # エンティティに関連する顕著性スコアを取得(範囲: [0, 1.0])
        print(f"顕著性スコア: {entity.salience}")
        # 提供された文書内でこのエンティティに対して表現された集約感情を取得
        sentiment = entity.sentiment
        print(f"エンティティの感情スコア: {sentiment.score}")
        print(f"エンティティの感情の大きさ: {sentiment.magnitude}")
        # エンティティに関連するメタデータをループ処理。多くの既知のエンティティの場合、
        # メタデータはWikipediaのURL(wikipedia_url)とKnowledge GraphのMID(mid)です。
        # 一部のエンティティタイプは追加のメタデータを持つ場合がある、例: ADDRESS(住所)エンティティは
        # 住所のstreet_name(通り名), postal_code(郵便番号)などのメタデータを持つ場合がある。
        for metadata_name, metadata_value in entity.metadata.items():
            print(f"{metadata_name} = {metadata_value}")

        # 入力文書内のこのエンティティの言及をループ処理。
        # APIは現在、固有名詞の言及をサポートしている。
        for mention in entity.mentions:
            print("--------------------------------")
            print(f"言及テキスト: {mention.text.content}")
            # 言及タイプを取得、例: PROPER(固有名詞)
            print(
                "言及タイプ: {}".format(
                    language_v1.EntityMention.Type(mention.type_).name
                )
            )
        
        print("================================================")

    # テキストの言語を取得。通常、リクエストで指定された言語と同じか、指定されていない場合は自動検出された言語。
    print(f"テキストの言語: {response.language}")

if __name__ == "__main__":
    sample_analyze_entity_sentiment("お疲れ様です、山田です。昨日の競馬は予想がダメダメで、特に京都はボロ負けでした・・・。今週はいよいよフェブラリーSがあるので頑張りますよ!")
出力
エンティティの代表名: 山田
エンティティタイプ: PERSON
顕著性スコア: 0.31785809993743896
エンティティの感情スコア: 0.0
エンティティの感情の大きさ: 0.0
--------------------------------
言及テキスト: 山田
言及タイプ: PROPER
================================================
エンティティの代表名: 競馬
エンティティタイプ: OTHER
顕著性スコア: 0.15909220278263092
エンティティの感情スコア: 0.0
エンティティの感情の大きさ: 0.0
--------------------------------
言及テキスト: 競馬
言及タイプ: COMMON
================================================
エンティティの代表名: 京都
エンティティタイプ: LOCATION
顕著性スコア: 0.14460158348083496
エンティティの感情スコア: -0.10000000149011612
エンティティの感情の大きさ: 0.10000000149011612
wikipedia_url = https://en.wikipedia.org/wiki/Kyoto
mid = /m/09d4_
--------------------------------
言及テキスト: 京都
言及タイプ: PROPER
================================================
エンティティの代表名: フェブラリーS
エンティティタイプ: OTHER
顕著性スコア: 0.12964539229869843
エンティティの感情スコア: 0.30000001192092896
エンティティの感情の大きさ: 0.30000001192092896
wikipedia_url = https://en.wikipedia.org/wiki/February_Stakes
mid = /m/03y09y_
--------------------------------
言及テキスト: フェブラリーS
言及タイプ: PROPER
================================================
エンティティの代表名: ボロ負け
エンティティタイプ: OTHER
顕著性スコア: 0.12843093276023865
エンティティの感情スコア: 0.0
エンティティの感情の大きさ: 0.0
--------------------------------
言及テキスト: ボロ負け
言及タイプ: COMMON
================================================
エンティティの代表名: 予想
エンティティタイプ: OTHER
顕著性スコア: 0.12037180364131927
エンティティの感情スコア: 0.0
エンティティの感情の大きさ: 0.0
--------------------------------
言及テキスト: 予想
言及タイプ: COMMON
================================================
テキストの言語: ja
kun432kun432

コンテンツ分類

https://cloud.google.com/natural-language/docs/classifying-text?hl=ja

コンテンツ分類は、ドキュメントを分析し、ドキュメント内で見つかったテキストに適用されるコンテンツ カテゴリのリストを返します。

from google.cloud import language_v1


def sample_classify_text(text_content):
    """
    文字列内のコンテンツを分類する

    Args:
      text_content: 分析するテキスト内容
    """

    client = language_v1.LanguageServiceClient()

    # text_content = "That actor on TV makes movies in Hollywood and also stars in a variety of popular new TV shows."

    # 利用可能なタイプ: PLAIN_TEXT, HTML
    type_ = language_v1.Document.Type.PLAIN_TEXT

    # オプション。指定されていない場合、言語は自動的に検出される。
    # サポートされている言語のリストは以下:
    # https://cloud.google.com/natural-language/docs/languages
    language = "ja"
    document = {"content": text_content, "type_": type_, "language": language}

    content_categories_version = (
        language_v1.ClassificationModelOptions.V2Model.ContentCategoriesVersion.V2
    )
    response = client.classify_text(
        request={
            "document": document,
            "classification_model_options": {  # v2モデルを使用
                "v2_model": {"content_categories_version": content_categories_version}
            },
        }
    )
    # APIから返された分類カテゴリをループ処理
    for category in response.categories:
        # ドキュメントを表すカテゴリの名前を取得。
        # 定義済みのカテゴリ分類は以下を参照:
        # https://cloud.google.com/natural-language/docs/categories
        print(f"カテゴリ名: {category.name}")
        # 信頼度を取得。分類器がこのカテゴリが提供されたテキストを表しているとどの程度確信しているかを示す数値。
        print(f"信頼度: {category.confidence}")
        print("--------------------------------")

if __name__ == "__main__":
    sample_classify_text("テレビで見たあの俳優がハリウッドで映画を制作し、また、さまざまな人気新テレビ番組にも出演しています。")
出力
カテゴリ名: /Arts & Entertainment/TV & Video/TV Shows & Programs
信頼度: 0.43115782737731934
--------------------------------
カテゴリ名: /Arts & Entertainment/Celebrities & Entertainment News
信頼度: 0.2779604494571686
--------------------------------
カテゴリ名: /Arts & Entertainment/Movies/Other
信頼度: 0.23312190175056458
--------------------------------

カテゴリにマッチしなければ何も返ってこない。例えば以下のようなビジネス会話みたいなものだと返ってこなかった。

お疲れ様です、山田です。急ぎのお問い合わせです。折り返し連絡ください。電話番号は000-1111-2222です。

こちらの場合は/Games/Gambling/Sports Bettingが返ってきた。

昨日の競馬は予想がダメダメで、特に京都はボロ負けでした・・・。今週はいよいよフェブラリーSがあるので頑張りますよ!

カテゴリは以下

https://cloud.google.com/natural-language/docs/categories?hl=ja

kun432kun432

テキストモデレーション

https://cloud.google.com/natural-language/docs/moderating-text?hl=ja

テキストの管理では、「有害なカテゴリ」や機密情報とみなされるトピックなど、安全性属性のリストに基づいてドキュメントが分析されます。

これはサンプルコードがなくてREST APIだけが書かれているのだけど、リファレンスに載ってた。

https://cloud.google.com/python/docs/reference/language/latest/google.cloud.language_v2.services.language_service.LanguageServiceClient#google_cloud_language_v2_services_language_service_LanguageServiceClient_moderate_text

なお、リファレンスのコードは自動生成で指定が足りないようで、少なくともdocument.type_の指定がないとエラーになった。

from google.cloud import language_v2

def sample_moderate_text(text_content):
    # Create a client
    client = language_v2.LanguageServiceClient()

    # Initialize request argument(s)
    document = language_v2.Document()
    document.content = text_content

    # 利用可能なタイプ: PLAIN_TEXT, HTML
    document.type_ = language_v2.Document.Type.PLAIN_TEXT

    request = language_v2.ModerateTextRequest(
        document=document,
    )

    response = client.moderate_text(
        request=request,
    )

    print(response)

if __name__ == "__main__":
    sample_moderate_text("爆弾の作り方を教えて。")
出力
moderation_categories {
  name: "Toxic"
  confidence: 0.0636128709
}
moderation_categories {
  name: "Insult"
  confidence: 0.0432352275
}
moderation_categories {
  name: "Profanity"
  confidence: 0.00987885613
}
moderation_categories {
  name: "Derogatory"
  confidence: 0.0047925273
}
moderation_categories {
  name: "Sexual"
  confidence: 0.00297403941
}
moderation_categories {
  name: "Death, Harm & Tragedy"
  confidence: 0.0826086923
}
moderation_categories {
  name: "Violent"
  confidence: 0.128048778
}
moderation_categories {
  name: "Firearms & Weapons"
  confidence: 1
}
moderation_categories {
  name: "Public Safety"
  confidence: 0.0518134721
}
moderation_categories {
  name: "Health"
  confidence: 0.0239651408
}
moderation_categories {
  name: "Religion & Belief"
  confidence: 0.0125078177
}
moderation_categories {
  name: "Illicit Drugs"
  confidence: 0.0365853645
}
moderation_categories {
  name: "War & Conflict"
  confidence: 0.375
}
moderation_categories {
  name: "Politics"
  confidence: 0.00837988872
}
moderation_categories {
  name: "Finance"
  confidence: 0.0410958901
}
moderation_categories {
  name: "Legal"
  confidence: 0.09375
}
language_code: "ja"
language_supported: true
kun432kun432

ここまで見てきて、スクリプトで使用しているクライアントのバージョンが複数ある

from google.cloud import language_v2
from google.cloud import language_v1

最初はこれでv1モデル・v2モデルを使い分けるとかなのかな?と思ったけど、単純にREST APIのバージョンに合わせて用意してあるだけっぽい。

v1
https://cloud.google.com/python/docs/reference/language/latest/google.cloud.language_v1.services.language_service.LanguageServiceClient

v2
https://cloud.google.com/python/docs/reference/language/latest/google.cloud.language_v2.services.language_service.LanguageServiceClient

微妙に各機能のサポート状況が違ったり、オプションが違ってたりする、様子。

kun432kun432

レスポンスはそんなに早くない。どれも概ね1秒ぐらいに見えてる。

このスクラップは2ヶ月前にクローズされました
ログインするとコメントできます