「メントスと囲碁の思い出」をCOTOHAさんに要約してもらった結果。COTOHA最速チュートリアル付き


# メントスと囲碁の思い出

メントスには深い思い入れがある。
当時あたしは囲碁同好会に参加しており、
碁石を弾いて相手の碁石を落とすという
「シューティング囲碁」に興じていた。
平安貴族も興じていたに違いない、
そのみやびな遊びを理解できない同好会会長は怒り狂った。
曰く、大切な碁石が割れるからやめろ、と。
碁石は割れたら直せない。
割れたら証拠隠滅のために食べてしまえばいい？
それならば、最初から「食べられる碁石」を採用してはどうか？
よく見ると「メントス」は碁石として最適な条件を兼ね揃えていた。
色、ツヤ、形、味、どれも通常の碁石より優れている。
専門店にいかなくても、コンビニで補充が出来る。
白と黒の淡泊な世界に飽きた際には、
色を変えることもできる。
唯一の問題は、夏の暑さに弱そうなところくらいであろう。
囲碁は、相手の石を取ることが出来る。
しかし、取ったからといって何が嬉しいのだろうか。
ちょっとゲームが有利になるだけだ。
メントスならばおいしく食べちゃってもいい。
囲碁を強くなろうという熱意も出てくるというもの。
あたしは同好会会長にこう直訴した。
碁石を全てメントスに変えよう！
いま、コンビニでメントスを見かけなくなったのは、
このあたしのアイデアでメントスの値段が高騰してしまったからである。
ああ、あたしのいとしいメントスよ、どこへいった！？

# 本投稿の内容

* ある日、詩想がわき「**メントスと囲碁の思い出**」というポエムが生まれた。
* **意味が分からない**、と言われてしまい悲しかった。
* ~~偉大なる芸術家は往々にして当時の人々には理解されないものだ。~~
* [【Qiita x COTOHA APIプレゼント企画】](https://zine.qiita.com/event/collaboration-cotoha-api/)で、**COTOHAには要約機能**があることを思いだした。
* そういえば[【今シンガポールLineBot】](https://qiita.com/youwht/items/014aa6e69657c5070593)の最後で、COTOHAを触ろうと思っていた。
* そうだ、このポエムをCOTOHAさんに読んでもらって要約してもらおう！（大迷惑）
* ついでに**COTOHAさんの主要機能を５秒で試せる最速チュートリアルコードを作成**
* COTOHAさんで誰でも簡単に自然言語処理が出来るようになったよ。（イマココ）

# COTOHAさんにポエムを読んでもらった結果

■ COTOHAさんによる要約結果：

ここから～

碁石を全てメントスに変えよう！
いま、コンビニでメントスを見かけなくなったのは、
このあたしのアイデアでメントスの値段が高騰してしまったからである。

～ここまで（改行は追加）

**COTOHAさんすごいっ！！（実感）**

# 要約機能以外にもCOTOHAには様々なAPIがある

**構文解析、固有表現抽出、照応解析、キーワード抽出、**
**類似度算出、文タイプ判定、ユーザ属性推定、感情分析、要約**
・・・などなど。

無料ユーザでも、各APIごとに**1000回/日**使えるそうだ。

試してみたいけど、リファレンスみながら作るのも面倒なんだよなー。
一瞬で全部動かせる＆内容を理解出来るサンプル無いかなー。
と、あたしが欲しかったのでまとめてみた。（後述に全コード記載）

**無料ユーザ登録後、[Colaboratory](https://colab.research.google.com/notebooks/welcome.ipynb) にアクセスして、**
**「ファイル」⇒「Python3の新しいノートブック」**
**⇒本稿のコードをコピペして実行 ⇒ これだけで主要API全てが分かる**

前提環境一切不要。ブラウザだけで実行できて、
すぐに使える＆応用開発が出来るサンプル。

Colaboratory（Googleの無料Python実行環境）を使わなくても、
Pythonがインストール済みの環境ならば、
下記のコードを１つのPythonファイルに書いて、
``python Mentos_Cotoha.py`` などと実行しても、
すぐ同じ結果が得られる。

ユーザ登録後、コピペだけで一瞬で試せるので、
ぜひお手元で試していただきたい。
[Qiitaとの企画でプレゼントやっている](https://zine.qiita.com/event/collaboration-cotoha-api/)ので触るなら**今がチャンス？**

さっそく無料ユーザ登録はこちらから。
[COTOHA API Portal](https://api.ce-cotoha.com/contents/index.html)

# COTOHA最速チュートリアルサンプルコード

Colaboratoryでも、ローカル環境でも、
どこでもコピペだけですぐ実行できるサンプルコード。
　（※ユーザIDとシークレットキーは自分で入力）
サンプルを試したあとは、
**API実行を扱いやすくするライブラリとして利用可能**。

参考： https://qiita.com/gossy5454/items/83072418fb0c5f3e269f

```py:Mentos_Cotoha.py
import os
import urllib.request
import json
import codecs

# 「自然言語処理を簡単に扱えると噂のCOTOHA APIをPythonで使ってみた」
# https://qiita.com/gossy5454/items/83072418fb0c5f3e269f
# 上記記事のコードをベースに、Colaboratoryですぐ動くように改変。
# また、同じ処理を共通化してコード全体を短くし
# 複数のAPIのサンプルコードも追加した。
# 本改変後コードの詳細は下記参照。
# https://qiita.com/youwht/items/16e67f4ada666e679875

# COTOHA API操作用クラス
class CotohaApi:
  # 初期化
  def __init__(self, client_id, client_secret, developer_api_base_url, access_token_publish_url):
    self.client_id = client_id
    self.client_secret = client_secret
    self.developer_api_base_url = developer_api_base_url
    self.access_token_publish_url = access_token_publish_url
    self.getAccessToken()
  
  # アクセストークン取得
  def getAccessToken(self):
    # アクセストークン取得URL指定
    url = self.access_token_publish_url
    # ヘッダ指定
    headers={
      "Content-Type": "application/json;charset=UTF-8"
    }
    # リクエストボディ指定
    data = {
      "grantType": "client_credentials",
      "clientId": self.client_id,
      "clientSecret": self.client_secret
    }
    # リクエストボディ指定をJSONにエンコード
    data = json.dumps(data).encode()
    # リクエスト生成
    req = urllib.request.Request(url, data, headers)
    # リクエストを送信し、レスポンスを受信
    res = urllib.request.urlopen(req)
    # レスポンスボディ取得
    res_body = res.read()
    # レスポンスボディをJSONからデコード
    res_body = json.loads(res_body)
    # レスポンスボディからアクセストークンを取得
    self.access_token = res_body["access_token"]
  
  #各APIの共通処理
  def callCotohaApiCommon(self, url, data):
    # ヘッダ指定
    headers={
      "Authorization": "Bearer " + self.access_token,
      "Content-Type": "application/json;charset=UTF-8",
    }
    # リクエストボディ指定をJSONにエンコード
    data = json.dumps(data).encode()
    # リクエスト生成
    req = urllib.request.Request(url, data, headers)
    # リクエストを送信し、レスポンスを受信
    # 以下、リクエストエラー時のリトライ処理を入れたが、
    # 長時間放置後に再実行、などが無ければ消しても良い。
    # リトライカウントを設定
    CONNECTION_RETRY_COUNT = 2
    for counter in range(1, CONNECTION_RETRY_COUNT + 1):
      try:
        res = urllib.request.urlopen(req)
        #exceptionに行かなければループ終了
        break
      # リクエストでエラーが発生した場合の処理
      except urllib.request.HTTPError as e:
        # ステータスコードが401 Unauthorizedならアクセストークンを取得し直して再リクエスト
        if e.code == 401:
          print ("[RETRY] get access token")
          self.access_token = getAccessToken(self.client_id, self.client_secret)
          headers["Authorization"] = "Bearer " + self.access_token
          req = urllib.request.Request(url, data, headers)
        # 401以外のエラーなら原因を表示して処理自体を終了。空白を返す。
        else:
          print ("<Error> " + e.reason)
          return ""
      # それ以外のエラーは不明なので終了。
      # サーバ系のエラーの場合、だいたいURLか引数を見直すと良い
      except Exception as e:
        print(e)
        return ""
    # レスポンスボディ取得
    res_body = res.read()
    # レスポンスボディをJSONからデコード
    res_body = json.loads(res_body)
    # レスポンスボディから解析結果を取得
    return res_body

  # 構文解析API
  def callParseApi(self, sentence):
    url = self.developer_api_base_url + "nlp/v1/parse"
    data = {
        "sentence": sentence
    }
    return self.callCotohaApiCommon(url, data)
  
  # 固有表現抽出API
  def callNeApi(self, sentence):
    url = self.developer_api_base_url + "nlp/v1/ne"
    data = {
        "sentence": sentence
    }
    return self.callCotohaApiCommon(url, data)
  
  # 照応解析API
  # document は string / array(string) なので文でも、文のリストでも良い
  # ほかのdocument箇所も同様
  def callCoreferenceApi(self, document):
    url = self.developer_api_base_url + "nlp/v1/coreference"  
    data = {
      "document": document
    }
    return self.callCotohaApiCommon(url, data)

  # キーワード抽出API
  def callKeywordApi(self, document):
    url = self.developer_api_base_url + "nlp/v1/keyword"
    data = {
      "document": document
    }
    return self.callCotohaApiCommon(url, data)

  # 類似度算出API
  def callSimilarityApi(self, sentence1, sentence2):
    url = self.developer_api_base_url + "nlp/v1/similarity"
    data = {
      "s1": sentence1,
      "s2": sentence2
    }
    return self.callCotohaApiCommon(url, data)

  # 文タイプ判定API
  def callSentenceTypeApi(self, sentence):
    url = self.developer_api_base_url + "nlp/v1/sentence_type"
    data = {
      "sentence": sentence
    }
    return self.callCotohaApiCommon(url, data)

  # ユーザ属性推定API
  def callUserAttributeApi(self, document):
    url = self.developer_api_base_url + "nlp/beta/user_attribute"
    data = {
      "document": document
    }
    return self.callCotohaApiCommon(url, data)

  # 感情分析API
  def callSentimentApi(self, sentence):
    url = self.developer_api_base_url + "nlp/v1/sentiment"
    data = {
      "sentence": sentence
    }
    return self.callCotohaApiCommon(url, data)

  # 要約API
  # sentenceのサイズは、5～5000
  # sent_lenのサイズは、1～100
  def callSummaryApi(self, sentence, sent_len):
    url = self.developer_api_base_url + "nlp/beta/summary"
    data = {
      "document": sentence,
      "sent_len": sent_len
    }
    return self.callCotohaApiCommon(url, data)
  
  #上記以外のAPIや、各APIのオプションを追加/変更するのも同様にやればOK

if __name__ == '__main__':
  #####各自の設定を記入する箇所#####
  #登録完了直後のページに書いてあるよ
  CLIENT_ID     = "ココニアイデイカク"
  CLIENT_SECRET = "ココニシークレットカク"
  #BASE_URLは、公式ページでは、末尾にnlpを含めていないけど、
  #少し前の技術記事だと、末尾にnlpも含めている人も多いから気を付けてね
  DEVELOPER_API_BASE_URL   = "https://api.ce-cotoha.com/api/dev/"
  ACCESS_TOKEN_PUBLISH_URL = "https://api.ce-cotoha.com/v1/oauth/accesstokens"

  #####以下使用例#####
  # 各APIのコール方法や、レスポンスの解析の詳細はリファレンスを見るといいよ。
  # https://api.ce-cotoha.com/contents/reference/apireference.html

  # COTOHA APIインスタンス生成
  cotoha_api = CotohaApi(CLIENT_ID, CLIENT_SECRET, DEVELOPER_API_BASE_URL, ACCESS_TOKEN_PUBLISH_URL)

  print("■ 構文解析")
  sentence = "すもももももももものうち"
  api_result  = cotoha_api.callParseApi(sentence)
  for chunks in api_result['result']:
    print(chunks)

  print("■ 固有表現抽出")
  sentence = "私は今日母と東京タワーでメントスを食べた"
  api_result  = cotoha_api.callNeApi(sentence)
  for chunks in api_result['result']:
    print(chunks)
  
  print("■ 照応解析")
  document = ["太郎は友人です","彼のおじいさんがくれた初めてのキャンディ","それはメントスで私は四歳でした"]
  api_result  = cotoha_api.callCoreferenceApi(document)
  for chunks in api_result['result']['coreference']:
    print(chunks['referents'])

  print("■ キーワード抽出")
  document = ["ペットボトルに入ったダイエットコーラの中にメントス数粒を一度に投入した際に急激に炭酸が気化し、泡が一気に数mの高さまで吹き上がる現象をメントスガイザーと呼ぶ"]
  api_result  = cotoha_api.callKeywordApi(document)
  for chunks in api_result['result']:
    print(chunks)

  print("■ 類似度算出")
  sentence1 = "メントスはおいしい"
  sentence2 = "ラーメンも大好きです"
  api_result  = cotoha_api.callSimilarityApi(sentence1, sentence2)
  print(api_result['result']['score'])

  print("■ 文タイプ判定")
  sentence = "質問を質問で返すんじゃない"
  api_result  = cotoha_api.callSentenceTypeApi(sentence)
  print(api_result['result']['modality'])
  #declarative（叙述）
  #interrogative（質問）
  #imperative（命令）

  print("■ ユーザ属性推定")
  document = ["やめられないとまらない","君が泣くまで殴るのをやめない"]
  api_result  = cotoha_api.callUserAttributeApi(document)
  print('結果 ＝ {}'.format(api_result['result']) )

  print("■ 感情分析")
  sentence = "その味は甘くてクリーミィでこんな素晴らしいメントスをもらえる私はきっと特別な存在なのだと感じました"
  api_result  = cotoha_api.callSentimentApi(sentence)
  #他のAPIの結果についても、各結果をjsonのまま見たい場合は下記のようにする。
  result_formated = json.dumps(api_result, indent=4, separators=(',', ': '))
  print (codecs.decode(result_formated, 'unicode-escape'))

  print("■ 要約")
  sentence='''タイトル：メントスと囲碁の思い出
メントスには深い思い入れがある。
当時あたしは囲碁同好会に参加しており、
碁石を弾いて相手の碁石を落とすという
「シューティング囲碁」に興じていた。
平安貴族も興じていたに違いない、
そのみやびな遊びを理解できない同好会会長は怒り狂った。
曰く、大切な碁石が割れるからやめろ、と。
碁石は割れたら直せない。
割れたら証拠隠滅のために食べてしまえばいい？
それならば、最初から「食べられる碁石」を採用してはどうか？
よく見ると「メントス」は碁石として最適な条件を兼ね揃えていた。
色、ツヤ、形、味、どれも通常の碁石より優れている。
専門店にいかなくても、コンビニで補充が出来る。
白と黒の淡泊な世界に飽きた際には、
色を変えることもできる。
唯一の問題は、夏の暑さに弱そうなところくらいであろう。
囲碁は、相手の石を取ることが出来る。
しかし、取ったからといって何が嬉しいのだろうか。
ちょっとゲームが有利になるだけだ。
メントスならばおいしく食べちゃってもいい。
囲碁を強くなろうという熱意も出てくるというもの。
あたしは同好会会長にこう直訴した。
碁石を全てメントスに変えよう！
いま、コンビニでメントスを見かけなくなったのは、
このあたしのアイデアでメントスの値段が高騰してしまったからである。
ああ、あたしのいとしいメントスよ、どこへいった！？
'''
  api_result  = cotoha_api.callSummaryApi(sentence, 1)
  print('結果 ＝ {}'.format(api_result['result']) )
  # Mentos(メントス)は商標または登録商標です。

```


```py:実行結果
■ 構文解析
{'chunk_info': {'id': 0, 'head': 1, 'dep': 'P', 'chunk_head': 0, 'chunk_func': 1, 'links': []}, 'tokens': [{'id': 0, 'form': 'すもも', 'kana': 'スモモ', 'lemma': '李', 'pos': '名詞', 'features': [], 'dependency_labels': [{'token_id': 1, 'label': 'case'}], 'attributes': {}}, {'id': 1, 'form': 'も', 'kana': 'モ', 'lemma': 'も', 'pos': '連用助詞', 'features': [], 'attributes': {}}]}
{'chunk_info': {'id': 1, 'head': 3, 'dep': 'D', 'chunk_head': 0, 'chunk_func': 1, 'links': [{'link': 0, 'label': 'other'}]}, 'tokens': [{'id': 2, 'form': 'もも', 'kana': 'モモ', 'lemma': '桃', 'pos': '名詞', 'features': [], 'dependency_labels': [{'token_id': 0, 'label': 'nmod'}, {'token_id': 3, 'label': 'case'}], 'attributes': {}}, {'id': 3, 'form': 'も', 'kana': 'モ', 'lemma': 'も', 'pos': '連用助詞', 'features': [], 'attributes': {}}]}
{'chunk_info': {'id': 2, 'head': 3, 'dep': 'D', 'chunk_head': 0, 'chunk_func': 1, 'links': []}, 'tokens': [{'id': 4, 'form': 'もも', 'kana': 'モモ', 'lemma': '桃', 'pos': '名詞', 'features': [], 'dependency_labels': [{'token_id': 5, 'label': 'case'}], 'attributes': {}}, {'id': 5, 'form': 'の', 'kana': 'ノ', 'lemma': 'の', 'pos': '格助詞', 'features': ['連体'], 'attributes': {}}]}
{'chunk_info': {'id': 3, 'head': -1, 'dep': 'O', 'chunk_head': 0, 'chunk_func': 0, 'links': [{'link': 1, 'label': 'other'}, {'link': 2, 'label': 'adjectivals'}]}, 'tokens': [{'id': 6, 'form': 'うち', 'kana': 'ウチ', 'lemma': '内', 'pos': '名詞', 'features': ['連用'], 'dependency_labels': [{'token_id': 2, 'label': 'nmod'}, {'token_id': 4, 'label': 'nmod'}], 'attributes': {}}]}
■ 固有表現抽出
{'begin_pos': 2, 'end_pos': 4, 'form': '今日', 'std_form': '今日', 'class': 'DAT', 'extended_class': '', 'source': 'basic'}
{'begin_pos': 6, 'end_pos': 11, 'form': '東京タワー', 'std_form': '東京タワー', 'class': 'ART', 'extended_class': '', 'source': 'basic'}
■ 照応解析
[{'referent_id': 0, 'sentence_id': 0, 'token_id_from': 0, 'token_id_to': 0, 'form': '太郎'}, {'referent_id': 1, 'sentence_id': 1, 'token_id_from': 0, 'token_id_to': 0, 'form': '彼'}]
[{'referent_id': 0, 'sentence_id': 1, 'token_id_from': 0, 'token_id_to': 2, 'form': '彼のおじいさん'}, {'referent_id': 1, 'sentence_id': 2, 'token_id_from': 0, 'token_id_to': 0, 'form': 'それ'}]
■ キーワード抽出
{'form': '投入', 'score': 18.75872}
{'form': '気化', 'score': 11.889}
{'form': '泡', 'score': 10.9335}
{'form': 'ペットボトル', 'score': 10.38192}
{'form': '急激', 'score': 10.2795}
■ 類似度算出
0.71831065
■ 文タイプ判定
declarative
■ ユーザ属性推定
結果 ＝ {'age': '20-29歳', 'earnings': '-1M', 'hobby': ['MOVIE', 'SHOPPING'], 'location': '関東', 'moving': ['RAILWAY'], 'occupation': '会社員'}
■ 感情分析
{
    "result": {
        "sentiment": "Positive",
        "score": 0.740555365045455,
        "emotional_phrase": [
            {
                "form": "素晴らしい",
                "emotion": "P"
            },
            {
                "form": "甘くて",
                "emotion": "PN"
            },
            {
                "form": "もらえる",
                "emotion": "P"
            },
            {
                "form": "きっと特別な",
                "emotion": "PN"
            }
        ]
    },
    "status": 0,
    "message": "OK"
}
■ 要約
結果 ＝ 碁石を全てメントスに変えよう！いま、コンビニでメントスを見かけなくなったのは、このあたしのアイデアでメントスの値段が高騰してしまったからである。
```

# オーラをメントスに変える念能力

記事を書いているうちに、
あたしもメントスが具現化出来るようになってきたかもしれない。

> まずメントスを具現化しようと決めてからはイメージ修行だな。
> 最初は実際のメントスを一日中いじくってたな。とにかく四六時中だよ。
> 目をつぶって触感を確認したり何百枚何千枚とメントスを写生したり、
> ずーっとただながめてみたりなめてみたり、音を立てたり嗅いでみたり、
> メントスで遊ぶ以外は何もするなと師匠に言われたからな。
> しばらくしたら毎晩メントスの夢を見るようになって
> その時点で実際のメントスをとりあげられた。
> そうすると今度は幻覚でメントスが見えてくるんだ。
> さらに日が経つと幻覚のメントスがリアルに感じられるんだ。
> 重さも冷たさもすれあう音も聞こえてくる。
> いつのまにか幻覚じゃなく、自然と具現化したメントスが出ていたんだ。
> それ以外はおそらくゴン達と同じだよ。とにかく毎日毎日纏と練だ。

~~ゴレイヌのゴリラの具現化修行よりはマシ~~

ヒトコト or フタコトで言うと・・・

```py:Mentosの具現化
sentence='''まずメントスを具現化しようと決めてからはイメージ修行だな。
最初は実際のメントスを一日中いじくってたな。とにかく四六時中だよ。
目をつぶって触感を確認したり何百枚何千枚とメントスを写生したり、
ずーっとただながめてみたりなめてみたり、音を立てたり嗅いでみたり、
メントスで遊ぶ以外は何もするなと師匠に言われたからな。
しばらくしたら毎晩メントスの夢を見るようになって
その時点で実際のメントスをとりあげられた。
そうすると今度は幻覚でメントスが見えてくるんだ。
さらに日が経つと幻覚のメントスがリアルに感じられるんだ。
重さも冷たさもすれあう音も聞こえてくる。
いつのまにか幻覚じゃなく、自然と具現化したメントスが出ていたんだ。
それ以外はおそらくゴン達と同じだよ。とにかく毎日毎日纏と練だ。
'''
api_result  = cotoha_api.callSummaryApi(sentence, 1)
print('結果 ＝ {}'.format(api_result['result']) )

api_result  = cotoha_api.callSummaryApi(sentence, 2)
print('結果 ＝ {}'.format(api_result['result']) )
```

```py:実行結果
結果 ＝ いつのまにか幻覚じゃなく、自然と具現化したメントスが出ていたんだ。
結果 ＝ 最初は実際のメントスを一日中いじくってたな。いつのまにか幻覚じゃなく、自然と具現化したメントスが出ていたんだ。
```

# 参考リンク

◇構文解析・照応解析のデモ
https://api.ce-cotoha.com/demo?query=いつのまにか幻覚じゃなく、自然と具現化したメントスが出ていたんだ
◇APIのリファレンス
https://api.ce-cotoha.com/contents/reference/apireference.html
◇コトハ イチバン ユウメイ キジ スゴイ
https://qiita.com/Harusugi/items/f499e8707b36d0f570c4
◇COTOHA APIポータル（無料登録はこちらから）
https://api.ce-cotoha.com/contents/index.html
◇COTOHAのコミュニティ、Slack等へのリンク
https://api.ce-cotoha.com/contents/community.html


# あとがき

"しゃべりすぎた翌朝 落ち込むことの方が多い"

見てごらん よく似ているだろう

ポエムを書いた次の日の朝と。

あたしは紙をくしゃくしゃと丸めて投げ、

メントスをほおばるのだった。

了。