20200227のNode.jsに関する記事は7件です。

Microsoft Teamsで使えるQualityForward Botを作る

Microsoft TeamsはMicrosoftの提供するチャットツールです。ビジネス界隈で利用が広がっています。他のチャットサービスと同様に、他社のサービスと簡単に連携できます。今回はMicrosoft Teamsと連携できるQualityForward用ボットを作成してみました。

利用するAPIについて

Microsoft Teamsのボットは5秒以内にレスポンスを返さないといけないという縛りがあります。Web APIを何度も叩いていると5秒以内にレスポンスが返せない可能性があるので、以前作成したGoogle Apps Script上で動作するWeb APIを利用します。

QualityForwardのテスト集計を返すSlackコマンドを作ってみた - Qiita

このWeb APIであればGoogle Apps Scriptを呼び出すだけなので処理は高速になります。ただし、Google Apps Scriptのリダイレクトする仕組みではMicrosoft Teamsのボットがうまくレスポンスを受け取れませんでした。そのため、直接Google Apps Scriptを呼び出すのではなく、Node.jsサーバ(今回はGlitchを利用)から呼び出す方式にしています。

ボットについて

Microsoft Teamsのボットは簡単に作成できます。今回はWebhookを利用しています。Webhookはあらかじめ作成したボットに対してメッセージを送ると、指定したURLへPOSTメソッドを投げてくれます。レスポンスで返したJSONをボットからの返信として表示してくれます。

Screenshot_ 2020-02-27 9.41.27.png

コードについて

Node.js(Express利用)のコードは次のようになります。Google Apps Script上で作成しているAPIを実行し、そのレスポンスを返しているだけです。

const express = require("express");
const app = express();
// POSTのボディ解析用
app.use(express.json())
app.use(express.urlencoded({ extended: true }));

// HTTPクライアントw追加
const client = require('superagent');

app.use(express.static("public"));
app.get("/", (request, response) => {
  response.sendFile(__dirname + "/views/index.html");
});

// ボットからデータを受け取る処理
app.post("/post", async (request, response) => {
  // メッセージ内にある日付部分を取得
  const date = request.body.text.replace(/^.*?<\/at>(.*)\n.*/s, "$1");
  // Google Apps ScriptのAPIを呼び出し
  const url = `https://script.google.com/macros/s/AKf...IGt/exec?text=${date}`;
  const res = await client.get(url)
  // レスポンスを返す
  response.json({
    "type": "message",
    "text": res.text
  });
});

const listener = app.listen(process.env.PORT, () => {
  console.log("Your app is listening on port " + listener.address().port);
});

これでボットに対して日付を送ると、その日付における処理件数を返してくれるようになりました。

Screenshot_ 2020-02-27 10.31.26.png

まとめ

今回の仕組みは自前のサーバを立てることなく、サーバレスで構築しています。GlitchもGoogle Apps Scriptも安定していますので、メンテナンス不要で動作できる仕組みは便利です。Microsoft Teamsで情報共有しているプロジェクトでは、この仕組みを試してみてください。

QualityForward

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AIに歌を聞かせた。そした彼は笑顔?になった。(COTOHA-情分析API)

概要

歌を聞かせた。
彼はその歌を聴き、
Positiveな感情になると笑い?、
Negativeな感情になると怒り?、
Neutralな感情になると。。。?

COTOHA感情分析APIを使って、歌の歌詞からどのような感情をくみ取るのかを試した。COTOHA API for Developersに登録してすぐに、感情分析APIを試せるようWEBアプリも作った。)

結果

とりあえず歴代CDシングル売り上げ枚数ランキングを聞かせた。
「1位から順に!カウントアップ!?」

1.(457.7万枚)およげ!たいやきくん

?
"sentiment": "Negative"
"score": 0.5

Response
{
  "result": {
    "sentiment": "Negative",
    "score": 0.5,
    "emotional_phrase": [
      {
        "form": "こころがはずむ",
        "emotion": "喜ぶ"
      },
      {
        "form": "たのしい",
        "emotion": "P"
      },
      {
        "form": "おもい",
        "emotion": "N"
      },
      {
        "form": "ひろいぜ",
        "emotion": "PN"
      },
      {
        "form": "いじめられる",
        "emotion": "N"
      },
      {
        "form": "もがいて",
        "emotion": "N"
      },
      {
        "form": "こげある",
        "emotion": "N"
      },
      {
        "form": "うまそう",
        "emotion": "P"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

2.(325.6万枚)女のみち

?
"sentiment": "Negative"
"score": 0.2011977885862898

Response
{
  "result": {
    "sentiment": "Negative",
    "score": 0.2011977885862898,
    "emotional_phrase": [
      {
        "form": "みちならば暗い",
        "emotion": "N"
      },
      {
        "form": "恋",
        "emotion": "好ましい,切ない"
      },
      {
        "form": "幸せ",
        "emotion": "P"
      },
      {
        "form": "つらい",
        "emotion": "N"
      },
      {
        "form": "泣",
        "emotion": "喜ぶ,悲しい,切ない"
      },
      {
        "form": "すがって泣いたうぶな",
        "emotion": "PN"
      },
      {
        "form": "いけない",
        "emotion": "N"
      },
      {
        "form": "みちならば",
        "emotion": "PN"
      },
      {
        "form": "捨てた",
        "emotion": "N"
      },
      {
        "form": "いじめる",
        "emotion": "N"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

3.(313.2万枚)世界に一つだけの花

?
"sentiment": "Positive"
"score": 0.08995079776388203

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.08995079776388203,
    "emotional_phrase": [
      {
        "form": "うれしそうな",
        "emotion": "P"
      },
      {
        "form": "笑顔",
        "emotion": "安心"
      },
      {
        "form": "好み",
        "emotion": "好ましい"
      },
      {
        "form": "困った",
        "emotion": "N"
      },
      {
        "form": "迷",
        "emotion": "不安"
      },
      {
        "form": "笑い",
        "emotion": "喜ぶ"
      },
      {
        "form": "もともと特別な",
        "emotion": "PN"
      },
      {
        "form": "ひとそれぞれ",
        "emotion": "PN"
      },
      {
        "form": "きれいだ",
        "emotion": "P"
      },
      {
        "form": "争う",
        "emotion": "N"
      },
      {
        "form": "誇らしげ",
        "emotion": "P"
      },
      {
        "form": "咲かせる",
        "emotion": "P"
      },
      {
        "form": "一生懸命",
        "emotion": "PN"
      },
      {
        "form": "頑張って",
        "emotion": "P"
      },
      {
        "form": "仕方ないね",
        "emotion": "N"
      },
      {
        "form": "色とりどり",
        "emotion": "P"
      },
      {
        "form": "気づかない",
        "emotion": "N"
      },
      {
        "form": "小さい",
        "emotion": "PN"
      },
      {
        "form": "同じものはない",
        "emotion": "PN"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

4.(293.6万枚)TSUNAMI

?
"sentiment": "Negative"
"score": 0.10121480950551423

Response
{
  "result": {
    "sentiment": "Negative",
    "score": 0.10121480950551423,
    "emotional_phrase": [
      {
        "form": "愛",
        "emotion": "安心,好ましい"
      },
      {
        "form": "愛しい",
        "emotion": "P"
      },
      {
        "form": "怯えてる",
        "emotion": "不安"
      },
      {
        "form": "悲しみ",
        "emotion": "悲しい"
      },
      {
        "form": "恋",
        "emotion": "好ましい,切ない"
      },
      {
        "form": "好きな",
        "emotion": "P"
      },
      {
        "form": "戸惑う",
        "emotion": "N"
      },
      {
        "form": "泣いた",
        "emotion": "N"
      },
      {
        "form": "涙",
        "emotion": "喜ぶ,不安,悲しい,切ない"
      },
      {
        "form": "微笑",
        "emotion": "安心"
      },
      {
        "form": "弱気な",
        "emotion": "N"
      },
      {
        "form": "すがる",
        "emotion": "N"
      },
      {
        "form": "涙もろい",
        "emotion": "PN"
      },
      {
        "form": "清か",
        "emotion": "P"
      },
      {
        "form": "魔性",
        "emotion": "N"
      },
      {
        "form": "彷徨う",
        "emotion": "N"
      },
      {
        "form": "枯れる",
        "emotion": "N"
      },
      {
        "form": "素直に",
        "emotion": "P"
      },
      {
        "form": "侘しさ",
        "emotion": "PN"
      },
      {
        "form": "鏡のような",
        "emotion": "P"
      },
      {
        "form": "深い",
        "emotion": "PN"
      },
      {
        "form": "気付いてる",
        "emotion": "P"
      },
      {
        "form": "張り裂けそうな",
        "emotion": "N"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

5.(291.8万枚)だんご3兄弟

?
"sentiment": "Negative"
"score": 0.06456371454543736

Response
{
  "result": {
    "sentiment": "Negative",
    "score": 0.06456371454543736,
    "emotional_phrase": [
      {
        "form": "かたくな",
        "emotion": "不安"
      },
      {
        "form": "ささって",
        "emotion": "P"
      },
      {
        "form": "まれ",
        "emotion": "PN"
      },
      {
        "form": "たくさん",
        "emotion": "PN"
      },
      {
        "form": "こげ",
        "emotion": "N"
      },
      {
        "form": "かたくなりました",
        "emotion": "PN"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

6.(289.5万枚)君がいるだけで

?
"sentiment": "Positive"
"score": 0.009547567550434202

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.009547567550434202,
    "emotional_phrase": [
      {
        "form": "憧れ",
        "emotion": "P"
      },
      {
        "form": "笑顔",
        "emotion": "安心"
      },
      {
        "form": "くやしい",
        "emotion": "N"
      },
      {
        "form": "何より大切な",
        "emotion": "P"
      },
      {
        "form": "涙",
        "emotion": "喜ぶ,切ない,不安,悲しい"
      },
      {
        "form": "儚い",
        "emotion": "PN"
      },
      {
        "form": "強く",
        "emotion": "PN"
      },
      {
        "form": "気付かせてくれたね",
        "emotion": "P"
      },
      {
        "form": "ありがちな",
        "emotion": "PN"
      },
      {
        "form": "つい引き込まれ",
        "emotion": "P"
      },
      {
        "form": "弱さ",
        "emotion": "N"
      },
      {
        "form": "忘れてた",
        "emotion": "PN"
      },
      {
        "form": "もっと素直になれなかった",
        "emotion": "N"
      },
      {
        "form": "わかって",
        "emotion": "P"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

7.(282.2万枚)SAY YES

?
"sentiment": "Negative"
"score": 0.2490204168421342

Response
{
  "result": {
    "sentiment": "Negative",
    "score": 0.2490204168421342,
    "emotional_phrase": [
      {
        "form": "愛",
        "emotion": "好ましい,安心"
      },
      {
        "form": "愛してる",
        "emotion": "P"
      },
      {
        "form": "恋",
        "emotion": "好ましい,切ない"
      },
      {
        "form": "寂しい",
        "emotion": "N"
      },
      {
        "form": "切なさ",
        "emotion": "PN"
      },
      {
        "form": "迷",
        "emotion": "不安"
      },
      {
        "form": "ワガママ",
        "emotion": "N"
      },
      {
        "form": "余計な",
        "emotion": "N"
      },
      {
        "form": "何げなく暮らさない",
        "emotion": "PN"
      },
      {
        "form": "あふれてる",
        "emotion": "N"
      },
      {
        "form": "勝てない",
        "emotion": "N"
      },
      {
        "form": "消えない",
        "emotion": "P"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

8.(276.6万枚)Tomorrow never knows

?
"sentiment": "Positive"
"score": 0.007165278534051281

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.007165278534051281,
    "emotional_phrase": [
      {
        "form": "愛した",
        "emotion": "P"
      },
      {
        "form": "悲しい",
        "emotion": "N"
      },
      {
        "form": "孤独な",
        "emotion": "PN"
      },
      {
        "form": "寂しい",
        "emotion": "N"
      },
      {
        "form": "愛される喜び",
        "emotion": "P"
      },
      {
        "form": "消えた帰らぬ",
        "emotion": "P"
      },
      {
        "form": "すれ違う",
        "emotion": "N"
      },
      {
        "form": "無邪気に",
        "emotion": "P"
      },
      {
        "form": "裏切れる",
        "emotion": "N"
      },
      {
        "form": "欲しがっていた",
        "emotion": "P"
      },
      {
        "form": "分かり合えた",
        "emotion": "P"
      },
      {
        "form": "夢中で駆け抜ける",
        "emotion": "P"
      },
      {
        "form": "勝利",
        "emotion": "P"
      },
      {
        "form": "敗北もない",
        "emotion": "P"
      },
      {
        "form": "忘れてゆく",
        "emotion": "PN"
      },
      {
        "form": "避けて通れない",
        "emotion": "P"
      },
      {
        "form": "果てしない",
        "emotion": "P"
      },
      {
        "form": "優しさ",
        "emotion": "P"
      },
      {
        "form": "長い",
        "emotion": "PN"
      },
      {
        "form": "癒える",
        "emotion": "P"
      },
      {
        "form": "少し",
        "emotion": "PN"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

9.(258.8万枚)ラブ・ストーリーは突然に

?
"sentiment": "Positive"
"score": 0.060429544970368884

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.060429544970368884,
    "emotional_phrase": [
      {
        "form": "もっと好き",
        "emotion": "P"
      },
      {
        "form": "もう心揺れたりしないで切ない",
        "emotion": "PN"
      },
      {
        "form": "揺れたり",
        "emotion": "興奮"
      },
      {
        "form": "いい",
        "emotion": "P"
      },
      {
        "form": "分からない",
        "emotion": "N"
      },
      {
        "form": "消えてゆく",
        "emotion": "N"
      },
      {
        "form": "あんまりすてきだ",
        "emotion": "P"
      },
      {
        "form": "甘く",
        "emotion": "PN"
      },
      {
        "form": "やわらかく",
        "emotion": "PN"
      },
      {
        "form": "心が動いた",
        "emotion": "P"
      },
      {
        "form": "忘れない",
        "emotion": "PN"
      },
      {
        "form": "心揺れたりしないで",
        "emotion": "PN"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

10.(248.9万枚)LOVE LOVE LOVE

?
"sentiment": "Positive"
"score": 0.24542462771149284

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.24542462771149284,
    "emotional_phrase": [
      {
        "form": "愛",
        "emotion": "安心,好ましい"
      },
      {
        "form": "愛してる",
        "emotion": "P"
      },
      {
        "form": "すごく好きな",
        "emotion": "P"
      },
      {
        "form": "涙",
        "emotion": "喜ぶ,切ない,不安,悲しい"
      },
      {
        "form": "すっごく",
        "emotion": "PN"
      },
      {
        "form": "うまく",
        "emotion": "P"
      },
      {
        "form": "願う",
        "emotion": "P"
      },
      {
        "form": "少しずつ思い出になって",
        "emotion": "P"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

番外編(何となく気になった曲)

大きなのっぽの古時計

?
"sentiment": "Positive"
"score": 0.30601098537139876

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.30601098537139876,
    "emotional_phrase": [
      {
        "form": "うれしい",
        "emotion": "P"
      },
      {
        "form": "かなしい",
        "emotion": "N"
      },
      {
        "form": "のっぽの",
        "emotion": "PN"
      },
      {
        "form": "ごじまんの",
        "emotion": "PN"
      },
      {
        "form": "きれいな",
        "emotion": "P"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

千の風になって

?
"sentiment": "Positive"
"score": 0.14780720679775194,

Response
{
  "result": {
    "sentiment": "Positive"
    "score": 0.14780720679775194,
    "emotional_phrase": [
      {
        "form": "泣かないでください",
        "emotion": "P"
      },
      {
        "form": "きらめく",
        "emotion": "P"
      },
      {
        "form": "見守る",
        "emotion": "P"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

パプリカ

?
"sentiment": "Positive"
"score": 0.01385186275421083

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.01385186275421083,
    "emotional_phrase": [
      {
        "form": "泣いてた",
        "emotion": "N"
      },
      {
        "form": "喜び",
        "emotion": "P"
      },
      {
        "form": "晴れた",
        "emotion": "P"
      },
      {
        "form": "燻り",
        "emotion": "N"
      },
      {
        "form": "慰める",
        "emotion": "P"
      },
      {
        "form": "まれ",
        "emotion": "PN"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

WEBアプリ化

COTOHA API for Developersに登録した人限定ではあるが、同じ遊びが出来るようにした。(簡単に登録可)
以下URLで遊ぶには、登録後に取得できる、Client IDClient secretが必要。
https://cotoha-demo.now.sh/

2020-02-26_17h32_04.png

Client IDClient secretは、画面リフレッシュのたびに入力しなおすのは面倒。なので、ブラウザのlocalstrageにて情報を保持している。

技術

サービス化に伴い、以下の技術を使用。

  • Nuxt.js【JavaScript framework】
  • ant-design-vue【Css framework】
  • Now【Deploy】
  • Express【API】

server.js
server.js
const express = require('express')
const request = require('request')
const app = express()

// server
const port = process.env.PORT || 5000
app.listen(port, err => {
    if (err) throw err
    console.log(`> Ready On Server http://localhost:${port}`)
})

// API
app.get('/getToken', function(req, res, next) {
    (() => {
        return new Promise(r => {
            if (req.query.ClientID && req.query.Clientsecret && req.query.AccessTokenPublishURL){
                const AccessTokenPublishURL = req.query.AccessTokenPublishURL
                const ClientID = req.query.ClientID
                const Clientsecret = req.query.Clientsecret
                const headers = {
                    'Content-Type': 'application/json'
                }
                const data = {
                    'grantType': 'client_credentials',
                    'clientId': ClientID,
                    'clientSecret': Clientsecret
                }
                const options = {
                    url: AccessTokenPublishURL,
                    method: 'POST',
                    headers: headers,
                    json: data
                }
                request(options, (error, response, body) => {
                    return r(body)
                })
            }else{
                r('Parameter is incorrect')
            }
        })
    })().then(data => {
        res.send(data)
    }).catch(error => {
        res.send(error)
      })
})

app.get('/cotohaApiSimilarity', function(req, res, next) {
    (() => {
        return new Promise(r => {
            if (req.query.sentence && req.query.token){
                const sentence = req.query.sentence
                const token = req.query.token
                const headers = {
                    'Content-Type': 'application/json;charset=UTF-8',
                    'Authorization': `Bearer ${token}`
                }
                const data = {
                    'sentence': sentence,
                }
                const options = {
                    url: 'https://api.ce-cotoha.com/api/dev/nlp/v1/sentiment',
                    method: 'POST',
                    headers: headers,
                    json: data
                }
                request(options, (error, response, body) => {
                    return r(body)
                })
            }else{
                r('Parameter is incorrect')
            }
        })
    })().then(data => {
        res.send(data)
    }).catch(error => {
        res.send(error)
      })
})

あとがき

他のAPIと組み合わせれば、話す内容によって表情を変えるbotが簡単に出来そう。

あと要約(β)API・キーワード抽出API・言い淀み除去(β)・音声認識誤り検知(β)・音声認識API ここら辺のを使って、音声データから議事録を作るWEBアプリ(WEBサービス)作りたい。。。時間が欲しい。。。

おまけ

Q. さて、これは誰が歌っているのさくらの結果でしょうか???↓

さくら

?
"sentiment": "Positive",
"score": 0.0010436678748683892,

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.0010436678748683892,
    "emotional_phrase": [
      {
        "form": "また気になる",
        "emotion": "PN"
      },
      {
        "form": "忘れた",
        "emotion": "PN"
      },
      {
        "form": "淡い",
        "emotion": "PN"
      },
      {
        "form": "意味なく",
        "emotion": "N"
      },
      {
        "form": "変わらない",
        "emotion": "PN"
      },
      {
        "form": "甦る",
        "emotion": "PN"
      },
      {
        "form": "長い",
        "emotion": "PN"
      },
      {
        "form": "たわいない",
        "emotion": "PN"
      },
      {
        "form": "気付けば",
        "emotion": "P"
      },
      {
        "form": "誘われ",
        "emotion": "P"
      },
      {
        "form": "すり抜けた",
        "emotion": "PN"
      },
      {
        "form": "分からなかった",
        "emotion": "N"
      },
      {
        "form": "若かった",
        "emotion": "P"
      },
      {
        "form": "香る",
        "emotion": "P"
      },
      {
        "form": "暖かい",
        "emotion": "P"
      },
      {
        "form": "こぼれる",
        "emotion": "N"
      },
      {
        "form": "消えてしまうよ",
        "emotion": "N"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AIに歌を聞かせた。そして彼は笑顔?になった。(COTOHA-情分析API)

概要

歌を聞かせた。
彼はその歌を聴き、
Positiveな感情になると笑い?、
Negativeな感情になると怒り?、
Neutralな感情になると。。。?

COTOHA感情分析APIを使って、歌の歌詞からどのような感情をくみ取るのかを試した。COTOHA API for Developersに登録してすぐに、感情分析APIを試せるようWEBアプリも作った。)

結果

とりあえず歴代CDシングル売り上げ枚数ランキングを聞かせた。
「1位から順に!カウントアップ!?」

1.(457.7万枚)およげ!たいやきくん

?
"sentiment": "Negative"
"score": 0.5

Response
{
  "result": {
    "sentiment": "Negative",
    "score": 0.5,
    "emotional_phrase": [
      {
        "form": "こころがはずむ",
        "emotion": "喜ぶ"
      },
      {
        "form": "たのしい",
        "emotion": "P"
      },
      {
        "form": "おもい",
        "emotion": "N"
      },
      {
        "form": "ひろいぜ",
        "emotion": "PN"
      },
      {
        "form": "いじめられる",
        "emotion": "N"
      },
      {
        "form": "もがいて",
        "emotion": "N"
      },
      {
        "form": "こげある",
        "emotion": "N"
      },
      {
        "form": "うまそう",
        "emotion": "P"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

2.(325.6万枚)女のみち

?
"sentiment": "Negative"
"score": 0.2011977885862898

Response
{
  "result": {
    "sentiment": "Negative",
    "score": 0.2011977885862898,
    "emotional_phrase": [
      {
        "form": "みちならば暗い",
        "emotion": "N"
      },
      {
        "form": "恋",
        "emotion": "好ましい,切ない"
      },
      {
        "form": "幸せ",
        "emotion": "P"
      },
      {
        "form": "つらい",
        "emotion": "N"
      },
      {
        "form": "泣",
        "emotion": "喜ぶ,悲しい,切ない"
      },
      {
        "form": "すがって泣いたうぶな",
        "emotion": "PN"
      },
      {
        "form": "いけない",
        "emotion": "N"
      },
      {
        "form": "みちならば",
        "emotion": "PN"
      },
      {
        "form": "捨てた",
        "emotion": "N"
      },
      {
        "form": "いじめる",
        "emotion": "N"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

3.(313.2万枚)世界に一つだけの花

?
"sentiment": "Positive"
"score": 0.08995079776388203

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.08995079776388203,
    "emotional_phrase": [
      {
        "form": "うれしそうな",
        "emotion": "P"
      },
      {
        "form": "笑顔",
        "emotion": "安心"
      },
      {
        "form": "好み",
        "emotion": "好ましい"
      },
      {
        "form": "困った",
        "emotion": "N"
      },
      {
        "form": "迷",
        "emotion": "不安"
      },
      {
        "form": "笑い",
        "emotion": "喜ぶ"
      },
      {
        "form": "もともと特別な",
        "emotion": "PN"
      },
      {
        "form": "ひとそれぞれ",
        "emotion": "PN"
      },
      {
        "form": "きれいだ",
        "emotion": "P"
      },
      {
        "form": "争う",
        "emotion": "N"
      },
      {
        "form": "誇らしげ",
        "emotion": "P"
      },
      {
        "form": "咲かせる",
        "emotion": "P"
      },
      {
        "form": "一生懸命",
        "emotion": "PN"
      },
      {
        "form": "頑張って",
        "emotion": "P"
      },
      {
        "form": "仕方ないね",
        "emotion": "N"
      },
      {
        "form": "色とりどり",
        "emotion": "P"
      },
      {
        "form": "気づかない",
        "emotion": "N"
      },
      {
        "form": "小さい",
        "emotion": "PN"
      },
      {
        "form": "同じものはない",
        "emotion": "PN"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

4.(293.6万枚)TSUNAMI

?
"sentiment": "Negative"
"score": 0.10121480950551423

Response
{
  "result": {
    "sentiment": "Negative",
    "score": 0.10121480950551423,
    "emotional_phrase": [
      {
        "form": "愛",
        "emotion": "安心,好ましい"
      },
      {
        "form": "愛しい",
        "emotion": "P"
      },
      {
        "form": "怯えてる",
        "emotion": "不安"
      },
      {
        "form": "悲しみ",
        "emotion": "悲しい"
      },
      {
        "form": "恋",
        "emotion": "好ましい,切ない"
      },
      {
        "form": "好きな",
        "emotion": "P"
      },
      {
        "form": "戸惑う",
        "emotion": "N"
      },
      {
        "form": "泣いた",
        "emotion": "N"
      },
      {
        "form": "涙",
        "emotion": "喜ぶ,不安,悲しい,切ない"
      },
      {
        "form": "微笑",
        "emotion": "安心"
      },
      {
        "form": "弱気な",
        "emotion": "N"
      },
      {
        "form": "すがる",
        "emotion": "N"
      },
      {
        "form": "涙もろい",
        "emotion": "PN"
      },
      {
        "form": "清か",
        "emotion": "P"
      },
      {
        "form": "魔性",
        "emotion": "N"
      },
      {
        "form": "彷徨う",
        "emotion": "N"
      },
      {
        "form": "枯れる",
        "emotion": "N"
      },
      {
        "form": "素直に",
        "emotion": "P"
      },
      {
        "form": "侘しさ",
        "emotion": "PN"
      },
      {
        "form": "鏡のような",
        "emotion": "P"
      },
      {
        "form": "深い",
        "emotion": "PN"
      },
      {
        "form": "気付いてる",
        "emotion": "P"
      },
      {
        "form": "張り裂けそうな",
        "emotion": "N"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

5.(291.8万枚)だんご3兄弟

?
"sentiment": "Negative"
"score": 0.06456371454543736

Response
{
  "result": {
    "sentiment": "Negative",
    "score": 0.06456371454543736,
    "emotional_phrase": [
      {
        "form": "かたくな",
        "emotion": "不安"
      },
      {
        "form": "ささって",
        "emotion": "P"
      },
      {
        "form": "まれ",
        "emotion": "PN"
      },
      {
        "form": "たくさん",
        "emotion": "PN"
      },
      {
        "form": "こげ",
        "emotion": "N"
      },
      {
        "form": "かたくなりました",
        "emotion": "PN"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

6.(289.5万枚)君がいるだけで

?
"sentiment": "Positive"
"score": 0.009547567550434202

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.009547567550434202,
    "emotional_phrase": [
      {
        "form": "憧れ",
        "emotion": "P"
      },
      {
        "form": "笑顔",
        "emotion": "安心"
      },
      {
        "form": "くやしい",
        "emotion": "N"
      },
      {
        "form": "何より大切な",
        "emotion": "P"
      },
      {
        "form": "涙",
        "emotion": "喜ぶ,切ない,不安,悲しい"
      },
      {
        "form": "儚い",
        "emotion": "PN"
      },
      {
        "form": "強く",
        "emotion": "PN"
      },
      {
        "form": "気付かせてくれたね",
        "emotion": "P"
      },
      {
        "form": "ありがちな",
        "emotion": "PN"
      },
      {
        "form": "つい引き込まれ",
        "emotion": "P"
      },
      {
        "form": "弱さ",
        "emotion": "N"
      },
      {
        "form": "忘れてた",
        "emotion": "PN"
      },
      {
        "form": "もっと素直になれなかった",
        "emotion": "N"
      },
      {
        "form": "わかって",
        "emotion": "P"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

7.(282.2万枚)SAY YES

?
"sentiment": "Negative"
"score": 0.2490204168421342

Response
{
  "result": {
    "sentiment": "Negative",
    "score": 0.2490204168421342,
    "emotional_phrase": [
      {
        "form": "愛",
        "emotion": "好ましい,安心"
      },
      {
        "form": "愛してる",
        "emotion": "P"
      },
      {
        "form": "恋",
        "emotion": "好ましい,切ない"
      },
      {
        "form": "寂しい",
        "emotion": "N"
      },
      {
        "form": "切なさ",
        "emotion": "PN"
      },
      {
        "form": "迷",
        "emotion": "不安"
      },
      {
        "form": "ワガママ",
        "emotion": "N"
      },
      {
        "form": "余計な",
        "emotion": "N"
      },
      {
        "form": "何げなく暮らさない",
        "emotion": "PN"
      },
      {
        "form": "あふれてる",
        "emotion": "N"
      },
      {
        "form": "勝てない",
        "emotion": "N"
      },
      {
        "form": "消えない",
        "emotion": "P"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

8.(276.6万枚)Tomorrow never knows

?
"sentiment": "Positive"
"score": 0.007165278534051281

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.007165278534051281,
    "emotional_phrase": [
      {
        "form": "愛した",
        "emotion": "P"
      },
      {
        "form": "悲しい",
        "emotion": "N"
      },
      {
        "form": "孤独な",
        "emotion": "PN"
      },
      {
        "form": "寂しい",
        "emotion": "N"
      },
      {
        "form": "愛される喜び",
        "emotion": "P"
      },
      {
        "form": "消えた帰らぬ",
        "emotion": "P"
      },
      {
        "form": "すれ違う",
        "emotion": "N"
      },
      {
        "form": "無邪気に",
        "emotion": "P"
      },
      {
        "form": "裏切れる",
        "emotion": "N"
      },
      {
        "form": "欲しがっていた",
        "emotion": "P"
      },
      {
        "form": "分かり合えた",
        "emotion": "P"
      },
      {
        "form": "夢中で駆け抜ける",
        "emotion": "P"
      },
      {
        "form": "勝利",
        "emotion": "P"
      },
      {
        "form": "敗北もない",
        "emotion": "P"
      },
      {
        "form": "忘れてゆく",
        "emotion": "PN"
      },
      {
        "form": "避けて通れない",
        "emotion": "P"
      },
      {
        "form": "果てしない",
        "emotion": "P"
      },
      {
        "form": "優しさ",
        "emotion": "P"
      },
      {
        "form": "長い",
        "emotion": "PN"
      },
      {
        "form": "癒える",
        "emotion": "P"
      },
      {
        "form": "少し",
        "emotion": "PN"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

9.(258.8万枚)ラブ・ストーリーは突然に

?
"sentiment": "Positive"
"score": 0.060429544970368884

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.060429544970368884,
    "emotional_phrase": [
      {
        "form": "もっと好き",
        "emotion": "P"
      },
      {
        "form": "もう心揺れたりしないで切ない",
        "emotion": "PN"
      },
      {
        "form": "揺れたり",
        "emotion": "興奮"
      },
      {
        "form": "いい",
        "emotion": "P"
      },
      {
        "form": "分からない",
        "emotion": "N"
      },
      {
        "form": "消えてゆく",
        "emotion": "N"
      },
      {
        "form": "あんまりすてきだ",
        "emotion": "P"
      },
      {
        "form": "甘く",
        "emotion": "PN"
      },
      {
        "form": "やわらかく",
        "emotion": "PN"
      },
      {
        "form": "心が動いた",
        "emotion": "P"
      },
      {
        "form": "忘れない",
        "emotion": "PN"
      },
      {
        "form": "心揺れたりしないで",
        "emotion": "PN"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

10.(248.9万枚)LOVE LOVE LOVE

?
"sentiment": "Positive"
"score": 0.24542462771149284

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.24542462771149284,
    "emotional_phrase": [
      {
        "form": "愛",
        "emotion": "安心,好ましい"
      },
      {
        "form": "愛してる",
        "emotion": "P"
      },
      {
        "form": "すごく好きな",
        "emotion": "P"
      },
      {
        "form": "涙",
        "emotion": "喜ぶ,切ない,不安,悲しい"
      },
      {
        "form": "すっごく",
        "emotion": "PN"
      },
      {
        "form": "うまく",
        "emotion": "P"
      },
      {
        "form": "願う",
        "emotion": "P"
      },
      {
        "form": "少しずつ思い出になって",
        "emotion": "P"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

番外編(何となく気になった曲)

大きなのっぽの古時計

?
"sentiment": "Positive"
"score": 0.30601098537139876

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.30601098537139876,
    "emotional_phrase": [
      {
        "form": "うれしい",
        "emotion": "P"
      },
      {
        "form": "かなしい",
        "emotion": "N"
      },
      {
        "form": "のっぽの",
        "emotion": "PN"
      },
      {
        "form": "ごじまんの",
        "emotion": "PN"
      },
      {
        "form": "きれいな",
        "emotion": "P"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

千の風になって

?
"sentiment": "Positive"
"score": 0.14780720679775194,

Response
{
  "result": {
    "sentiment": "Positive"
    "score": 0.14780720679775194,
    "emotional_phrase": [
      {
        "form": "泣かないでください",
        "emotion": "P"
      },
      {
        "form": "きらめく",
        "emotion": "P"
      },
      {
        "form": "見守る",
        "emotion": "P"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

パプリカ

?
"sentiment": "Positive"
"score": 0.01385186275421083

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.01385186275421083,
    "emotional_phrase": [
      {
        "form": "泣いてた",
        "emotion": "N"
      },
      {
        "form": "喜び",
        "emotion": "P"
      },
      {
        "form": "晴れた",
        "emotion": "P"
      },
      {
        "form": "燻り",
        "emotion": "N"
      },
      {
        "form": "慰める",
        "emotion": "P"
      },
      {
        "form": "まれ",
        "emotion": "PN"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

WEBアプリ化

COTOHA API for Developersに登録した人限定ではあるが、同じ遊びが出来るようにした。(簡単に登録可)
以下URLで遊ぶには、登録後に取得できる、Client IDClient secretが必要。
https://cotoha-demo.now.sh/

2020-02-26_17h32_04.png

Client IDClient secretは、画面リフレッシュのたびに入力しなおすのは面倒。なので、ブラウザのlocalstrageにて情報を保持している。

技術

サービス化に伴い、以下の技術を使用。

  • Nuxt.js【JavaScript framework】
  • ant-design-vue【Css framework】
  • Now【Deploy】
  • Express【API】

server.js
server.js
const express = require('express')
const request = require('request')
const app = express()

// server
const port = process.env.PORT || 5000
app.listen(port, err => {
    if (err) throw err
    console.log(`> Ready On Server http://localhost:${port}`)
})

// API
app.get('/getToken', function(req, res, next) {
    (() => {
        return new Promise(r => {
            if (req.query.ClientID && req.query.Clientsecret && req.query.AccessTokenPublishURL){
                const AccessTokenPublishURL = req.query.AccessTokenPublishURL
                const ClientID = req.query.ClientID
                const Clientsecret = req.query.Clientsecret
                const headers = {
                    'Content-Type': 'application/json'
                }
                const data = {
                    'grantType': 'client_credentials',
                    'clientId': ClientID,
                    'clientSecret': Clientsecret
                }
                const options = {
                    url: AccessTokenPublishURL,
                    method: 'POST',
                    headers: headers,
                    json: data
                }
                request(options, (error, response, body) => {
                    return r(body)
                })
            }else{
                r('Parameter is incorrect')
            }
        })
    })().then(data => {
        res.send(data)
    }).catch(error => {
        res.send(error)
      })
})

app.get('/cotohaApiSimilarity', function(req, res, next) {
    (() => {
        return new Promise(r => {
            if (req.query.sentence && req.query.token){
                const sentence = req.query.sentence
                const token = req.query.token
                const headers = {
                    'Content-Type': 'application/json;charset=UTF-8',
                    'Authorization': `Bearer ${token}`
                }
                const data = {
                    'sentence': sentence,
                }
                const options = {
                    url: 'https://api.ce-cotoha.com/api/dev/nlp/v1/sentiment',
                    method: 'POST',
                    headers: headers,
                    json: data
                }
                request(options, (error, response, body) => {
                    return r(body)
                })
            }else{
                r('Parameter is incorrect')
            }
        })
    })().then(data => {
        res.send(data)
    }).catch(error => {
        res.send(error)
      })
})

あとがき

他のAPIと組み合わせれば、話す内容によって表情を変えるbotが簡単に出来そう。

あと要約(β)API・キーワード抽出API・言い淀み除去(β)・音声認識誤り検知(β)・音声認識API ここら辺のを使って、音声データから議事録を作るWEBアプリ(WEBサービス)作りたい。。。時間が欲しい。。。

おまけ

Q. さて、これは誰が歌っているのさくらの結果でしょうか???↓

さくら

?
"sentiment": "Positive",
"score": 0.0010436678748683892,

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.0010436678748683892,
    "emotional_phrase": [
      {
        "form": "また気になる",
        "emotion": "PN"
      },
      {
        "form": "忘れた",
        "emotion": "PN"
      },
      {
        "form": "淡い",
        "emotion": "PN"
      },
      {
        "form": "意味なく",
        "emotion": "N"
      },
      {
        "form": "変わらない",
        "emotion": "PN"
      },
      {
        "form": "甦る",
        "emotion": "PN"
      },
      {
        "form": "長い",
        "emotion": "PN"
      },
      {
        "form": "たわいない",
        "emotion": "PN"
      },
      {
        "form": "気付けば",
        "emotion": "P"
      },
      {
        "form": "誘われ",
        "emotion": "P"
      },
      {
        "form": "すり抜けた",
        "emotion": "PN"
      },
      {
        "form": "分からなかった",
        "emotion": "N"
      },
      {
        "form": "若かった",
        "emotion": "P"
      },
      {
        "form": "香る",
        "emotion": "P"
      },
      {
        "form": "暖かい",
        "emotion": "P"
      },
      {
        "form": "こぼれる",
        "emotion": "N"
      },
      {
        "form": "消えてしまうよ",
        "emotion": "N"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AIに歌を聞かせた。そして彼は笑顔?になった。(COTOHA-感情分析API)

概要

歌を聞かせた。
彼はその歌を聴き、
Positiveな感情になると笑い?、
Negativeな感情になると怒り?、
Neutralな感情になると。。。?

(COTOHA感情分析APIを使って、歌の歌詞からどのような感情をくみ取るのかを試した。COTOHA API for Developersに登録してすぐに、感情分析APIを試せるようWEBアプリも作った。)

結果

とりあえず歴代CDシングル売り上げ枚数ランキングを聞かせた。
「1位から順に!カウントアップ!?」

1.(457.7万枚)およげ!たいやきくん

?
"sentiment": "Negative"
"score": 0.5

Response
{
  "result": {
    "sentiment": "Negative",
    "score": 0.5,
    "emotional_phrase": [
      {
        "form": "こころがはずむ",
        "emotion": "喜ぶ"
      },
      {
        "form": "たのしい",
        "emotion": "P"
      },
      {
        "form": "おもい",
        "emotion": "N"
      },
      {
        "form": "ひろいぜ",
        "emotion": "PN"
      },
      {
        "form": "いじめられる",
        "emotion": "N"
      },
      {
        "form": "もがいて",
        "emotion": "N"
      },
      {
        "form": "こげある",
        "emotion": "N"
      },
      {
        "form": "うまそう",
        "emotion": "P"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

2.(325.6万枚)女のみち

?
"sentiment": "Negative"
"score": 0.2011977885862898

Response
{
  "result": {
    "sentiment": "Negative",
    "score": 0.2011977885862898,
    "emotional_phrase": [
      {
        "form": "みちならば暗い",
        "emotion": "N"
      },
      {
        "form": "恋",
        "emotion": "好ましい,切ない"
      },
      {
        "form": "幸せ",
        "emotion": "P"
      },
      {
        "form": "つらい",
        "emotion": "N"
      },
      {
        "form": "泣",
        "emotion": "喜ぶ,悲しい,切ない"
      },
      {
        "form": "すがって泣いたうぶな",
        "emotion": "PN"
      },
      {
        "form": "いけない",
        "emotion": "N"
      },
      {
        "form": "みちならば",
        "emotion": "PN"
      },
      {
        "form": "捨てた",
        "emotion": "N"
      },
      {
        "form": "いじめる",
        "emotion": "N"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

3.(313.2万枚)世界に一つだけの花

?
"sentiment": "Positive"
"score": 0.08995079776388203

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.08995079776388203,
    "emotional_phrase": [
      {
        "form": "うれしそうな",
        "emotion": "P"
      },
      {
        "form": "笑顔",
        "emotion": "安心"
      },
      {
        "form": "好み",
        "emotion": "好ましい"
      },
      {
        "form": "困った",
        "emotion": "N"
      },
      {
        "form": "迷",
        "emotion": "不安"
      },
      {
        "form": "笑い",
        "emotion": "喜ぶ"
      },
      {
        "form": "もともと特別な",
        "emotion": "PN"
      },
      {
        "form": "ひとそれぞれ",
        "emotion": "PN"
      },
      {
        "form": "きれいだ",
        "emotion": "P"
      },
      {
        "form": "争う",
        "emotion": "N"
      },
      {
        "form": "誇らしげ",
        "emotion": "P"
      },
      {
        "form": "咲かせる",
        "emotion": "P"
      },
      {
        "form": "一生懸命",
        "emotion": "PN"
      },
      {
        "form": "頑張って",
        "emotion": "P"
      },
      {
        "form": "仕方ないね",
        "emotion": "N"
      },
      {
        "form": "色とりどり",
        "emotion": "P"
      },
      {
        "form": "気づかない",
        "emotion": "N"
      },
      {
        "form": "小さい",
        "emotion": "PN"
      },
      {
        "form": "同じものはない",
        "emotion": "PN"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

4.(293.6万枚)TSUNAMI

?
"sentiment": "Negative"
"score": 0.10121480950551423

Response
{
  "result": {
    "sentiment": "Negative",
    "score": 0.10121480950551423,
    "emotional_phrase": [
      {
        "form": "愛",
        "emotion": "安心,好ましい"
      },
      {
        "form": "愛しい",
        "emotion": "P"
      },
      {
        "form": "怯えてる",
        "emotion": "不安"
      },
      {
        "form": "悲しみ",
        "emotion": "悲しい"
      },
      {
        "form": "恋",
        "emotion": "好ましい,切ない"
      },
      {
        "form": "好きな",
        "emotion": "P"
      },
      {
        "form": "戸惑う",
        "emotion": "N"
      },
      {
        "form": "泣いた",
        "emotion": "N"
      },
      {
        "form": "涙",
        "emotion": "喜ぶ,不安,悲しい,切ない"
      },
      {
        "form": "微笑",
        "emotion": "安心"
      },
      {
        "form": "弱気な",
        "emotion": "N"
      },
      {
        "form": "すがる",
        "emotion": "N"
      },
      {
        "form": "涙もろい",
        "emotion": "PN"
      },
      {
        "form": "清か",
        "emotion": "P"
      },
      {
        "form": "魔性",
        "emotion": "N"
      },
      {
        "form": "彷徨う",
        "emotion": "N"
      },
      {
        "form": "枯れる",
        "emotion": "N"
      },
      {
        "form": "素直に",
        "emotion": "P"
      },
      {
        "form": "侘しさ",
        "emotion": "PN"
      },
      {
        "form": "鏡のような",
        "emotion": "P"
      },
      {
        "form": "深い",
        "emotion": "PN"
      },
      {
        "form": "気付いてる",
        "emotion": "P"
      },
      {
        "form": "張り裂けそうな",
        "emotion": "N"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

5.(291.8万枚)だんご3兄弟

?
"sentiment": "Negative"
"score": 0.06456371454543736

Response
{
  "result": {
    "sentiment": "Negative",
    "score": 0.06456371454543736,
    "emotional_phrase": [
      {
        "form": "かたくな",
        "emotion": "不安"
      },
      {
        "form": "ささって",
        "emotion": "P"
      },
      {
        "form": "まれ",
        "emotion": "PN"
      },
      {
        "form": "たくさん",
        "emotion": "PN"
      },
      {
        "form": "こげ",
        "emotion": "N"
      },
      {
        "form": "かたくなりました",
        "emotion": "PN"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

6.(289.5万枚)君がいるだけで

?
"sentiment": "Positive"
"score": 0.009547567550434202

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.009547567550434202,
    "emotional_phrase": [
      {
        "form": "憧れ",
        "emotion": "P"
      },
      {
        "form": "笑顔",
        "emotion": "安心"
      },
      {
        "form": "くやしい",
        "emotion": "N"
      },
      {
        "form": "何より大切な",
        "emotion": "P"
      },
      {
        "form": "涙",
        "emotion": "喜ぶ,切ない,不安,悲しい"
      },
      {
        "form": "儚い",
        "emotion": "PN"
      },
      {
        "form": "強く",
        "emotion": "PN"
      },
      {
        "form": "気付かせてくれたね",
        "emotion": "P"
      },
      {
        "form": "ありがちな",
        "emotion": "PN"
      },
      {
        "form": "つい引き込まれ",
        "emotion": "P"
      },
      {
        "form": "弱さ",
        "emotion": "N"
      },
      {
        "form": "忘れてた",
        "emotion": "PN"
      },
      {
        "form": "もっと素直になれなかった",
        "emotion": "N"
      },
      {
        "form": "わかって",
        "emotion": "P"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

7.(282.2万枚)SAY YES

?
"sentiment": "Negative"
"score": 0.2490204168421342

Response
{
  "result": {
    "sentiment": "Negative",
    "score": 0.2490204168421342,
    "emotional_phrase": [
      {
        "form": "愛",
        "emotion": "好ましい,安心"
      },
      {
        "form": "愛してる",
        "emotion": "P"
      },
      {
        "form": "恋",
        "emotion": "好ましい,切ない"
      },
      {
        "form": "寂しい",
        "emotion": "N"
      },
      {
        "form": "切なさ",
        "emotion": "PN"
      },
      {
        "form": "迷",
        "emotion": "不安"
      },
      {
        "form": "ワガママ",
        "emotion": "N"
      },
      {
        "form": "余計な",
        "emotion": "N"
      },
      {
        "form": "何げなく暮らさない",
        "emotion": "PN"
      },
      {
        "form": "あふれてる",
        "emotion": "N"
      },
      {
        "form": "勝てない",
        "emotion": "N"
      },
      {
        "form": "消えない",
        "emotion": "P"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

8.(276.6万枚)Tomorrow never knows

?
"sentiment": "Positive"
"score": 0.007165278534051281

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.007165278534051281,
    "emotional_phrase": [
      {
        "form": "愛した",
        "emotion": "P"
      },
      {
        "form": "悲しい",
        "emotion": "N"
      },
      {
        "form": "孤独な",
        "emotion": "PN"
      },
      {
        "form": "寂しい",
        "emotion": "N"
      },
      {
        "form": "愛される喜び",
        "emotion": "P"
      },
      {
        "form": "消えた帰らぬ",
        "emotion": "P"
      },
      {
        "form": "すれ違う",
        "emotion": "N"
      },
      {
        "form": "無邪気に",
        "emotion": "P"
      },
      {
        "form": "裏切れる",
        "emotion": "N"
      },
      {
        "form": "欲しがっていた",
        "emotion": "P"
      },
      {
        "form": "分かり合えた",
        "emotion": "P"
      },
      {
        "form": "夢中で駆け抜ける",
        "emotion": "P"
      },
      {
        "form": "勝利",
        "emotion": "P"
      },
      {
        "form": "敗北もない",
        "emotion": "P"
      },
      {
        "form": "忘れてゆく",
        "emotion": "PN"
      },
      {
        "form": "避けて通れない",
        "emotion": "P"
      },
      {
        "form": "果てしない",
        "emotion": "P"
      },
      {
        "form": "優しさ",
        "emotion": "P"
      },
      {
        "form": "長い",
        "emotion": "PN"
      },
      {
        "form": "癒える",
        "emotion": "P"
      },
      {
        "form": "少し",
        "emotion": "PN"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

9.(258.8万枚)ラブ・ストーリーは突然に

?
"sentiment": "Positive"
"score": 0.060429544970368884

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.060429544970368884,
    "emotional_phrase": [
      {
        "form": "もっと好き",
        "emotion": "P"
      },
      {
        "form": "もう心揺れたりしないで切ない",
        "emotion": "PN"
      },
      {
        "form": "揺れたり",
        "emotion": "興奮"
      },
      {
        "form": "いい",
        "emotion": "P"
      },
      {
        "form": "分からない",
        "emotion": "N"
      },
      {
        "form": "消えてゆく",
        "emotion": "N"
      },
      {
        "form": "あんまりすてきだ",
        "emotion": "P"
      },
      {
        "form": "甘く",
        "emotion": "PN"
      },
      {
        "form": "やわらかく",
        "emotion": "PN"
      },
      {
        "form": "心が動いた",
        "emotion": "P"
      },
      {
        "form": "忘れない",
        "emotion": "PN"
      },
      {
        "form": "心揺れたりしないで",
        "emotion": "PN"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

10.(248.9万枚)LOVE LOVE LOVE

?
"sentiment": "Positive"
"score": 0.24542462771149284

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.24542462771149284,
    "emotional_phrase": [
      {
        "form": "愛",
        "emotion": "安心,好ましい"
      },
      {
        "form": "愛してる",
        "emotion": "P"
      },
      {
        "form": "すごく好きな",
        "emotion": "P"
      },
      {
        "form": "涙",
        "emotion": "喜ぶ,切ない,不安,悲しい"
      },
      {
        "form": "すっごく",
        "emotion": "PN"
      },
      {
        "form": "うまく",
        "emotion": "P"
      },
      {
        "form": "願う",
        "emotion": "P"
      },
      {
        "form": "少しずつ思い出になって",
        "emotion": "P"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

番外編(何となく気になった曲)

大きなのっぽの古時計

?
"sentiment": "Positive"
"score": 0.30601098537139876

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.30601098537139876,
    "emotional_phrase": [
      {
        "form": "うれしい",
        "emotion": "P"
      },
      {
        "form": "かなしい",
        "emotion": "N"
      },
      {
        "form": "のっぽの",
        "emotion": "PN"
      },
      {
        "form": "ごじまんの",
        "emotion": "PN"
      },
      {
        "form": "きれいな",
        "emotion": "P"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

千の風になって

?
"sentiment": "Positive"
"score": 0.14780720679775194,

Response
{
  "result": {
    "sentiment": "Positive"
    "score": 0.14780720679775194,
    "emotional_phrase": [
      {
        "form": "泣かないでください",
        "emotion": "P"
      },
      {
        "form": "きらめく",
        "emotion": "P"
      },
      {
        "form": "見守る",
        "emotion": "P"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

パプリカ

?
"sentiment": "Positive"
"score": 0.01385186275421083

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.01385186275421083,
    "emotional_phrase": [
      {
        "form": "泣いてた",
        "emotion": "N"
      },
      {
        "form": "喜び",
        "emotion": "P"
      },
      {
        "form": "晴れた",
        "emotion": "P"
      },
      {
        "form": "燻り",
        "emotion": "N"
      },
      {
        "form": "慰める",
        "emotion": "P"
      },
      {
        "form": "まれ",
        "emotion": "PN"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

WEBアプリ化

COTOHA API for Developersに登録した人限定ではあるが、同じ遊びが出来るようにした。(簡単に登録可)
以下URLで遊ぶには、登録後に取得できる、Client IDClient secretが必要。
https://cotoha-demo.now.sh/

2020-02-26_17h32_04.png

Client IDClient secretは、画面リフレッシュのたびに入力しなおすのは面倒。なので、ブラウザのlocalstrageにて情報を保持している。

技術

アプリ化に伴い、以下の技術を使用。

  • Nuxt.js【JavaScript framework】
  • ant-design-vue【Css framework】
  • Now【Deploy】
  • Express【API】

server.js
server.js
const express = require('express')
const request = require('request')
const app = express()

// server
const port = process.env.PORT || 5000
app.listen(port, err => {
    if (err) throw err
    console.log(`> Ready On Server http://localhost:${port}`)
})

// API
app.get('/getToken', function(req, res, next) {
    (() => {
        return new Promise(r => {
            if (req.query.ClientID && req.query.Clientsecret && req.query.AccessTokenPublishURL){
                const AccessTokenPublishURL = req.query.AccessTokenPublishURL
                const ClientID = req.query.ClientID
                const Clientsecret = req.query.Clientsecret
                const headers = {
                    'Content-Type': 'application/json'
                }
                const data = {
                    'grantType': 'client_credentials',
                    'clientId': ClientID,
                    'clientSecret': Clientsecret
                }
                const options = {
                    url: AccessTokenPublishURL,
                    method: 'POST',
                    headers: headers,
                    json: data
                }
                request(options, (error, response, body) => {
                    return r(body)
                })
            }else{
                r('Parameter is incorrect')
            }
        })
    })().then(data => {
        res.send(data)
    }).catch(error => {
        res.send(error)
      })
})

app.get('/cotohaApiSimilarity', function(req, res, next) {
    (() => {
        return new Promise(r => {
            if (req.query.sentence && req.query.token){
                const sentence = req.query.sentence
                const token = req.query.token
                const headers = {
                    'Content-Type': 'application/json;charset=UTF-8',
                    'Authorization': `Bearer ${token}`
                }
                const data = {
                    'sentence': sentence,
                }
                const options = {
                    url: 'https://api.ce-cotoha.com/api/dev/nlp/v1/sentiment',
                    method: 'POST',
                    headers: headers,
                    json: data
                }
                request(options, (error, response, body) => {
                    return r(body)
                })
            }else{
                r('Parameter is incorrect')
            }
        })
    })().then(data => {
        res.send(data)
    }).catch(error => {
        res.send(error)
      })
})

あとがき

他のAPIと組み合わせれば、話す内容によって表情を変えるbotが簡単に出来そう。

あと要約(β)API・キーワード抽出API・言い淀み除去(β)・音声認識誤り検知(β)・音声認識API ここら辺のを使って、音声データから議事録を作るWEBアプリ(WEBサービス)作りたい。。。時間が欲しい。。。

おまけ

Q. さて、これは誰が歌っているのさくらの結果でしょうか???↓

さくら

?
"sentiment": "Positive",
"score": 0.0010436678748683892,

Response
{
  "result": {
    "sentiment": "Positive",
    "score": 0.0010436678748683892,
    "emotional_phrase": [
      {
        "form": "また気になる",
        "emotion": "PN"
      },
      {
        "form": "忘れた",
        "emotion": "PN"
      },
      {
        "form": "淡い",
        "emotion": "PN"
      },
      {
        "form": "意味なく",
        "emotion": "N"
      },
      {
        "form": "変わらない",
        "emotion": "PN"
      },
      {
        "form": "甦る",
        "emotion": "PN"
      },
      {
        "form": "長い",
        "emotion": "PN"
      },
      {
        "form": "たわいない",
        "emotion": "PN"
      },
      {
        "form": "気付けば",
        "emotion": "P"
      },
      {
        "form": "誘われ",
        "emotion": "P"
      },
      {
        "form": "すり抜けた",
        "emotion": "PN"
      },
      {
        "form": "分からなかった",
        "emotion": "N"
      },
      {
        "form": "若かった",
        "emotion": "P"
      },
      {
        "form": "香る",
        "emotion": "P"
      },
      {
        "form": "暖かい",
        "emotion": "P"
      },
      {
        "form": "こぼれる",
        "emotion": "N"
      },
      {
        "form": "消えてしまうよ",
        "emotion": "N"
      }
    ]
  },
  "status": 0,
  "message": "OK"
}

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Windowsでnpm startしたときに「内部コマンドまたは外部コマンド」と出てくる現象と戦う

1. 問題発生

Webpackをglobalにインストールすることが非推奨であることを知り、

> npm remove -g webpack webpack-cli

としたところ、既存のプロジェクトにて

> npm run build
'webpack' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

と出てしまった。
package.json の scripts はこんな感じ

package.json
"scripts": {
    "build": "webpack --mode development",
},

ひとまずこれは再度グローバルにインストールすることで回避していたが、
ある日、Reactの勉強を始めようとしたところ、

> npx create-react-app pwa-sample
> cd pwa-sample
> yarn start
'react-scripts' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

と、こちらもNG。
どういうことなの?

2. 試したこと

  1. node_modules と packege-lock.json を削除して npm install ・・・ NG
  2. コマンドプロンプトやPowerShellを管理者で起動して ・・・ NG
  3. node_modules/.bin の中に webpack.cmd(react-scripts.cmd) が存在するか確認 ・・・ 存在する
  4. npx コマンドでstart ・・・ OK
  5. package.json 内の webpack や react-scripts コマンドのパス書き換え ・・・ OK

つまり、 node_modules/.bin のパスを理解していない ということか?
この時点での解決策は以下になるが、これではMacやLinuxと共通化ができずに面倒くさいしイマイチ美しくない。

package.json
"scripts": {
    "build": "node_modules\\.bin\\webpack.cmd --mode development"   // webpackの場合
    "start": "node_modules\\.bin\\react-scripts.cmd start"   // react-scriptの場合
}

通常、私はプロジェクト用のディレクトリは D:\projects というパスに設置しているが、
ちょっと気分を変えて C:\Users\hogehoge\Documents(マイドキュメント) にて作業してみた。

>yarn start
yarn run v1.22.0
$ react-scripts start
Starting the development server...
Compiled successfully!

あれ?通った?

3. 原因判明

CドライブとDドライブで何が違うんだろう・・・とパーミッションやnpmグローバルディレクトリを覗いていたがよくわからない。
C:\Users\hogehoge\AppData\Roaming\npm-cache\_logs も見るがパスは通っているように見える。
(PATHの行に プロジェクトディレクトリ/node_modules/.bin が含まれている)

後は何が問題なのだろうか、ドライブ間で何か特別な操作をしただろうか?

1つだけあった
それは以前に 大文字小文字を区別する設定をしていた ことだった。

試しにこれを解除して再チャレンジ

> fsutil.exe file SetCaseSensitiveInfo D:\project disable
> yarn start
yarn run v1.22.0
$ react-scripts start
Starting the development server...
Compiled successfully!

問題なく通りました。
もちろんwebpackもOK。

つまり、webpack や react-scripts コマンドは webpack.cmd や react-scripts.cmd ではなく、webpack.CMD や react-scripts.CMD を探していた、ということらしい。

皆さん、楽がしたいからと大きいディレクトリでSetCaseSensitiveInfoを有効にしないように注意しましょう。
ただ、これが有効になっていないと困るケースもあるので悩ましい・・・

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Windowsでnpm startしたときに「内部コマンドまたは外部コマンド~」と出てくる現象と戦う

1. 問題発生

Webpackをglobalにインストールすることが非推奨であることを知り、

> npm remove -g webpack webpack-cli

としたところ、既存のプロジェクトにて

> npm run build
'webpack' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

と出てしまった。
package.json の scripts はこんな感じ

package.json
"scripts": {
    "build": "webpack --mode development",
}

ひとまずこれは再度グローバルにインストールすることで回避していたが、
ある日、Reactの勉強を始めようとしたところ、

> npx create-react-app pwa-sample
> cd pwa-sample
> yarn start
'react-scripts' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

と、こちらもNG。
どういうことなの?

2. 試したこと

  1. node_modules と packege-lock.json を削除して npm install ・・・ NG
  2. コマンドプロンプトやPowerShellを管理者で起動して ・・・ NG
  3. node_modules/.bin の中に webpack.cmd(react-scripts.cmd) が存在するか確認 ・・・ 存在する
  4. npx コマンドでstart ・・・ OK
  5. package.json 内の webpack や react-scripts コマンドのパス書き換え ・・・ OK

つまり、 node_modules/.bin のパスを理解していない ということか?
この時点での解決策は以下になるが、これではMacやLinuxと共通化ができずに面倒くさいしイマイチ美しくない。

package.json
"scripts": {
    "build": "node_modules\\.bin\\webpack.cmd --mode development"   // webpackの場合
    "start": "node_modules\\.bin\\react-scripts.cmd start"   // react-scriptの場合
}

通常、私はプロジェクト用のディレクトリは D:\projects というパスに設置しているが、
ちょっと気分を変えて C:\Users\hogehoge\Documents(マイドキュメント) にて作業してみた。

>yarn start
yarn run v1.22.0
$ react-scripts start
Starting the development server...
Compiled successfully!

あれ?通った?

3. 原因判明

CドライブとDドライブで何が違うんだろう・・・とパーミッションやnpmグローバルディレクトリを覗いていたがよくわからない。
C:\Users\hogehoge\AppData\Roaming\npm-cache\_logs も見るがパスは通っているように見える。
(PATHの行に プロジェクトディレクトリ/node_modules/.bin が含まれている)

後は何が問題なのだろうか、ドライブ間で何か特別な操作をしただろうか?

1つだけあった
それは以前に 大文字小文字を区別する設定をしていた ことだった。

# 管理者で実行
> fsutil.exe file SetCaseSensitiveInfo D:\projects
ディレクトリ D:\projects の大文字と小文字を区別する属性が有効になっています。

試しにこれを解除して再チャレンジ

# 管理者で実行
> fsutil.exe file SetCaseSensitiveInfo D:\project disable
ディレクトリ D:\project の大文字と小文字を区別する属性が無効になっています。

# 通常ユーザーで実行
> yarn start
yarn run v1.22.0
$ react-scripts start
Starting the development server...
Compiled successfully!

問題なく通りました。
もちろんwebpackもOK。

どうやら、webpack や react-scripts コマンドは webpack.cmd や react-scripts.cmd ではなく、webpack.CMD や react-scripts.CMD を探していた、ということらしい。

安易にSetCaseSensitiveInfoを有効にしないように注意しましょう。
ただ、これが有効になっていないと困るケースもあるので悩ましい・・・
状況により中段に書いた node_modules\\.bin\\webpack.cmd と併用することになりそう。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RESTサーバのMockを簡単に作る方法

node.jsのjson-serverを利用する

json-serverというライブラリが素敵な感じ。

導入

ローカルに導入するとして。。。
1. 展開場所確保
npm init
2. インストール
npm install json-server
3. キック用にpackage.jason書き換え

package.json
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "json-server": "json-server"
  },

4.mockデータファイル用意。例えばこんな感じのjsonだとするとtop下の階層がエンドポイントになる感じ。

mockdata.json
{
  "movies": [
    { "title": "マトリックス", "rating": 9.1},
    { "title": "タイタニック", "rating": 8.8}
  ],
  "user": [
     {"name": "fukuhara", "age": 35, "sex": "male"},
     {"name": "sugiyama", "age": 42, "sex": "male"}
  ]
}

5.mockサーバ起動
npm run json-server -- --watch mockdata.json

npm WARN lifecycle The node binary used for scripts is C:\Program Files (x86)\Nodist\bin\node.exe but npm is using C:\Program Files (x86)\Nodist\v-x64\10.15.3\node.exe itself. Use the `--scripts-prepend-node-path` option to include the path for the node binary npm was executed with.

> restmock@1.0.0 json-server H:\work\restmock
> json-server "--watch" "mockdata.json"


  \{^_^}/ hi!

  Loading mockdata.json
  Done

  Resources
  http://localhost:3000/movies
  http://localhost:3000/user

  Home
  http://localhost:3000

  Type s + enter at any time to create a snapshot of the database
  Watching...

6.Curlでちょっと叩いてみる

curl -X GET "http://localhost:3000/movies"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   126  100   126    0     0    126      0  0:00:01 --:--:--  0:00:01   473[
  {
    "title": "マトリックス",
    "rating": 9.1
  },
  {
    "title": "タイタニック",
    "rating": 8.8
  }
]

できること

登録/更新/削除操作ができる

登録

curl -X POST -H "Content-Type: application/json" -d '{
  "title": "test1",
  "id":1
}' "http://localhost:3000/movies"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    65  100    33  100    32     33     32  0:00:01 --:--:--  0:00:01   277{
  "title": "test1",
  "id": 1
}

curl -X GET "http://localhost:3000/movies/"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   169  100   169    0     0    169      0  0:00:01 --:--:--  0:00:01   722[
  {
    "title": "マトリックス",
    "rating": 9.1
  },
  {
    "title": "タイタニック",
    "rating": 8.8
  },
  {
    "title": "test1",
    "id": 1
  }
]

curl -X GET "http://localhost:3000/movies/1"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    33  100    33    0     0     33      0  0:00:01 --:--:--  0:00:01   150{
  "title": "test1",
  "id": 1
}

  • 更新系作業時は「id」ってフィールド無いとダメっぽい。
  • 逆に「id」フィールドさえあれば他はチェックしてないくさい

更新されたmockデータのjsonをスナップショットとして保存できる

ctrl+s

  Saved snapshot to db-1582737815807.json
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む