no-image

Python初心者がたったの3日間でチャットボットを作った【2日目】

ゼロから3日でチャットボット開発チャレンジの2日目!
今日学んだことは、ざっくり次の3項目。

・SQLAlchemyを用いた、PythonコードによるDB操作。
・CSSによるアニメーション。
・スクロールによるアクションの操作。

CSSによるアニメーションと、スクロールによるアクションの操作に関しては、参照のしやすさを考えて別の記事でまとめる。

参考にした教材はこちら。
書籍の中で使われている言語はPHPだが、チャットボットの基礎的な仕組みについて丁寧に解説してあり、Pythonでの開発にも応用が非常に簡単であった。
チャットボットのつくり方について体系的にまとめられたリソースは非常に少ないので助かる。

おもしろまじめなチャットボットをつくろう

本記事の構成

この記事の構成は以下の通り。

  1. SQLAlchemyとは
  2. SQLAlchemyによる、モデルの構築
  3. SQLAlchemyによる、インスタンスの追加
  4. DBの参照
  5. rondomメソッドによる乱数生成
  6. チャットボット
  7. 参考

SQLAlchemyとは

SQLAlchemyとは、公式ドキュメントの説明をこれでもかというくらいざっくりまとめると、SQLをPythonで操作するための便利ツール、のようなものだ。
このようなツールをORM(オブジェクトリレーショナルマッパー)というらしい。
これは、データベースとオブジェクト指向プログラミング言語の間の非互換なデータを変換するプログラミング技法である。
これを用いることで、本来互換性のないPythonでSQLを操作することができる。

DBは今回始めて触れたこともあり、まだまだ全然わからない。
浅い説明で申し訳ないが、とりあえずこれを使ってFlaskでDBを構築することにした。

SQLAlchemyによる、モデルの構築

まずはインストールから。

  pip install sqlalchemy

新たにパッケージをインストールしたので、Herokuデプロイ前にpip freezeも忘れずに行う。
これを忘れてデプロイしてしまい、動かなくなるというエラーが何度かあった。
エラーが出た際には、requirements.txtにきちんとパッケージが明記されているか、バージョンに問題がないかを確認してみるといい。
余談ではあるが、今のHeroku上では、最新のwhitenoiseは動かないらしく、何度かそのエラーにつまづいたことがある。

SQLAlchemyを使う手順は、基本的に次のとおりである。

①テーブルの定義を行い、新たなテーブルを生成する
②生成したテーブルにインスタンスを追加する
③既存のテーブルを更新、削除する

これらの手順全てに、テーブルと接続して最後に閉じるというプロセスがあることを忘れないように。
私がハマったエラーの原因として、接続先のDBの名前がタイポ、というものがあった。

まずは1つめの手順。
テーブルの定義を行い、新たなテーブルを生成する

今回は、チャットボットが返答する内容を格納するシンプルなテーブルを作った。

  from sqlalchemy import Column, ForeignKey, Integer, String
  from sqlalchemy.ext.declarative import declarative_base
  from sqlalchemy.orm import relationship
  from sqlalchemy import create_engine

  Base = declarative_base()


  class contents(Base):
      __tablename__ = 'contents'

      id = Column(Integer, primary_key=True)
      content = Column(String(160), nullable=False)

      @property
      def serialize(self):
          return {
              'content': self.content,
              'id': self.id,
          }

  engine = create_engine('sqlite:///db.sqlite3')
  Base.metadata.create_all(engine)

正直なところ、現在は解説できるほど理解して書いてはいない。
とりあえずテーブルのインスタンスの型と名前を書いた感じ。
これからもう少しちゃんと勉強していきたい。

SQLAlchemyによる、インスタンスの追加

先程のコードを実行したら、不思議なことにdb.sqlite3というファイルが生成されていた。
何だこれは。

どうやらこれがテーブルであり、ここに接続する必要があるらしい。
インスタンス追加のためのコードはこちら。

  from sqlalchemy import create_engine
  from sqlalchemy.orm import sessionmaker
  from dbset import contents

  engine = create_engine('sqlite:///db.sqlite3', echo=True)
  Session = sessionmaker(bind=engine)
  session = Session()

  session.add_all([
      contents(content="お金持ちと貧乏人の違いって何だと思いますか?\nお金持ちにとって、お金を稼ぐとは、人を喜ばせる行為の結果であり、善いことなのです。\nですが貧乏人は、お金を求めることを悪とし、恥じます。\n人間は、恥と感じることに本気にはなれません。\nこの考え方こそが、お金持ちと貧乏人との違いなのです。"),
      contents(content="普通の人は、お金を得るためにはより多くの時間と労働力を費やそうとしますが、お金持ちにとって、時間はお金よりも大切なものです。\nだから彼らは、自分の時間と労働力を使わずにお金を稼ぐ仕組みづくりを目指します。\nあなたがもしお金持ちになりたければ、まずは自分の時間を大切にすることね。"),
      contents(content="保険業がどうやって利益を得ているか知ってますか?\n期待値で考えれば、あなたが受けとる保険金は支払った額の2/3以下程度になるよう計算されているわ。\nつまり、本当に必要な保険以外は解約し、投資に回した方が利益が大きいということよ。\n何となく入った保険ありませんか?一度見直してみましょう。"),
      contents(content="あなたは自分は違うと思うかもしれないけど、株式投資は損する人の方が多いと言われているわ。\n投資で稼ぎたければ、大損を覚悟しなさい。\n投資の神と言われる人ですら、どん底に突き落とされるような大失敗をしてるわ。\n失敗して、そこから学ぶの。\nだから生活資金は絶対に投資に回してはだめよ。"),
      contents(content="あなたは自分のが今どれだけの資産を持っていて、毎月どれだけ使っているのか、正確に把握してますか?\n自分の資産を増やしたければ、まずこれらを正確に把握することね。\nただ『記録する』だけで、月々の出費が減って貯金に成功することはよくあるわ。\nまずは己を知ることが資産形成の第一歩よ。"),
  ])

  session.commit()

こちらも正直全く理解できていないので解説はできないが許してほしい。
処理としては、DBとの接続を確立し、インスタンスを渡しているだけである。
この辺を変数に変えたら、チャットで受け取った内容をDBに保存することもできそうだ。

DBの参照

DBにちゃんとインスタンスが入ったかどうか、またどんな中身かどうかを確認するのにおすすめのソフトがある。
その名もDB brouser for SQlite。
まんまな名前だが、これが優れものなのだ。
直感的にSQliteのファイルを扱うことができる。

もともとWindowsで使っていたソフトだが、嬉しいことにLinuxでも使うことができた。
今回はあまり使わなかったが、一応書いておく。

rondomメソッドによる乱数生成

DBからランダムに返信内容を取り出してボットに送るための関数を作った。

  from sqlalchemy import create_engine
  from sqlalchemy.orm import sessionmaker
  from dbset import contents

  def content_from_DB():
      i = random.randint(1, 5)
      engine = create_engine('sqlite:///db.sqlite3', echo=False)
      Session = sessionmaker(bind=engine)
      session = Session()

      for row in session.query(contents).all():
          if row.id == i:
              return row.content

      session.close()

まだまだアマチュアだが、こんな関数をサラサラかけたあたり、Pythonを始めてからの4ヶ月で少しは成長したなと感じる。
解説としては、まず必要なモジュールをインポートして、その後ランダムに整数を一つ生成。
それと一致するIDをもつDBのインスタンスをreturnするという、まあ言ってしまえばなんてことないシンプルな関数だ。
これで準備が整った。

チャットボット

これを使って機能を拡張したボットがこちら。

返答がランダムに変わるようになっている。

ちなみに、こちらのランディングページも作った。
秋野カエデのお金の相談室

※現在はこのBOTは停止しています。

参考

・BOOK
おもしろまじめなチャットボットをつくろう
逆引きPython標準ライブラリ 目的別の基本レシピ180 ! (impress top gear)

・WEB

Pythonで、SQLAlchemyを使う
SQLAlchemy公式ドキュメント
Pythonでランダムな整数を生成するrandom.randrange, randint
FlaskとPostgreSQLでウェブアプリを作ってHerokuで無料で運用する

次の記事:Python初心者がたったの3日間でチャットボットを作った【3日目】

前の記事:Python初心者がたったの3日間でチャットボットを作った【1日目】