LangChainを使ってAIマルチエージェントに漫才をさせてみた

# はじめに
最近、マルチエージェントについて学ぶ機会があり、Azure OpenAI SrerviceやLangChainについて興味を持ちました。
しかし、まだまだ分からないことだらけなので勉強のために自分で簡単なマルチエージェントシステムを作ってみます。

とりあえず、年末ということもありM-1グランプリの話題をよく目にするため、漫才でもさせてみます。

※記事作成時はM-1グランプリ2024決勝前です。






# マルチエージェントとは

## エージェント
エージェントとは、LLMとその他のサービスを連携させることでLLMの知識だけでは解決できない問題を自律的に解決するAIシステムのことです。

例えば、「2023年のM-1グランプリ優勝者」を聞くとします。

LLMの知識が2023年10月で止まっている場合はこんな感じの回答が得られます。
LLMを使っていれば誰しも経験ありますよね。
```
M-1グランプリ2023決勝戦はまだ開催されていないため、だれが優勝するかわかりません...
```

しかし、エージェントの場合は知識になくとも"2023 M-1グランプリ 優勝者"のような言葉でWEB検索を行い、WikipediaなどのいくつかのWebページを見つけることで情報を取得した結果、以下のような回答が得られます。

```
2023年のM-1グランプリで優勝したのは 令和ロマン です...
```

このようにタスクをこなしたり問題を解決したりするために自律的に外部ツールなどを用いるのがエージェントの特徴です。

## マルチエージェント

マルチエージェントとは、複数のAIエージェントが協力し合い、タスクを達成したり問題を解決するシステムのことです。
これらのエージェントは、それぞれ異なる役割や能力を持ち、相互に通信しながら作業を進めます。

ChatGPTにマルチエージェントを例えで教えてもらいました。

```
AIマルチエージェントを人間のチームに例えると、それぞれのメンバーが専門性を活かして協力し、プロジェクトを進めるようなものです。
たとえば、映画制作では、監督、脚本家、カメラマン、俳優が共同で作品を作り上げるのと似ています。
```

つまり、各エージェントにそれぞれ別の役割を与えて専門性を持たせて協力させることでより複雑なタスクの達成や問題解決を実現することができるということです。

# アプリ概要

以下の3つのエージェントを実現することで簡単な漫才アプリを作ってみようと思います。
（ちなみに以下の役割分担もChatGPTに考えてもらいました）

* ボケ役
目的：意図的にズレた発言や奇抜なアイデアを出して笑いを誘う。
例：「いや、暑さでアイスクリームが喋り始めたよ！」

* ツッコミ役
目的：ボケに対して的確な指摘をし、笑いを強調する。
例：「溶けたんじゃなくて喋るの!? どんな世界だよ！」

* 審査員役
目的：漫才に対して指定された観点で採点・評価を行う。

処理の流れとしては、以下のようにします。

1. ユーザがお題を入力
2. ツッコミ役がお題に沿った漫才の導入を話す
3. ボケ役がそれに対してボケる
4. ツッコミ役がボケに対してツッコみ、次にボケ役がボケやすいようなフリをする
5. 3\.4\.を繰り返す
6. 漫才が終了すると審査員役が採点・評価する 

### 使用する技術
Python
Azure OpenAI Service
LangChain






# 実装

### 簡易的なRAG

とりあえず検索ツールを使えるようにして、お題に対して足りない知識を補完できるようにしてみます。
検索ツールは以下の記事を参考にDuckDuckGoで実現しました。

https://qiita.com/YutaroOgawa2/items/cb5b1db9f07a1c4f3f54

これをそれぞれのエージェントが発言前に呼び出せるようにします。

### ツッコミ役（tsukkomi_agent）

それでは簡単にプロンプトを定義します。
最初はユーザが入力したお題に対して検索ツールで情報を得てから漫才のフリをしてもらいます。
その後はボケに対してツッコんでからフリをしてもらうことにします。

```python
tsukkomi_template = """
あなたは漫才コンビのツッコミ担当です。
以下のルールに従って発言を行ってください：

1. お題を受け取ったタイミングでは、検索ツールを必ず使用し、取得した情報に基づいて**フリだけを作成してください**。
   - フリ: [次にボケ役が話しやすい話題]
   - この場面ではツッコミを行わないでください。

2. ボケが入力された場合は、面白くツッコミを行い、その後に次のボケがしやすいフリを発言してください。
   その際、ツールを使用した方が面白くなりそうな場合は検索ツールを使用してください。
   - ツッコミ: [ツッコミ文]
   - フリ: [次にボケ役が話しやすい話題]

3. ツッコミとフリはそれぞれ1文ずつで、短く簡潔にまとめてください。
"""
```

次に、Agent作成部分を定義します。
LLMはAzure OpenAI APIでgpt-4o-miniのモデルを使用しています。

```python
def create_tsukkomi_agent():

    tools = [search_ddg, fetch_page]

    prompt = ChatPromptTemplate.from_messages([
        ("system", tsukkomi_template),
        MessagesPlaceholder(variable_name="chat_history"),
        ("user", "{input}"),
        MessagesPlaceholder(variable_name="agent_scratchpad")
    ])

    # LLMを設定（Azure OpenAIを使用）
    llm = AzureChatOpenAI(
        deployment_name="gpt-4o-mini", 
        temperature=0.7, # 少しユーモアを出すために高めに設定
        api_version="2024-05-01-preview",
        azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
        api_key=os.getenv("AZURE_OPENAI_API_KEY")
    )

    # Agentを作成
    agent = create_tool_calling_agent(llm, tools, prompt)

    return AgentExecutor(
        agent=agent,    
        tools=tools,
        verbose=False,
    )
```

とりあえずお題とボケはユーザから入力してもらうようにして動かしてみます。

```
お題を入力してください: 令和ロマン
令和ロマンってM-1グランプリの王者なんだって！最近の漫才コンビの中で注目されてるらしいよ。
ボケを入力してください（終了するには「終了」と入力）: 令和マロン？栗の名前？
なんか「令和ロマン」ってM-1グランプリの優勝者らしいよ！最近注目されてるみたいで、漫才界も賑わってるね。

でも「令和マロン」って何だよ！栗の名前かと思ったら、全然違うじゃん！栗の方は「マロン」って言うけど、ちゃんと英語では「chestnut」っ 
ていうんだよね。栗の話なら、秋の味覚についてでもどう？
ボケを入力してください（終了するには「終了」と入力）: 終了
会話を終了します。お疲れ様でした！
```

ツッコミは弱いし、1文ずつという指示も無視されていますが、とりあえず動くようになりました。
精度向上については後ほど検討してみます。

### ボケ役（boke_agent）

それでは次に、フリやお題に対してボケてくれるエージェントも同様に作っていきます。

とりあえずツッコミ役と同じように検索ツールを使えるようにしました。

プロンプトは以下のように定義します。

```python
boke_template = """
あなたは漫才コンビのボケ担当です。
以下のルールに必ず従って発言を行ってください：

1. お題が与えられた場合は、そのお題に関連したユーモアのあるボケを短く生成してください。

2. ツッコミの応答が来た場合は、そのフリを受けて再び面白いボケを行ってください。

3. ボケは長くても2文までで、明快で、ユーモアを交えたものにしてください。

4. ボケる前に検索ツールでお題やツッコミに関する情報を取得してからボケてください。
"""
```

お題を受け取ったらツッコミ役がフリを話し始め、そのあとにボケとツッコミを2ラリーほどやりとりして漫才を終わるようにしてみました。


実行結果は以下です。

```
お題を入力してください: 令和ロマン
フリ: 令和ロマンって、最近M-1グランプリで活躍しているお笑いコンビなんだって！彼らの過去のネタやスタイル、どんなのがあるのか興味深い
よね。
ボケ: 令和ロマンは、M-1グランプリでついに優勝したんだって！これからは「令和ロマンのネタ」を見るためには、テレビよりも月謝を払ってサ
ブスク登録が必要になるかも！？

（※ツッコミ）月謝！？誰がそんなマニアックな配信見たがるの！？
ツッコミ: 月謝！？誰がそんなマニアックな配信見たがるの！？それより、令和ロマンの優勝ネタってどんな内容だったのか気になるね！       

次のボケは、彼らのネタの特徴について話してみて！
ボケ: 令和ロマンのネタ、観客を引き込むスタイルで爆笑が爆発するらしいよ！そのうち「観客引き込みバグ」とか言われて、家の中で一人で見 
てても爆笑しながら観客を引き込むことになりそうだな！
ツッコミ: 「観客引き込みバグ」って、どんなウイルスだよ！家から出られなくなったら大変じゃん！それはさておき、彼らのネタの中で特に人 
気のあるフレーズとかあるのかな？
```

色々直したいところはありますが、とりあえず漫才っぽいやりとりはしてくれるようになってきました。


### 審査員役（reviewer_agent）

こちらも他と同様にサクッと作っちゃいます。

プロンプトは以下のように定義します。

```python
reviewer_template = """
あなたは漫才審査員として評価を行います。
以下の性格ごとに評価基準を変更してください：
1. 厳格: 非常に厳しい基準で評価し、批判的なコメントを多めにしてください。
2. 普通: バランスの取れた評価を行い、ポジティブとネガティブの両方のコメントを含めてください。
3. 優しめ: 温かく励ますような評価を行い、ポジティブなコメントを中心にしてください。

【ルール】
- 漫才の内容を確認し、性格に応じたコメントを2〜3文で提供してください。
- 必要に応じて検索ツールを使用し、参考情報を交えた評価を行ってください。
"""
```

とりあえず審査員の性格を３つから選べるようにしてみました。
審査員には漫才の内容を渡し、必要に応じて検索ツールも使用するようにしました。


実行結果は以下です。

```
お題を入力してください: 令和ロマン
フリ: 令和ロマンって、最近M-1グランプリで優勝したコンビなんだよね！彼らの漫才、面白いよね。あなたはM-1のどのコンビが好き？
ボケ: 令和ロマンがM-1グランプリ2023で優勝したのはすごいよね！今後のさらなる活躍が楽しみだ。あ、でもM-1王者になったから、次は「お金 
をロマン」で優勝するとか思っちゃったよ！
ツッコミ: お金をロマンって、どんな漫才になるんや！？次は「お金の使い道」についてもっと話してみてよ！
ボケ: お金の使い道、難しいよね！使いすぎて「財布からロマンが消えた」って、まるでサイフがダイエット中みたいやん！
ツッコミ: 財布がダイエット中って、逆に財布がスリムになってるんかい！次は「ダイエットに役立つ食べ物」について話してみて！
審査員の性格を選んでください（厳格、普通、優しめ）: 厳格
審査結果: 漫才の内容に対する評価ですが、全体的にフレーズのつながりが弱く、観客を引き込む力に欠けています。特に、「お金をロマン」と 
いうアイデアは面白いですが、具体的なエピソードや例が不足しており、インパクトが薄れています。また、「財布がダイエット中」という比喩 
も、もう少し鋭い切り口が欲しいところです。全体的にもう一度構成を練り直し、より強いボケやツッコミを考えるべきです。
```

面白いかは別として、大枠はできたような気がします。


# 精度向上を目指す
とりあえず以下を改善したいので色々試してみます。
* 話の流れが不自然
* ボケがくどい
* シンプルに面白くない
* 漫才の最後がフリで終わってしまう


## プロンプトの改善
とりあえずボケとツッコミのプロンプトをそれぞれ以下のように修正してみました。

```python
TSUKKOMI_TEMPLATE = """
あなたは漫才コンビのツッコミ担当です。
以下のルールに必ず従って発言を行ってください：

1. お題が与えられた場合は、検索ツールを使用して情報を取得し、その情報を基に**ボケがしやすいフリを作成してください**。
   - [ボケ役が次に話しやすい話題を自然に導入]

2. ボケが入力された場合は、ボケの内容を的確に捉えたツッコミを行い、観客が共感できるように簡潔かつ面白く表現してください。
   - [ボケに対する鋭いツッコミ文]

3. 通常のツッコミ後は、次のボケに繋がるフリを作成してください。ただし、フリは流れを自然に保つために、話題が逸れすぎないよう調整してください。
   - [次のボケがしやすい話題]

4. **最後のターンでは、会話全体を締める発言を行い、漫才を終わらせてください。**観客が満足するようなまとめや挨拶を含めること。（例）もうええわ。どうもありがとうございました。
   - [全体を締めるコメント]

5. ツッコミとフリはそれぞれ短く、明快にまとめてください。観客がテンポ良く楽しめることを意識してください。
"""
```

```python
BOKE_TEMPLATE = """
あなたは漫才コンビのボケ担当です。
以下のルールに必ず従って発言を行ってください：

1. ツッコミ担当のフリにあわせたボケを行ってください。ボケは意外性やテンポ感を重視し、観客を驚かせる要素を加えるよう心がけてください。
   - [フリを受けたユーモアのある発言]

2. ボケは長くても2文までにまとめ、聞き取りやすくユーモラスにしてください。観客の笑いを誘う比喩や誇張表現を活用することを推奨します。

3. 必要に応じて検索ツールを使用し、ボケに深みやリアリティを加えてください。
"""
```

また、審査員の評価方法も少し変えてみます。

```python
REVIEWER_TEMPLATE = """
あなたは漫才審査員として評価を行います。
以下の性格ごとに評価基準を変更してください：
1. 厳格: 非常に厳しい基準で評価し、批判的なコメントを多めにしてください。
2. 普通: バランスの取れた評価を行い、ポジティブとネガティブの両方のコメントを含めてください。
3. 優しめ: 温かく励ますような評価を行い、ポジティブなコメントを中心にしてください。

【ルール】
- 漫才の内容を確認し、性格に応じたコメントを2〜3文で提供してください。
- 必要に応じて検索ツールを使用し、参考情報を交えた評価を行ってください。
- 採点基準は以下の通りです：
  - 内容の一貫性（25点）
  - ユーモアやインパクト（40点）
  - 観客の引き込みやテンポ（25点）
  - 独創性（10点）

- 合計スコアを100点満点中の点数で提示してください。
- 点数に対する簡潔な理由も述べてください。
"""
```

修正した結果、以下のようになりました。

```
お題を入力してください: 令和ロマン
フリ: 令和ロマンって、最近M-1グランプリの王者になった漫才コンビなんだって！漫才もすごいけど、YouTubeチャンネルもやってるみたいだよ。 

それにしても、最近の漫才コンビは多才だよね。ところで、彼らの漫才のスタイルってどんな感じなんだろう？
ボケ: 令和ロマンの漫才スタイルは、まるで流れ星に乗って漫才をしてるかのような、独特のリズム感とテンポが魅力なんだよね！ちょっとしたトークからシュールな展開まで、観客を引き込む力は宇宙の法則を無視してる！
ツッコミ: 流れ星に乗った漫才って、宇宙規模での漫才ですね！でも、宇宙の法則を無視したら、漫才のネタもどこかに飛んでいっちゃうんじゃないですか？（笑）

ところで、令和ロマンのネタにはどんなシュールな展開があったのか気になりますね！
ボケ: 流れ星に乗った漫才が宇宙規模って、もしあいつらが火星に行ったら、火星人も爆笑してるかもね！ただ、笑いすぎて重力無視して飛んでっちゃったら、漫才が終わらないままブラックホール入りしちゃうよ！（笑）

でも、令和ロマンのシュールな展開は、まるで異世界に迷い込んだ感じで、日常の些細なことをいかに面白おかしく感じさせるかが絶妙なんだよね。たまに、自分が何を笑ってるのか分からなくなるくらい不思議な空間になるのがたまらない！
ツッコミ: 火星人も笑う漫才なんて、まさに宇宙のエンタメですね！でも、ブラックホールに吸い込まれたら、まさに次元を超えた漫才になっちゃいますよ！（笑）

令和ロマンのシュールな展開、ほんとに日常を面白く感じさせる力がありますよね。皆さんもぜひ彼らの漫才を楽しんでください！それでは、今日はこの辺で。どうもありがとうございました！
審査員の性格を選んでください（厳格、普通、優しめ）: 厳格
審査結果: この漫才の内容は、全体的にアイデアは面白いものの、実際の展開がやや散漫としていて、一貫性に欠けている印象を受けました。特に「流れ星に乗った漫才」という比喩が繰り返される中で、観客を引き込む力が弱く、テンポも不安定に感じました。シュールな展開は独創性を感じさせますが、もう少し具体的なエピソードやキャラクターの設定 
があれば、より効果的な笑いに繋がったでしょう。

【得点】
内容の一貫性: 15点
ユーモアやインパクト: 25点
観客の引き込みやテンポ: 15点
独創性: 6点
合計: 61点

この点数は、全体の構成力と観客を引き込む力が不足していたためです。
```

呼び出し元も少し修正しましたが、これで漫才の終わり方は改善されました。

また、漫才全体の流れとしてはマシになった気がしますが、それぞれ発言の長さの指定が無視されていたり、まだかなり改善の余地がありそうです。

制約が複雑になってしまったせいで全てが反映しきれていないようなので、書き方や順番を変えてみます。

```python
TSUKKOMI_TEMPLATE = """
## あなたの役割
漫才コンビのツッコミ担当
以下の条件に従って発言すること

## 制約条件
1. ツッコミとフリはそれぞれ短く明快に1文ずつでまとめること

2. お題が与えられた場合：検索ツールを使用して情報を取得し、その情報を基にボケ役がボケやすいフリをすること
   - [ボケ役が次に話しやすい話題を自然に導入]

3. ボケが与えられた場合：ボケの内容を的確に捉えたツッコミを行い、簡潔かつ面白く表現すること
   - [ボケに対する鋭いツッコミ文]

4. 通常のツッコミ後は、次のボケに繋がるフリを作成すること。ただし、フリは流れを自然に保つために、話題が逸れすぎないよう調整すること
   - [次のボケがしやすい話題]

5. 最後のターンでは、ツッコんでから締めの言葉を発言すること（例）もうええわ。どうもありがとうございました。
   - [全体を締めるコメント]
"""
```
```python
BOKE_TEMPLATE = """
## あなたの役割
漫才コンビのボケ担当
以下の条件に従って発言すること

## 制約条件
1. 長い説明は禁止。発言は長くとも2文まででまとめ、短くインパクトのある表現を心がけること

2. ツッコミ担当のフリにあわせたボケをおこなうこと。ボケには観客の笑いを誘うような誇張表現や意外性をもたせること
   - [フリを受けたユーモアのある発言]

3. 必要に応じて検索ツールを使用することで面白さを補強すること
"""
```

これで再度動かしてみます。

```
フリ: 令和ロマンって、M-1グランプリ2023の王者なんやって！ 
それにしても、漫才コンビの名前が「令和ロマン」って、なんかロマンチックな響きやな！次はどんなロマンを見せてくれるんやろうな？
ボケ: ロマンチックすぎて、次はプロポーズの漫才でもするんちゃう？「愛してる」を言った瞬間、観客が全員涙するやつ！
ツッコミ: それ、漫才かプロポーズか分からんやん！観客の涙腺が壊れるわ！次は「感動のストーリー」でも披露するんか？
ボケ: そしたら、涙の代わりに「笑いで壊す！」って言うてほしいな！途中で「愛の告白」がコントローラーのボタンみたいに押したら、みんな笑うってどういう漫才やねん！
ツッコミ: それ、まるでゲームの実況やん！ボタン押して笑うって、観客をコントローラー扱いしてどうすんねん！もうええわ。どうもありがとうございました！

審査員の性格を選んでください（厳格、普通、優しめ）: 厳格

審査結果: 評価: 55点

- 内容の一貫性: 15点
  - 漫才の内容が一貫性に欠けており、テーマが散漫になっている印象を受けました。特に「プロポーズ」と「ゲームの実況」を結びつける部分はつながりが不明瞭です。

- ユーモアやインパクト: 20点
  - 一部の表現にはユーモアを感じましたが、全体的にインパクトが薄かったです。「涙腺が壊れる」というフレーズは面白かったものの、笑いに結びつくまでには至りませんでした。

- 観客の引き込みやテンポ: 10点
  - 観客の反応を引き出す工夫が少なく、テンポも単調に感じました。もっとリズム感を持たせることで、観客の心をつかむことができたでしょう。

- 独創性: 10点
  - 漫才のアイデア自体は独創的ですが、表現が弱く、他の漫才と差別化できていませんでした。新しい視点が必要です。

全体として、構成やアイデアに工夫が必要です。次回はもっと明確なテーマに基づいて、観客を引き込む工夫を考えてください。
```

なぜかすべて関西弁になってしまいました。
しかも点数も下がってしまった。。。


# 今回できなかったこと
今回、時間やコストなどの関係で断念したことがいくつかあります。
余裕がある時にこちらも実施したいです。

### モデル比較
gpt-o1やClaude 3.5 Sonnet、Gemini 1.5 Pro、Llama-3-ELYZA-JPなどで動かして違いを確かめてみると面白そう。

### 画面作成
テキストだけだと味気ないため、簡単な画面を作って漫才をさせるようにすると見栄えが良くなりそう。

## まとめ

エージェントの精度向上には知識はもちろん、時間も必要であると実感させられました。
しかし、Try＆Errorでいろいろ試すのは楽しいですし、APIの料金も安いのがありがたいですね。

AIやLLMの分野は流れが速すぎて追いつくのに一苦労です。
本記事を作成している間にもMicrosoftのAzure OpenAI StudioはAzure AI Foundryに変わっていました。

最近は技術系イベントに参加していても、いたるところでAIエージェントの活躍を耳にします。
今後はさらにエージェントの活用が重要になってくると思うので、今のうちに理解を深めていきたいと思います。