MkItYs

MkItYs > AI・交渉・物語の自動生成 > 

images

感情分析のエンジン/サーバ/クライアントを作る:Python (Transformers, aiohttp)

images

感情分析のエンジンと、そのサーバ〜クライアントを作ってみます。

関連


サーバ証明書を取得〜更新する(ワイルドカード証明書、ネームサーバ経由):Let's Encrypt

検証


クラウド:GCP
コンテナ:Docker
ゲストOS:Ubuntu 22.04
ウェブブラウザ:Chrome
画像生成アプリ:ComfyUI

概要


背景

いまは感情分析のモデルを、ローカル環境で動かすことができます。

対応

ここでは、感情分析のエンジンと、そのサーバ〜クライアントの、かんたんな実装を試みます。

構成

言語モデルに LUKE 、データセットに愛媛大学のもの(プルチックの「感情の輪」にもとづく)を使用した感情分析のモデルを使います:[※1]

https://huggingface.co/Mizuiro-sakura/luke-japanese-large-sentiment-analysis-wrime

※1
エクマンもそうですが、感情を分類できるという主張は、すでに否定されていますーーとはいえ、生成モデルとの組み合わせでは使い勝手がいいので、テキストから8コの感情を抽出するプルチックのモデルを採用します(XML にもエクマンの感情分類をもとにした仕様があり、表現という点から一定の需要はあるのかもしれませんね)。

設置


環境は、音声認識エンジン向けに作ったコンテナ/ライブラリを流用します:

音声認識のエンジン/サーバ/クライアントを作る:Python (Transformers, aiohttp), Javascript (MediaRecorder)

実装



バックエンド:エンジン
appsen/bin/senprc.py
import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification, LukeConfig

class SenPrc:

  def __init__(self, lenmax, nmodel):
    self.lenmax = lenmax
    cnfluk = LukeConfig.from_pretrained(
      nmodel,
      output_hidden_states=True)
    self.omodel = AutoModelForSequenceClassification.from_pretrained(
      nmodel,
      config=cnfluk)
    self.tokenz = AutoTokenizer.from_pretrained(
      nmodel)

  def getsen(self, txtreq):
    inputs = self.tokenz(
      txtreq,
      truncation=True,
      max_length=self.lenmax,
      padding="max_length")
    output = self.omodel(
      torch.tensor(inputs["input_ids"]).unsqueeze(0),
      torch.tensor(inputs["attention_mask"]).unsqueeze(0))
    maxsen = torch.argmax(
      torch.tensor(output.logits))
    numsen = maxsen.item()
    return numsen

バックエンド:サーバ
appsen/bin/sensrv.py
import json
from aiohttp import web
from senprc import SenPrc

async def res001(datreq):
  dicreq = await datreq.json()
  txtreq = dicreq["txtreq"]
  numres = senprc.getsen(txtreq)
  return web.Response(
    text=json.dumps({"numres": numres}),
    content_type="application/json",
  )

prttgt = 8081
adr001 = "/"
lenmax = 512
nmodel = "Mizuiro-sakura/luke-japanese-large-sentiment-analysis-wrime"

senprc = SenPrc(lenmax, nmodel)
appweb = web.Application()
appweb.add_routes([web.post(adr001, res001)])
web.run_app(appweb, port=prttgt)

フロントエンド:クライアント
appsen/bin/senclt.py
import sys
import asyncio
import aiohttp

async def req001(dicreq):
  async with aiohttp.ClientSession() as sssweb:
    async with sssweb.post(adr001, json=dicreq) as datres:
      dicres = await datres.json()
      return dicres

txtreq = sys.argv[1]
adr001 = "http://localhost:8081/"

dicreq = {"txtreq": txtreq}
dicres = asyncio.run(req001(dicreq))
print(dicres["numres"])

利用


コンテナ上で、サーバを起動し〜クライアントを実行します:

# サーバ
$ python /system/vol104/bin/sensrv.py &

# クライアント
$ python /system/vol104/bin/senclt.py 'きょうは楽しい一日だった'