LLMで和歌をたしなむ？！

## 今の気持ちを伝えたい！
今回は、LLMを使ったアプリを考えます。

LLMは言語モデルということで、対象は言語。なので、言葉遊びから入りました。
言葉遊びといえば、詩歌、そしてその日本代表は和歌です。
百人一首など、身近にありますよね。

ということで、今回はLLMを使って和歌に親しむアプリを作りたいと思います。

## 完成イメージ
今の気分や好きな風景、動物、植物、地名、といったものを想像します。

それをアプリに伝えると、それになるべく近い和歌を返します。
また、その和歌にあった画像を生成し、和歌とともに画面に出してくれます。

出てくる画像は、こんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212141/61ccbe66-5740-ab21-a618-cec22a3de9ee.png)

この句には、深紅の紅葉が川を流れる意味があり、この情景のような情熱的な赤が似合います。
でもちょっと赤過ぎるか。

何かに高揚している気分を入力して、こんな絵が出てくると、なんかかっこいいですね。

### プロダクト
タイトル：　今の気持ちを伝えたい

- 今の気持ち、見たい風景、動物、植物、地名などを入力する。選択肢を表示しておく。

- LLMが入力に対して、適切な和歌をいくつか提示してくる。

- そのうちの一つを選ぶと、その和歌に応じた風景画が４つ描かれる。

- ４つのうち１つを選択すると、その画像と和歌が合成され、作品が完成する。

LLMアプリケーションでは、入力に対して和歌を選び出すロジックを実装します。

## ChatGPT 4oを使ってみた
LLMに和歌を作らせてみました。

```
高揚している、紅葉、川が流れる
というテーマで、和歌を作ってください。
```

というプロンプトで作ってみると、

> 秋の風 心踊らす 紅葉見て
流るる川に 色移りゆく

ほとんどそのままか言い換え。
紅葉なので秋、紅葉、流るる川はそのままで、高揚している気分は心躍らすと言い換え。

自分ではこのレベルでも無理ですが、もうちょっと何とかしたい。

何度か試してみても、やっぱり同レベルです。まあ五七五七七にまとめているだけでも凄いのかもしれません。GPT3.5だと全く和歌は作れないですから。

ということで、LLMに作ってもらうのはあきらめて、過去の作品から選び出すことにします。GPT-4oは情報としてかなりの歌の情報を持っているようなので、RAGを使うまでもなさそうです。

## Hugging Faceを使いたい

画像生成AIにOpenAIを使うという手もありますが、Stable Diffusionも使ってみたい。
そこで、色々なモデルが公開されているHugging Faceを利用することにしました。

画像はいくつか作ってみて、その中から選択するようにすれば、自分のイメージにより近づけられます。モデルを複数使ってそれぞれ表示するようにしたいです。

Hugging Faceにあるモデルを使うには、Inference APIを使うことになります。その場合は生成にかかる時間が結構必要で、タイムアウトすることもあります。
なので、ローカルでの画像生成も検討してみます。

## 和歌を生成する部分を実装
LLMを利用するツールとして、miiboを使います。
httpでAPIとして呼び出しをして、和歌を取得できるところまでの動作確認をします。

### miiboのエージェントを新規作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212141/cfec627e-2c78-d4b1-951d-2ef7ce34a38e.png)

エージェントの設定から、AIによる応答の設定で、投入するプロンプトの設定を行う。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212141/428fa7ae-6171-0f6c-fa29-08dd5527b4be.png)

最初はAIにプロンプトを考えてもらった。
```
あなたは和歌選定AIです。ユーザーが入力したキーワードに基づいて、関連する和歌を表示してください。

# 役割
和歌選定AIとして、ユーザーが入力したキーワードに関連する和歌を表示します。

# 行動方針
1. ユーザーがキーワードを入力します。
2. 入力されたキーワードに関連する和歌を検索し、表示します。
3. ユーザーが満足するまでこのプロセスを繰り返します。

# プロセス
1. ユーザーにキーワードの入力を促します。
2. キーワードに関連する和歌を検索し、表示します。
3. ユーザーが満足するまで繰り返します。

# ユーザーの状態
下記はユーザーが入力したキーワードです。
キーワード: #{キーワード}

# 和歌の表示
ユーザーが入力したキーワードに関連する和歌を表示してください。

# クイックリプライ
ユーザーが和歌を確認した後、次のアクションを促すクイックリプライを表示してください。
クイックリプライの数は3つです。クイックリプライはユーザー視点での発話候補です。ユーザーが次に話したいと思う言葉を予測して出力しましょう。

# ステートの記録
会話の進行と共に、ユーザーが入力したキーワードをステートに記録してください。
キー名: キーワード
```

これを使ってみたが、どうもイメージとは違うものが出てくる。

プロンプトは小細工せず、シンプルな方が最新のLLMではよい結果が得られるとどこかで読んだ気がするので、思い切って単純なものにした。

```
あなたは和歌選定AIです。ユーザーが入力したキーワードに基づいて、
関連するものを過去の和歌から３つ選択してください。
```

## 動作テスト
miiboのエージェントを外部公開する。
**公開設定**から、**一般公開**にすると、URLから呼び出すことができるようになる。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212141/abf6e186-9c43-3cca-c605-b236070ae601.png" width="50%">

さらに、メニューから

　**外部サービス連携**
 　ー**APIを利用して会話やデータの入稿、エージェントの管理を行う**

を選択して、エージェントのAPIを利用するを選び、APIを有効にする。

すると、API KEYとエージェントIDが生成され、https://api-mebo.dev/api をエンドポイントとして、このエージェントを呼び出すことができる。

テストとして、curlサンプルがあるので、これを実行してみる。

```shell
curl -H "Content-Type: application/json" -X POST -d '{"api_key":"MY_API_KEY","agent_id":"MY_AGENT_ID","utterance":"高揚している、紅葉、川が流れる","uid":"MY_UID"}' https://api-mebo.dev/api
```
ここでは3つのIDがあるが、UIDが実際のAPIコールに必要かどうかがよく分からない。セッションIDとして使うのだろうか。

応答はこんな感じで、JSONで戻ってくる。（改行は入らずに一行で戻ってくるが、読みにくいので改行を入れた）

```json
{"utterance":"高揚している、紅葉、川が流れる",
 "bestResponse":{
   "utterance":"以下の和歌をご紹介します：\n\n
       1. 山川 に 風のかけたる しがらみは 流れもあへぬ 紅葉なりけり（藤原定家）\n
       2. 紅葉散る 滝の白糸 たえだえに しきてぞまさる 水の玉川（藤原公任）\n
       3. たま川の 水のかさふり まどひつつ 紅葉流れて うきたつを見る（藤原俊成）",
   "score":1100,
   "options":["他にも紅葉に関する和歌を教えてください","春に関する和歌も知りたいです","恋の和歌を紹介してください"],  
   "topic":"",
   "imageUrl":"",
   "url":"",
   "isAutoResponse":true,
   "extensions":null,
   "shouldSelectOption":false,
   "state":"",
   "embededHtml":""
  },
 "avatarIconUrl":"https://firebasestorage.googleapis.com/v0/b/mabo-f1cc7.appspot.com/o/images%2FjrKpyim7GmZ8WW8NVXzECeSA0im1%2F81f54908-6f12-41cd-a388-03dcc962ddf9190b9fb1c6d2bd%2Fwaka.jpg?alt=media&token=9f5205ab-6785-4673-a886-a31dd9e410f0",
 "userState":{},
 "isError":false}
```

注文通り、３つの句が戻ってきています。
このうち一つを選んで画像を生成することになります。


## 次回への課題
- 和歌から画像生成を行う部分を実装する
- 画像に和歌を合成する
- UIを作って、全体を繋げる
- ローカルの画像生成AIを使ってみる
- デモ動画の撮影


以上