コンテンツにスキップ

基礎知識

ドラマ作成者向けガイド - 基礎知識

このガイドでは、Marionetteでドラマを作成するための基礎知識を学びます。


ドラマとは

ドラマ は、Marionetteの会話シナリオです。
ドラマは、様々な Item をツリーのようにつなげることで、任意のシナリオを実現します。

ドラマのツリーは、AI発話を生成する度に一回呼ばれます 。シナリオ遷移ではなく、発話生成の度に上から下へ流れるように実行されます。
クライアント側からは、以下の順序で処理が呼ばれます:

  1. まず、ユーザーの発話や、ユーザーの状態をドラマに設定 (dialog.add, state.set)
  2. AI発話生成をトリガー (event.trigger)

ドラマ側では、このトリガを受け取り、最終的にAI発話や音声 を返すことが基本動作です (event.response)

graph TD
    A[Item1<br/>Entry] --> B[Item2<br/>DialogAdd]

    style A fill:#c8e6c9,stroke:#4caf50,color:#1b5e20
    style B fill:#e1bee7,stroke:#9c27b0,color:#4a148c
  • Itemは、箱で表されている要素。音声合成やRAGなど、特定の処理を行います
  • Linkは、Item同士の処理の順序を表します。その他にもいくつか機能を持っています:
    • 前のItemの処理結果の情報を次のItemに伝えます (Value)
    • 前のItemの処理が完了したかどうかを、次のItemに伝えます (is_last)

Entry

Entry は、ドラマの開始点となるItemです。外部からのイベント(event.trigger)を受け取り、ドラマの処理を開始します。すべてのドラマは、必ずEntryから始まります。

Group

Group は、複数のItemを組み合わせて再利用可能なコンポーネントとして扱う機能です。よく使う処理パターンをグループ化することで、ドラマの作成効率を向上できます。

Groupは画面上「タブ」として表現されています。「+」ボタンを押すことで追加可能です。
追加後は通常通りItemを追加していきますが、Group特有の特殊な概念も存在します:

  • GroupInを追加。そこが処理の開始地点となり、Groupの前の処理の流れやデータを受け取る
  • Group以降に出力したいデータや処理の流れがある場合は、GroupOutを追加し、そこにLinkをつなげる

重要

Groupでは、グループ専用の環境変数を設定できます。自由式の中で ${変数名} として参照すると、その値が展開されます。

同じGroupを複数の場所で使う際に、環境変数に異なる値を設定することで、同じ処理パターンを使いながら、それぞれ異なる挙動を実現できます。

使用例 : キャラクター発話用のGroupを作成し、環境変数 ${ai_name} を設定します。このGroupを2箇所で使用する際、一方では ai_name = "Tsuyoshi"、もう一方では ai_name = "Koichi" と設定することで、同じGroupを使いながら異なるキャラクターとして振る舞わせることができます。


DialogとStates

クライアントとサーバー側双方から参照と書き換えができる共通データベースとして、dialogstatesが用意されています。

  • dialog: 会話履歴を保持します。ユーザーとアシスタントの会話だけでなく、システムメッセージなども含みます。
  • states: なんでも保存できる変数です。任意の変数名を使えますし、ドットによる階層化も可能です。使用例:
    • ユーザー情報の保存: user.nickname, user.age
    • 前回会話の要約: conversation.summary
    • 会話進行管理: greeting.done, start_timestamp

これらは、内容が変化すると、サーバー・クライアント側にすぐに通知されます。

重要

Statesとは別に、そのツリーの中で前のItemから伝わってくる一時的な情報を扱うValueという概念存在します。Valueはクライアント側には伝わらない内部変数です。
Marionetteの中では、このDialog, States, Valueの3つを組み合わせながら、あらゆる処理を行います。


自由式

Marionetteでは、柔軟な処理を実現するために、自由に式を記入できる箇所が多く存在しています。

Jinja2

テキスト入力を柔軟に行うための書き方です。

こんにちは、{{ values.name }}さん!
{% if values.score >= 80 %}合格{% else %}不合格{% endif %}

Lambda式(短い処理向け)

lambda values: values.count + 1
lambda: states.phase == 1

Async関数(複雑な処理向け)

async def process(input_msg, output_msg):
    history = await input_msg.dialog.get_recent(limit=10)
    result = process_history(history)
    await output_msg.update("result", result, is_last=True)

重要

詳細は、式の書き方ガイドを参照してください。
また、これらはいずれも一般的なプログラミング言語のため、ネット検索やChatGPT等で自分で記述することも可能です。