実践的な例
実践的な例¶
このページでは、ドラマ作成時によくあるパターンと具体的な実装例を紹介します。
例: ドラマ開始時点からの経過時間でゲートを制御¶
ドラマの開始時点でstates.start_timestampを設定し、Gateのトリガ条件で経過時間を計算します。
必要なコンポーネント¶
graph LR
A[Entry] --> B[StateSet<br/>開始時刻記録]
B --> C{Gate<br/>時間判定}
C -->|30秒経過| D[次の処理...]
C -.->|30秒未満| E[スキップ]
style B fill:#e1f5ff
style C fill:#fff4e1
style D fill:#e8f5e9
style E fill:#ffebee 設定方法¶
1. StateSet - 開始時刻を記録¶
- モード :
once - キー :
start_timestamp - 値 :
lambda: time.time() if not states.get('start_timestamp') else Skip()
2. Gate - 経過時間でゲート開閉¶
- トリガ :
lambda: (time.time() - (states.start_timestamp or 0)) >= 30
応用例¶
複数の時間ゲート¶
graph LR
A[Entry] --> B[StateSet<br/>開始時刻記録]
B --> C1{Gate<br/>10秒}
B --> C2{Gate<br/>30秒}
B --> C3{Gate<br/>60秒}
C1 -->|10秒経過| D1[メッセージ1]
C2 -->|30秒経過| D2[メッセージ2]
C3 -->|60秒経過| D3[メッセージ3]
style B fill:#e1f5ff
style C1 fill:#fff4e1
style C2 fill:#fff4e1
style C3 fill:#fff4e1 各Gateに排他的な時間条件を設定:
- Gate1(10〜30秒) :
lambda: 10 <= (time.time() - (states.start_timestamp or 0)) < 30 - Gate2(30〜60秒) :
lambda: 30 <= (time.time() - (states.start_timestamp or 0)) < 60 - Gate3(60秒以上) :
lambda: (time.time() - (states.start_timestamp or 0)) >= 60
例: 状態が切り替わったタイミングで特定のsystemプロンプトを追加¶
DialogAddのconditionパラメータでprev_statesを使用して、stateの変化を検出します。
必要なコンポーネント¶
graph LR
A[処理] --> B[StateSet<br/>状態更新]
B --> C{DialogAdd<br/>条件判定}
C -->|状態変化あり| D[Systemメッセージ<br/>追加]
C -.->|変化なし| E[スキップ]
style B fill:#e1f5ff
style C fill:#fff4e1
style D fill:#e8f5e9
style E fill:#ffebee 設定方法¶
1. StateSet - 状態を更新¶
- モード :
once - キー :
conversation.phase - 値 :
values.new_phase
2. DialogAdd - 状態変化を検出してメッセージ追加¶
- ロール :
system - テキスト :
{{ "フェーズが" + states.conversation.phase|string + "に変わりました" }} - トリガ条件 :
lambda: prev_states and prev_states.get('conversation', {}).get('phase') != states.conversation.phase
さまざまな条件例¶
特定の値に変化したときのみメッセージ追加¶
# phaseが2になったときのみメッセージを追加
lambda: prev_states and prev_states.get('conversation', {}).get('phase') != 2 and states.conversation.phase == 2
テキスト:
複数の状態変化を検出¶
# phaseまたはlevelが変化したときにメッセージを追加
lambda: prev_states and (
prev_states.get('conversation', {}).get('phase') != states.conversation.phase or
prev_states.get('user', {}).get('level') != states.user.level
)
例: Structured Outputで盛り上がり判定¶
Structured Outputを使って、会話の盛り上がり度を判定し、Stateに保存します。
graph LR
A[DialogHistory] --> B[PublicLLM<br/>盛り上がり判定<br/>Structured Output]
B --> C[StateSet<br/>結果を保存]
style A fill:#e8f5e9
style B fill:#fff4e1
style C fill:#e1f5ff 設定方法¶
1. DialogHistory - 会話履歴を取得¶
- role_filter :
["system", "user*", "assistant"] - max_history_items :
10
2. PublicLLM - 盛り上がり判定(Structured Output)¶
- プロンプト :
会話の盛り上がり度を1〜5で判定してください。1が最も低い。
会話履歴:
{% for msg in values.messages %}
{{ msg.role }}: {{ msg.content }}
{% endfor %}
- 構造化出力スキーマ :
{
"type": "object",
"properties": {
"excitement": {
"type": "integer"
}
},
"required": ["excitement"]
}
3. StateSet - 結果を保存¶
- キー :
conversation.excitement - 値 :
values.response.excitement
例: 対話数に応じて会話履歴の詳細度を変える¶
直近10対話はsystem・metadataを含めて詳細に、それ以前はシンプルにPublicLLMに渡します。Jinjaテンプレートで実現します。
graph LR
A[Entry] --> B[DialogHistory<br/>limit=100]
B --> C[PublicLLM]
style B fill:#e8f5e9
style C fill:#fff4e1 設定方法¶
1. DialogHistory - 会話履歴を取得¶
- role_filter:
["system", "user*", "assistant"] - max_history_items:
100
2. PublicLLM - Jinjaで詳細度を制御¶
- プロンプト :
あなたは親切なアシスタントです。
会話履歴:
{% set recent_count = 10 %}
{% set total = values.history|length %}
{% for msg in values.history %}
{% if loop.index > total - recent_count %}
{{ msg.role }}: {{ msg.text }}{% if msg.meta %} (meta: {{ msg.meta }}){% endif %}
{% else %}
{% if msg.role != "system" %}{{ msg.role }}: {{ msg.text }}
{% endif %}
{% endif %}
{% endfor %}
出力例¶
15件の履歴がある場合(直近10件は詳細、それ以前5件はシンプル):
あなたは親切なアシスタントです。
会話履歴:
user: こんにちは
assistant: はじめまして!
user: 今日の天気は?
assistant: 晴れです。
user: ありがとう
system: あなたは親切なアシスタントです。
user: 最近どう? (meta: {'timestamp': 1234567890})
assistant: 元気ですよ!
user: 何か面白い話ある?
assistant: 昨日公園で猫を見ました。 (meta: {'emotion': 'happy'})
...
補足¶
loop.indexで現在のループ位置を取得- 直近10件(
total - recent_count以降)は詳細表示(meta付き、systemも含む) - それ以前はシンプル表示(systemを除外、metaなし)
例: クライアントから渡された会話履歴を使用¶
クライアント側で前回セッションの会話履歴をstates.historyにセットしてもらい、それを使って応答を生成します。
graph LR
A[Entry] --> B[PublicLLM<br/>履歴をStateから取得]
style B fill:#e8f5e9 クライアント側の設定¶
クライアントからstate.setで前回セッションの履歴をセットします:
{
"data": {
"history": [
{"role": "user", "text": "こんにちは"},
{"role": "assistant", "text": "こんにちは!何かお手伝いできますか?"}
]
}
}
設定方法¶
1. PublicLLM - Stateから履歴を取得¶
- プロンプト :
前回の会話履歴を要約してください。
{% if states.history %}
前回の会話履歴:
{% for msg in states.history %}
{{ msg.role }}: {{ msg.text }}
{% endfor %}
{% endif %}
例: 複数処理の完了を待ってからEventResponseを送信¶
DialogAdd、TTS3、PublicLLM(Structured Output)+StateSetの3つの処理が全て終了してからEventResponseを送信します。
graph TB
A[Entry] --> B[DialogAdd]
A --> C[TTS3]
A --> D[PublicLLM<br/>Structured Output]
D --> E[StateSet]
B --> F[EventResponse]
C --> F
E --> F
style B fill:#e1f5ff
style C fill:#e8f5e9
style D fill:#fff4e1
style E fill:#e1f5ff
style F fill:#ffe8e8 設定方法¶
1. EventResponse - 全処理完了後に送信¶
EventResponseに複数の入力を接続すると、すべての入力がis_last=Trueになるまで待機してから送信します。
- mode :
once - データ :
lambda values: {"status": "completed"}