LoginSignup
56
24

More than 3 years have passed since last update.

COTOHAでクイズ自動生成

Posted at

1.始めに

 モノにつられてQiitaデビュー笑。以前、NTTコミュニケーションズが提供する自然言語処理API・COTOHAを使ったクイズQAの自動生成を試みたのですが、このたび、Qiitaさんとのプレゼント企画が開かれたのでまんまとのっかります。という訳でニュース記事を活用したQAクイズの自動生成について書いていきます。

2.開発環境

*Google Colaboratory
*Python3
*COTOHA api(構文解析)

3.概要

 やりたいことは、例えば

フランスでマクロン政権に抗議する黄色いベスト運動のデモが18日、27週連続で行われた。内務省によると、……

のような記事があった場合に、「誰が」、「どこで」などの情報を上手く読み取ることができれば、

問題: マクロン政権に抗議する黄色いベスト運動のデモが18日、27週連続で行われたのはどこ?
答え: フランス

といった問題文と解答が自動で作れるんじゃというのがモチベーション。この「上手に」の部分をCOTOHAに担ってもらいます。

4.文章解析

 先ほどの例文記事をCOTOHAの構文解析に投げてみます。

curl -H "Content-Type:application/json;charset=UTF-8" -H "Authorization:Bearer **自身のToken**" -X POST -d '{"sentence":"フランスでマクロン政権に抗議する黄色いベスト運動のデモが18日、27週連続で行われた。"}' "https://api.ce-cotoha.com/api/dev/nlp/v1/parse"

レスポンスは、こんな感じ。しっかり形態素解析してくれて、「フランス」が「[ "固有", "地" ]」であることが抽出できています。

{
  "result" : [ {
    "chunk_info" : {
      "id" : 0,
      "head" : 8,
      "dep" : "D",
      "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" : 2,
      "dep" : "D",
      "chunk_head" : 1,
      "chunk_func" : 2,
      "links" : [ ]
    },
    "tokens" : [ {
      "id" : 2,
      "form" : "マクロン",
      "kana" : "マクロン",
      "lemma" : "マクロン",
      "pos" : "名詞",
      "features" : [ ],
      "attributes" : { }
    }, {
      "id" : 3,
      "form" : "政権",
      "kana" : "セイケン",
      "lemma" : "政権",
      "pos" : "名詞接尾辞",
      "features" : [ "名詞" ],
      "dependency_labels" : [ {
        "token_id" : 2,
        "label" : "compound"
      }, {
        "token_id" : 4,
        "label" : "case"
      } ],
      "attributes" : { }
    }, {
      "id" : 4,
      "form" : "に",
      "kana" : "ニ",
      "lemma" : "に",
      "pos" : "格助詞",
      "features" : [ "連用" ],
      "attributes" : { }
    } ]
  }

一方で、マクロンが人名っていうところまでは、現状では厳しいみたい。加えて、"chunk_info"という塊で、文節情報がとれているので(すげー!!)、ある文節に地名などが入っていれば、その文節(地名)を解答にするように元記事を書き換えれば、クイズっぽくなりそうです。

5.実装

今回は、地名と人の2パターンの入力に対応してみました。

import collections
import requests
import json

#入力文
sentence = 'フランスでマクロン政権に抗議する黄色いベスト運動のデモが18日、27週連続で行われた。'
url = 'https://api.ce-cotoha.com/api/dev/nlp/v1/parse'
headers = {'Content-Type':'application/json;charset=UTF-8','Authorization':'Bearer **Token**'}
payload={'sentence':sentence}

#COTOHAにリクエスト
r = requests.post(url, data=json.dumps(payload), headers=headers)

#構文解析結果を格納
data = r.json()
j = json.dumps(data["result"])
chunk_dic = json.loads(j, object_pairs_hook=collections.OrderedDict)

quiz_flug = 100
chunk_dic_len = len(chunk_dic)
token = ""

#文節ごとに人名や地名が含まれるか判定。見つかればクイズ候補にする
for i in range(chunk_dic_len):
    dic = chunk_dic[i]
    dic_len = len(dic["tokens"])
    for j in range(dic_len):
      if "名" in dic["tokens"][j]["features"] and "姓" in dic["tokens"][j]["features"] and "固有" in dic["tokens"][j]["features"]:
        #クイズの解答する
        key_word = dic["tokens"][j]["form"]
        #文節を元記事から抜き取るために使う変数 
        for s in range(dic_len):
          token = token + dic["tokens"][s]["form"]
        quiz_flug = "0"

      elif "地" in dic["tokens"][j]["features"] and "固有" in dic["tokens"][j]["features"]:
        key_word = dic["tokens"][j]["form"]
        for s in range(dic_len):
          token = token + dic["tokens"][s]["form"]
        quiz_flug = "1"

question_sentence = sentence[sentence.find(token):]
question_sentence = question_sentence.replace(token, '')

#抽出した名詞ごとにクイズ文を変える
if quiz_flug == "0":
  question_sentence = question_sentence[:-1] + "のは誰?"
elif quiz_flug == "1":
  question_sentence = question_sentence[:-1] + "のはどこ?"

print("問題:",question_sentence)
print("答え:",key_word)

実行結果

問題: マクロン政権に抗議する黄色いベスト運動のデモが18日、27週連続で行われたのはどこ?
答え: フランス

一応、狙ったものはできています。

6.テスト

色々な記事で実験。

・元記事①
###
#元モーニング娘。でタレント・プライベートでは“4児のママ”辻希美が17日、「辻ちゃんネル」を開設し、YouTubeデビューすることを発表した。"
###
問題: 17日、「辻ちゃんネル」を開設し、YouTubeデビューすることを発表したのは誰?
答え: 辻希美
・元記事②
###
#新型コロナウイルスへの感染が確認されたクルーズ船のアメリカ人乗客ら14人をそのままチャーター機で帰国させたことについて、トランプ大統領が、事前に知らされず、怒りをあらわにしたと有力紙が伝えた。
###
問題: 14人をそのままチャーター機で帰国させたことについて、トランプ大統領が、事前に知らされず、怒りをあらわにしたと有力紙が伝えたのはどこ?
答え: アメリカ
・元記事③
###
#戦国時代に織田信長が攻略した山城として知られる岐阜城について、岐阜市は7日、発掘調査で信長が築いたとみられる天守台(天守の土台)の石垣を初めて発見したと発表した。
###
問題: 7日、発掘調査で信長が築いたとみられる天守台(天守の土台)の石垣を初めて発見したと発表したのはどこ?
答え: 岐阜市

完璧な出力とは言いがたいですが、可能性を感じる結果になりました!もうちょっとルールも精査しながら、精度を高めていきたいと思います!!

7・引用

仏デモ半年、規模縮小(共同通信)
辻希美がYouTubeデビュー発表 ママ向け情報や美容情報など配信「私なりの経験を活かして」(オリコンニュース)
感染者帰国 事前報告なくトランプ氏が怒り(日本テレビ系(NNN))
信長が築いた特徴あり 岐阜城で初確認の天守土台の石垣(朝日新聞)

56
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
56
24