2020年12月14日月曜日

【チャットボット】チャットボットの仕組みの技術資料

Webサイトで見かけることが多くなったチャットですが、中に人がいて人が対応してくれるもの、ボットが無人で対応してくれるものなどがあります。

ボットが無人対応するものはどんな仕組みになっているのか?どのボットも質問をすると何か返してくれるという動きは同じですが中の仕組みは色々とあるようです。そのような参考記事はこちら。

【チャットボット – その種類別の仕組み】

仕事などでチャットボット製品の調査をするときに、このような仕組みからベンダに質問できると、より自分たちに合ったものを選べそうですね。

種別ごとの詳細もありますので、参考にしてみてください。

以上

2020年12月7日月曜日

【チャットボット】 SharePointと連携して社内チャットを便利に活用

企業内でのコミュニケーションにMicrosoft TeamsやGoogle Chatなどの企業向けチャットをを使ってますという話を聞く機会も、最近多くなって来たように感じます。リモートワークに合わせて企業向けチャットを社内コミュニケーションに使い始めたという会社も多いのだろうなと思います。

リモートワークといえばワードやパワーポイントのなどファイルサーバーにあるものを「あれどこにあるっけ?」と場所を教えてもらっていたものが、それがやりにくくなったのがちょっと困ったことです。チャットで聞いたりしていますが、全体のグループで聞くのも気が引けるしなど、誰にどう聞こうか一瞬迷ってしまいます。

こんな場合に役に立ちそうなツールのβ版がリリースされたとのことなので紹介します。 チャット経由で「○○のファイル」という感じで質問するとSharePointの中に格納されているファイルを探してくれるそうです。 SharePointの通常の検索だとファイル名やキーワードが正確にわからずに探すのにはいつも苦労するのですが、このツールはファイル名が曖昧であっても近しいものを抽出して候補を表示することで、目的のファイルをチャットボットが探してくれるようです。

【「ENOKI5.0 SharePoint連携オプション」のβ版】

今ならβ版ということでトライアルができるようなので、Microsoft365やSharePointでファイル管理されている方は試してみてはいかがでしょうか?

2020年11月30日月曜日

【チャットボット】 無料トライアルの落とし穴

チャットボットの導入検討の際にトライアルをしてみるのはとても有効だと思います。最近は無料トライアルができる製品も増えてきました。導入するのにどんなデータが必要なのか?運用するのにメンテナンス性はどうなのかは検討しておきたいですよね。

トライアルをする場合の注意点がこちらの記事にありますので、ぜひ参考にして下さい。こういうのは実際やってみないと、なかなか気がつかないことかと思いますが、知っているかどうかでも評価にだいぶ差が出てきますね!

【チャットボット – 無料トライアルの落とし穴】

トライアルを考えている方の参考になれば幸いです!

2020年11月26日木曜日

【チャットボット】目的に合ったチャットボットを選ぶ

チャットボットを設置したサイトが最近多くなってきて、チャットボット製品も色々なものが数多く出ています。 見た目は同じなのでちょっと調査しただけでは違いがわかりにくくどれを選んでも同じに見えますが、用途や状況によって選ぶポイントがあるという記事を紹介します。

【お客様にマッチしたチャットボットを選ぶには?~チャットボットマッチングチャート~】

上記のチャートでは以下のような区分けで、有人対応/無人対応どちらにするか、無人対応するならどの方式がいいか説明していますので参考にしてもらえればと思います。

  • 有人チャット
  • 無人チャット
    • シナリオ型チャット
    • 機械学習型チャット
    • ハイブリッド型チャット

以上、チャットボットの選び方についてのご紹介でした。

2020年6月14日日曜日

MyBatisでヘッダ明細型のデータをINSERTする(自動採番もする)

MyBatisでヘッダ明細型のデータを扱うシリーズの3回目。今回はネストしたJavaオブジェクトをデータベースに新規作成する方法について書いてみたいと思う。またIDもデータベースで自動採番させようとちょっと欲張ったものにしている。 今回はSQLの都合上MySQLに特化した内容となっている。

今回のサンプルもいつもと同じ以下のクラスとテーブルを使用する。

  1. public class Student {  
  2.   int id;  
  3.   String name;  
  4.   Result[] result;  
  5. }  
  6.   
  7. public class Result {  
  8.   String course;  
  9.   int score;  
  10. }  

studentテーブル(ヘッダ)

id name
100 やまだ

resultテーブル(明細)

refid course score
100 英語 80
100 数学 90

データベースはMySQLを使用する。 idは連番を振りたいのでデータベースで自動採番させてしまおう、ということで以下のようにテーブル定義をした。

  1. CREATE TABLE student (  
  2.   id INTEGER NOT NULL AUTO_INCREMENT UNIQUE,  
  3.   name VARCHAR(100)  
  4. );  
  5.   
  6. CREATE TABLE result (  
  7.   refid INTEGER NOT NULL,  
  8.   course VARCHAR(100),  
  9.   score INTEGER  
  10. );  

MyBatisのmapper定義

さて、ヘッダ明細型のテーブルに対してJavaオブジェクトをINSERTするMyBatisのmapperの定義をする。 INSERTの処理としてまず思いつくのは、MyBatisの設定でstudentテーブルとresultテーブルにINSERTするmapperをそれぞれ作成してJavaコードから順に呼び出す方法だろう。この場合はStudentクラスのオブジェクトをMyBatis経由で書き込んだ後、resultの配列ごとにループを回してResultクラスのオブジェクトをMyBatis経由で書き込む処理となる。

しかし、ネストしたStudentクラスのオブジェクトをMyBatisに渡して、その中でネストした部分も書き込んでもらうことはできないだろうかということで、以下のようなmapperを作成した。

  1. <mapper namespace="mapper.student">  
  2.   <resultmap id="student" type="student">  
  3.     <id column="id" property="id" />  
  4.     <result column="name" property="name" />  
  5.   
  6.     <collection property="result" oftype="Result">  
  7.       <result column="course" property="course" />  
  8.       <result column="score" property="score" />  
  9.     </collection>  
  10.   </resultmap>  
  11.   
  12.   <insert id="create" parameterType="student" useGeneratedKeys="true" keyProperty="id">  
  13.     INSERT INTO student (name) VALUES (#{name});  
  14.     SET @uid = LAST_INSERT_ID();  
  15.     <if test="result != null">  
  16.       <foreach item="i" collection="result">  
  17.         INSERT INTO result (refid, course, source)  
  18.           VALUES (@uid, #{i.course}, #{i.source});  
  19.       </foreach>  
  20.     </if>  
  21.     SELECT @uid FROM dual;  
  22.   </insert>  
  23.   
  24. </mapper>  

まずは最初の "INSERT INTO student ~" でStudentクラスのオブジェクトをstudentテーブルに書き込む。

次の行で "SET @uid = LAST_INSERT_ID()" を行っているが、ここでstudentテーブルに書き込んで自動採番されたIDを取得している。 これはMySQL専用の構文となる。

次にMyBatisの動的SQLを使ってネストしたオブジェクトを1つづつINSERTする。
まず、<if test="result != null"> でStudentクラスのオブジェクトがネストしたResultオブジェクトを持っているか(nullでないか)を調べ、持っているなら <foreach item="i" collection="result"> でひとつづつ順にINSERT処理をしている。
resultテーブルではrefid列に紐づくstudentテーブルのidを保持するが、先にMySQLの変数 "@uid" に自動採番された値を保存しているので、その値を書き込んでいる。

自動採番された値はJavaのStudentクラスのオブジェクトにも反映したい。MyBatisの処理結果として返した値が反映されるので、最後に "SELECT @uid FROM dual" を実行して、自動採番された値を返している。

Javaコードから書き込み

以下のようなJavaコードでネストされたオブジェクトを1回のMyBatis呼び出しでヘッダ明細型のテーブルにINSERTできる。

  1. // 英語の結果  
  2. Result result_english = new Result();  
  3. result_english.course = "英語";  
  4. result_english.score = 50;  
  5.   
  6. // 英語の結果  
  7. Result result_math = new Result();  
  8. result_math.course = "数学";  
  9. result_math.score = 68;  
  10.   
  11. // 生徒の情報  
  12. // IDは自動採番されるため  
  13. Student student = new Student();  
  14. student.name = "たなか";  
  15. student.result = new Result[] { result_english, result_math };  
  16.   
  17. // オブジェクトをデータベースに書き込む  
  18. sqlSession.insert("mapper.student.create", student);  
  19.   
  20. // 自動採番された生徒のIDを表示  
  21. System.out.println("ID=" + student.id);  

おわりに:BadSqlGrammarExceptionが出た時

Springから使っていたらこんな例外が出てしまいました。

org.springframework.jdbc.BadSqlGrammarException: 
### Error updating database.  Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SET @uid = LAST_INSERT_ID();
		 
		SELECT @uid FROM dual' at line 3

今回はMyBatisのmapperで複数のステートメントを一度に実行していますが、MySQLのJDBCドライバの仕様で複数ステートメントを実行するときは "allowMultiQueries=true" オプションを指定する必要があるようです。JDBC接続のURLに以下のようにオプションを追加したらうまく動くようになりました。


jdbc.url=jdbc:mysql://localhost/student?allowMultiQueries=true

2020年5月26日火曜日

JavaのSimpleDateFormatで日付文字列チェックではまる

java.text.SimpleDateFormatを使って日付文字列をチェックしようとしてはまったときのメモ。 parseメソッドに文字列を与えてParseExceptionが出るか出ないかでチェックしようとした。

  1. SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd");  
  2.   
  3. // 不正な日付  
  4. Date d = fmt.parse("197405112"); // ParseExceptionが発生しない!!  

しかし、エラーとはならず、yyyy=1970、MM=05、dd=112と解釈され、5月112日→8月20日として、d=1974/8/20として通ってしまい予想外の動きになってしまった。 SimpleDateFormatはデフォルトだとできるだけ日付として解釈するように動作をするらしい。 日付を3桁で拾ってしまうのは予想外だったが・・・

存在しない日付を厳密にチェックするときはsetLenientをfalseに設定する必要があるようだ。 以下にすることでチェックをすることができた。

  1. SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd");  
  2.   
  3. // 厳密な日付チェックを行う設定  
  4. fmt.setLenient(false);  
  5.   
  6. // 不正な日付  
  7. Date d = fmt.parse("197405112"); // ParseException発生!!  

SimpleDateFormatはスレッドセーフではなく使いまわしが難しいので、そろそろ新しいスレッドセーフなDateTimeFormatterに移行するべきとは思うが、Dateを使っている手持ちライブラリも多く使い勝手の悪さからなかなか移行できていない・・・

2020年5月15日金曜日

MySQLでUnknown command '\''.がでる。

MySQL5.7でSQLを流した時にUnknown command '\''.がでる時の対処法。

どういう状況で出るのかはいまいちはっきりしていないが、UTF-8のファイルを流した時に出る? 5.6などでは同じSQLでも出ていなかったように思われる。 このようなときは--default-character-set=utf8オプションを指定してやると成功するようだ。

mysql -umydb -pmypass -Dmydb --default-character-set=utf8 < data.sql