(builtin_blocks)= # 組み込みブロッククラスの仕様 (llm_dialogue)= ## LLM Dialogue (大規模言語モデルベースの対話ブロック) (`dialbb.builtin_blocks.llm_dialogue.LLMDialogue`) 大規模言語モデル(LLM)を用いて対話を行います. ### 入出力 - 入力 - `aux_data`: 補助データ(辞書型) - `dialogue_history`: 対話履歴 (辞書型のリスト) - 出力 - `system_utterance`: 入力文字列(文字列) - `aux_data`: 補助データ(辞書型) - `final`: 対話終了かどうかのフラグ(ブール値) ### ブロックコンフィギュレーションのパラメータ - `first_system_utterance` (文字列,デフォルト値は`""`) 対話の最初のシステム発話です. - `user_name` (文字列,デフォルト値は日本語の場合`"ユーザ"`, その他は`"User"`) LLMのプロンプトに対話履歴を与えるときに使う文字列です. - `system_name` (文字列,デフォルト値は日本語の場合`"システム"`, その他は`"System"`) LLMのプロンプトに対話履歴を与えるときに使う文字列です. - `prompt_template` (文字列) システム発話の生成をLLMに行わせるプロンプトを記述したファイル名です.アプリケーションディレクトリからの相対で記述します. - `model` (文字列,デフォルト値は`gpt-5.4-nano`) モデル指定文字列です.`provider:model_name` の形式で指定します(langchainの[init_chat_modelで指定する形式](https://reference.langchain.com/python/langchain/chat_models/base/init_chat_model)です).例:`google_genai:gemini-2.0-flash-001`.ただし,`gpt-5.4-nano` のようなOpenAIのGPTモデルは `openai:` を省略できます. モデルによっては環境変数でキーを指定する必要があります.例えば`gpt-5.4-nano` のようなOpenAIのGPTモデルを用いる場合は,`OPENAI_API_KEY`を指定します. - `temperature` (float,デフォルト値は`0.7`) LLM呼び出しの際の温度パラメータです.LLMが`gpt-5x`の場合は無視されます. - `instruction` (文字列, デフォルト値は[このファイル](https://github.com/c4a-ri/dialbb/blob/main/dialbb/util/globals.py)を参照.) システムロールのメッセージとしてLLMに送られる指示です. - `multi_party` (ブール値.デフォルト値: `false`) この値が`true`のとき,プロンプトに入る対話履歴で`user_id`の値が用いられます.これにより複数のユーザの発話の区別がLLMにつくようになります. ### 処理内容 - 対話の最初はブロックコンフィギュレーションの`first_system_utterance`の値をシステム発話として返します. - 2回目以降のターンでは,プロンプトテンプレートの末尾に対話履歴を与えてLLMに発話を生成させ,返ってきた文字列をシステム発話として返します.プロンプトテンプレートにプレースホルダが含まれている場合の処理は後述します. - 対話履歴の形式は以下です. ``` <コンフィギュレーションのsystem_name>: <システム発話> <コンフィギュレーションのuser_name>: <ユーザ発話> ... <コンフィギュレーションのsystem_name>: <システム発話> <コンフィギュレーションのuser_name>: <ユーザ発話> ``` - `aux_data`は基本的に出力と同じものが出力されますが,{numref}`extract_aux_data`で述べるようにシステム発話文字列に`aux_data`をアップデートする内容が含まれている場合は,それに従ってアップデートされます. - 出力の`final`は常に`False`です. ### プロンプトテンプレート内のプレースホルダ - プロンプトテンプレート内では,以下のプレースホルダが利用できます. - `{current_time}` 対話の行われている時点の年月日,曜日,時分秒を表す文字列で置き換えられる. - `{<アルファベット,数字,アンダースコアのみからなる任意の文字列>}` 文字列が`aux_data`のキーにあれば,その値を文字列に変換したもので置き換えらる. - プレースホルダの削除 もし置き換えられないプレースホルダが残っていて,それが`[[[`と`]]]`で囲まれていれば,その部分は消去されます. - `{dialogue_history}`をテンプレートに記述する必要はありません. (extract_aux_data)= ### システム発話からのaux_dataの抽出 出力のシステム発話文字列の最後に `(: , : , ... : )`の形の文字列があるとき,この部分は発話文字列から削除され,出力の`aux_data`に`{””: ””, ””: ””, ... ””: ””}`が付け加わります.(実際にはupdateされるので,同じキーがあれば値が上書きされます.)クライアントの制御に用いることができます. 例: - システム発話文字列 :`"こんにちは (emotion:happy)"` - 最終的なシステム発話:`"こんにちは"`, `aux_data`のアップデート:`{"emotion": "happy"}` キーはアルファベット,数字,アンダースコアの並びでないといけません. (passage_retrieval)= ## Passage Retrieval (RAG用のパッセージ検索ブロック) (`dialbb.builtin_blocks.passage_retrieval.Retriever`) RAG(Retrieval-Augmented Generation)のために,文書集合からユーザ発話に関連するパッセージを検索します. 起動時に指定された文書ファイル群を読み込み,ベクトルDBを構築します.実行時には直近のユーザ発話を検索クエリとして類似検索を行い,検索結果を`aux_data["passages"]`に格納します. ### 入出力 - 入力 - `dialogue_history`: 対話履歴 メインモジュールが保持している対話履歴です.直近のユーザ発話が検索クエリとして使われます. - `aux_data`: 補助データ(辞書型) メインモジュールに`aux_data`がない時は,`{}`になります. - 出力 - `aux_data`: 補助データ(辞書型) 入力の`aux_data`に,検索結果を連結した文字列を`"passages"`というキーで追加または上書きしたものです. ### ブロックコンフィギュレーションのパラメータ - `sources`(文字列のリスト) 検索対象文書が入っているファイルまたはディレクトリを指定します.コンフィギュレーションファイルのあるディレクトリからの相対パスで記述します.ディレクトリを指定した場合は,その配下を再帰的に走査します. - `extensions`(文字列のリスト,デフォルト値は`.pdf`, `.txt`, `.md`, `.docx`, `.pptx`, `.html`, `.htm`, `.json`, `.csv`) 読み込み対象とする拡張子のリストです. - `vector_db_dir`(文字列,デフォルト値は`"vector_db"`) ベクトルDBを保存するディレクトリ名です.コンフィギュレーションファイルのあるディレクトリからの相対パスで指定します. - `collection`(文字列,デフォルト値は`"rag_docs"`) Chroma DB内のコレクション名です. - `clear_before_ingest`(ブール値,デフォルト値は`True`) `True`のとき,起動時に既存のベクトルDBディレクトリを削除してから文書を再投入します.文書変更後に毎回ベクトルDBを作り直したい場合に使います. - `chunk_size`(整数,デフォルト値は`800`) 文書を分割するときのチャンクサイズです. - `chunk_overlap`(整数,デフォルト値は`100`) 文書分割時のチャンクの重なりサイズです.`chunk_size`より小さくする必要があります. - `top_k`(整数,デフォルト値は`5`) 類似検索で取得するパッセージ数です. - `separator`(文字列,デフォルト値は`"\n\n---\n\n"`) 検索された複数パッセージを1つの文字列に連結するときの区切り文字列です. ### 処理内容 - 起動時に`OPENAI_API_KEY`環境変数を確認し,OpenAIの埋め込みモデルを初期化します. - `sources`で指定されたファイル群を読み込み,必要に応じて正規化と分割を行ってベクトルDBに投入します. - 実行時には`dialogue_history`の最後のユーザ発話を検索クエリとして類似検索を行います. - 検索結果の各パッセージ本文を`separator`で連結し,`aux_data["passages"]`に格納して返します. (dst_with_llm)= ## DST with LLM (LLMを用いたスロット抽出ブロック) (`dialbb.builtin_blocks.dst_with_llm.DST`) 大規模言語モデルを用いて,対話履歴からのスロットの抽出,すなわち対話状態追跡(Dialogue State Tracking: DST)を行います. コンフィギュレーションの`language`要素が`ja`の場合は日本語,`en`の場合は英語のスロット抽出を行います. 本ブロックは,起動時にExcelで記述したスロット抽出知識を読み込み,スロットのリストとスロット抽出例に変換します. 実行時は,プロンプトに対話履歴を付加してLLMにスロット抽出を行わせます. ### 入出力 - 入力 - `dialogue_history`: 対話履歴 メインモジュールが保持している対話履歴(最新のユーザ発話までの対話)です. - `aux_data`: 補助データ(辞書型) メインモジュールに`aux_data`がない時は,`{}`になります. - 出力 - `aux_data`: 補助データ(辞書型) スロット抽出結果を含みます. ### 処理内容 対話履歴からスロットを抽出して,その結果をもとに`aux_data`をアップデートします. 例えば,`好きなラーメン`スロットの値が`味噌ラーメン`で,`ユーザの名前`スロットの値が`健二`だった場合,以下の処理が行われます. ```python aux_data["好きなラーメン"] = "味噌ラーメン" aux_data["ユーザの名前"] = "健二" ``` (dst_params)= ### ブロックコンフィギュレーションのパラメータ - `knowledge_file`(文字列) 知識を記述したExcelファイルを指定します.コンフィギュレーションファイルのあるディレクトリからの相対パスで記述します. - `flags_to_use`(文字列のリスト) 各シートの`flag`カラムにこの値のうちのどれかが書かれていた場合に読み込みます.このパラメータがセットされていない場合はすべての行が読み込まれます. - `knowledge_google_sheet` (ハッシュ) - Excelの代わりにGoogle Sheetを用いる場合の情報を記述します.(Google Sheetを利用する際の設定は[こはたさんの記事](https://note.com/kohaku935/n/nc13bcd11632d)が参考になりますが,Google Cloud Platformの設定画面のUIがこの記事とは多少変わっています.) - `sheet_id` (文字列) Google SheetのIDです. - `key_file`(文字列) Goole Sheet APIにアクセスするためのキーファイルをコンフィギュレーションファイルのディレクトリからの相対パスで指定します. - `model` (文字列.デフォルト値は`gpt-5.4-nano`) LLMのモデルを指定します. - `prompt_template` スロット抽出のためのプロンプトテンプレートを書いたファイルをコンフィギュレーションファイルのディレクトリからの相対パスで指定します. これが指定されていない場合は,`dialbb.builtin_blocks.dst_with_llm.prompt_template_ja.PROMPT_TEMPLATE_JA` (日本語)または,`dialbb.builtin_blocks.dst_with_llm.prompt_template_en.PROMPT_TEMPLATE_EN` (英語)が使われます. プロンプトテンプレートは,言語理解をLLMに行わせるプロンプトのテンプレートで,以下のプレイスホルダを含みます. - `{slot_definitions}`: スロットの種類を列挙したものです. - `{examples}`: 対話例と,タイプ,スロットの正解を書いた,いわゆるfew shot exampleです. - `{dialogue_history}`: 対話履歴 これらのプレイスホルダには,実行時に値が代入されます. (dst_knowledge)= ### スロット抽出知識 スロット抽出知識は,以下の2つのシートからなります. | シート名 | 内容 | | ---------- | ------------------------------------------------ | | dialogues | 対話とスロット抽出結果の組の例 | | slots | スロットとエンティティの関係および同義語のリスト | シート名はブロックコンフィギュレーションで変更可能ですが,変更することはほとんどないと思いますので,詳細な説明は割愛します. #### dialoguesシート 各行は次のカラムからなります. - `flag` 利用するかどうかを決めるフラグ.`Y` (yes), `T` (test)などを書くことが多いです.どのフラグの行を利用するかはコンフィギュレーションに記述します.サンプルアプリのコンフィギュレーションでは,すべての行を使う設定になっています. - `dialogue` 対話例 以下が例です ``` システム:好きなラーメンは何ですか? ユーザ:味噌ラーメン システム:札幌の味噌ラーメンですか? ユーザ:そう ``` - `slots` 対話から抽出されるべきスロット.スロットを以下の形で記述します. ``` <スロット名>=<スロット値>, <スロット名>=<スロット値>, ... <スロット名>=<スロット値> ``` 以下が例です. ``` 地方=札幌, 好きなラーメン=味噌ラーメン ``` このブロックで使うシートにこれ以外のカラムがあっても構いません. #### slotsシート 各行は次のカラムからなります. - `flag` dialoguesシートと同じ - `slot name` スロット名.utterancesシートの発話例で使うもの.スロット抽出結果でも用います. - `entity` 辞書エントリー名.スロット抽出結果結果に含まれます. - `synonyms` 同義語を`','`で連結したものです. (stn_manager)= ## STN manager (状態遷移ネットワークベースの対話管理ブロック) (`dialbb.builtin_blocks.stn_manager.stn_management.Manager`) 状態遷移ネットワーク(State-Transition Network)を用いて対話管理を行います. - 入力 - `dialogue_history`: メインモジュールから送られてくる対話履歴(任意) - `nlu_result`: 言語理解結果(辞書型または辞書型のリスト)(任意) (廃止予定) - `sentence`: ユーザ発話(文字列)(`dialogue_history`があればなくても良い) - `user_id`: ユーザID(文字列)(`dialogue_history`があればなくても良い) - `aux_data`: 補助データ(辞書型)(任意:クライアントから補助データを受け取る場合には必要) - 出力 - `output_text`: システム発話(文字列) 例: ``` "醤油ラーメン好きなんですね" ``` - `final`: 対話終了かどうかのフラグ(ブール値) - `aux_data`: 補助データ(辞書型)(ver. 0.4.0で変更) 入力の補助データを,後述のアクション関数の中でアップデートしたものに,遷移した状態のIDを含めたもの.アクション関数の中でのアップデートは必ずしも行われるわけではない.遷移した状態は,以下の形式で付加される. ```json {"state": "特定のラーメンが好き"} ``` ### ブロックコンフィギュレーションのパラメータ - `knowledge_file`(文字列) シナリオを記述したExcelファイルを指定します.コンフィギュレーションファイルのあるディレクトリからの相対パスで記述します. - `function_definitions`(文字列) シナリオ関数({numref}`dictionary_function`を参照)を定義したモジュールの名前です.複数ある場合は`':'`でつなぎます.モジュール検索パスにある必要があります.(コンフィギュレーションファイルのあるディレクトリはモジュール検索パスに入っています.) - `flags_to_use`(文字列のリスト) 各シートの`flag`カラムにこの値のうちのどれかが書かれていた場合に読み込みます. - `knowledge_google_sheet` (ハッシュ) DST with LLMブロックと同じです. - `scenario_graph`: (ブール値.デフォルト値 `false`) この値が`true`の場合,シナリオシートの`system utterance`カラムと`user utterance example`カラムの値を使って,グラフを作成します.これにより,シナリオ作成者が直感的に状態遷移ネットワークを確認できます. - `repeat_when_no_available_transitions` (ブール値.デフォルト値 `false`.ver. 0.4.0で追加) この値が`True`のとき,条件に合う遷移がないとき,遷移せず同じ発話を繰り返します. - `multi_party` (ブール値.デフォルト値 `false`.ver. 0.10.0で追加) この値が`true`のとき,{numref}`context_information`の対話履歴の内容,および,{numref}`llm_functinos`の大規模言語モデルを用いる組み込み関数のプロンプトに入る対話履歴で,`user_id`の値が用いられます. (scenario)= ### 対話管理の知識記述 対話管理知識(シナリオ)は,Excelファイルの`scenario`シートです. このシートの各行が,一つの遷移を表します.各行は次のカラムからなります. - `flag` `utterance`シートと同じ - `state` 遷移元の状態名 - `system utterance` `state`の状態で生成されるシステム発話の候補. システム発話文字列に含まれる`{<変数>}`または`{<関数呼び出し>}`は,対話中にその変数に代入された値や関数呼び出しの結果で置き換えられます.これについては,以下の{numref}`realization_in_system_utterance`で詳しく説明します. `state`が同じ行は複数あり得ますが,同じ`state`の行の`system utterance`すべてが発話の候補となり,ランダムに生成されます. - `user utterance example` ユーザ発話の例.対話の流れを理解するために書くだけで,システムでは用いられません. - `user utterance type` ユーザ発話を言語理解した結果得られるユーザ発話のタイプ.遷移の条件となります. このブロックの入力に`nlu_result`がない場合,この列はなくても構いません. - `conditions` 条件(の並び).遷移の条件を表す関数呼び出し.複数あっても構いません.複数ある場合は,`';'`で連結します.各条件は`<関数名>(<引数1>, <引数2>, ..., <引数n>)`の形をしています.引数は0個でも構いません.各条件で使える引数については,{numref}`arguments`を参照してください. - `actions` アクション(の並び).遷移した際に実行する関数呼び出し.複数あっても構いません.複数ある場合は,`;`で連結します.各条件は`<関数名>(<引数1>, <引数2>, ..., <引数n>)`の形をしています.引数は0個でも構いません.各条件で使える引数については,{numref}`arguments`を参照してください. - `next state` 遷移先の状態名 (メモとして利用するために)シートにこれ以外のカラムがあっても構いません. 各行が表す遷移の`user utterance type`が空かもしくは言語理解結果のタイプと一致し,`conditions`が空か全部満たされた場合,遷移の条件を満たし,`next state`の状態に遷移します.その際,`actions`に書いてあるアクションが実行されます. `state`カラムが同じ行(遷移元の状態が同じ遷移)は,**上に書いてあるものから順に**遷移の条件を満たしているかどうかをチェックします. デフォルト遷移(`user utterance type`カラムも`conditions`カラムも空の行)は,`state`カラムが同じ行の中で一番下に書かれていなくてはなりません. `repeat_when_no_available_transitions`がTrueの場合以外は,デフォルト遷移が必要です. ### 特別な状態 以下の状態名はあらかじめ定義されています. - `#prep` 準備状態.この状態がある場合,対話が始まった時(クライアントから最初にアクセスがあった時)に,この状態からの遷移が試みられます.`state`カラムの値が`#prep`の行の`conditions`にある条件がすべて満たされるかどうかを調べ,満たされた場合に,その行の`actions`のアクションを実行してから,`next state`の状態に遷移し,その状態のシステム発話が出力されます. 最初のシステム発話や状態を状況に応じて変更するときに使います.日本語サンプルアプリは,対話が行われる時間に応じて挨拶の内容を変更します. この準備状態はなくても構いません. `#prep`からの遷移先は`#initial`でなくてもよくなりました.(ver. 0.4.0) - `#initial` 初期状態.`#prep`状態がない場合,対話が始まった時(クライアントから最初にアクセスがあった時)この状態から始まり,この状態のシステム発話が`output_text`に入れられてメインプロセスに返されます. `#prep`状態または`#initial`状態のどちらかがなくてはなりません. - `#error` 内部エラーが起きたときこの状態に移動します.システム発話を生成して終了します. また,`#final_say_bye` のように,`#final`ではじまるstate IDは最終状態を表します. 最終状態ではシステム発話を生成して対話を終了します. ### 条件とアクション (context_information)= #### 文脈情報 STN Managerは,対話のセッションごとに文脈情報を保持しています.文脈情報は変数とその値の組の集合(pythonの辞書型データ)で,値はどのようなデータ構造でも構いません. 条件やアクションの関数は文脈情報にアクセスします. 文脈情報にはあらかじめ以下のキーと値のペアがセットされています. | キー | 値 | | -------------------------- | ------------------------------------------------------------ | | _current_state_name | 遷移前状態の名前(文字列) | | _config | configファイルを読み込んでできた辞書型のデータ | | _block_config | configファイルのうち対話管理ブロックの設定部分(辞書型のデータ) | | _aux_data | メインプロセスから受け取ったaux_data(辞書型のデータ) | | _previous_system_utterance | 直前のシステム発話(文字列) | | _dialogue_history | 対話履歴(リスト) | | _turns_in_state | 今の状態でのターン数(ユーザの発話回数)(整数) | | _session_id | 現在の対話のセッションID(文字列) | | _user_id | 直前のユーザ発話のユーザID(文字列) | 対話履歴は,以下の形です. ```python [ { "speaker": "user", "utterance": <正規化後のユーザ発話(文字列)> }, { "speaker": "system", "utterance": <システム発話> }, { "speaker": "user", "utterance": <正規化後のユーザ発話(文字列)> }, { "speaker": "system", "utterance": <システム発話> }, ... ] ``` ブロックコンフィギュレーションの`multi_party`の値が`true`の時,`"user"`の代わりに,`user_id`の値を用います. これらに加えて新しいキーと値のペアをアクション関数内で追加することができます. (arguments)= #### 関数の引数 条件やアクションで用いる関数の引数には次のタイプがあります. - 特殊変数 (`#`で始まる文字列) 以下の種類があります. - `#<スロット名>` 直前のユーザ発話の言語理解結果(入力の`nlu_result`の値)のスロット値.スロット値が空の場合は空文字列になります. - `#<補助データのキー>` 入力の`aux_data`の中のこのキーの値.例えば`#emotion`の場合,`aux_data['emotion']`の値.このキーがない場合は,空文字列になります. - `#sentence` 直前のユーザ発話(正規化したもの) - `#user_id` ユーザID(文字列) - 変数(`*`で始まる文字列) 文脈情報における変数の値です.`*<変数名>`の形.変数の値は文字列でないといけません.文脈情報にその変数がない場合は空文字列になります. - 変数参照(&で始まる文字列) `&<文脈情報での変数の名前>` の形で,関数定義内で文脈情報の変数名を利用するときに用います. - 定数(`""`で囲んだ文字列) 文字列そのままを意味します. #### 条件関数による文脈情報のアップデート 条件に用いられる関数が呼び出され、その中で文脈情報がアップデートされた場合、条件が満たされなくても文脈情報は**もとに戻りません**。 (realization_in_system_utterance)= ### システム発話中の変数や関数呼び出しの扱い システム発話中の`{`と`}`に囲まれた部分の変数や関数呼び出しは,その変数の値や,関数呼び出しの返り値で置き換えられます. 変数は`#`で始まるものは上記の特殊変数です.それ以外のものは通常の変数で,文脈情報にあるはずのものです.それらの変数が存在しない場合は,置換されず変数名がそのまま使われます. 関数呼び出しの場合,関数は条件やアクションで用いる関数と同じように上記の引数を取ることができます.返り値は文字列でないといけません. ### システム発話からのaux_dataの抽出 {numref}`extract_aux_data`と同様に,システム発話文字列から情報を抽出して`aux_data`に追加することができます. ### 関数定義 条件やアクションで用いる関数(まとめてシナリオ関数と呼びます)は,DialBB組み込みのものと,開発者が定義するものがあります.条件で使う関数はbool値を返し,アクションで使う関数は何も返しません. #### 組み込み関数 組み込み関数には以下があります. - 条件で用いる関数 - `_eq(x, y)` `x`と`y`が同じなら`True`を返します. 例:`_eq(*a, "b"`): 変数`a`の値が`"b"`なら`True`を返します. `_eq(#food, "ラーメン")`: `#food`スロットが`"ラーメン"`なら`True`を返します. - `_ne(x, y)` `x`と`y`が同じでなければ`True`を返します. 例:`_ne(*a, *b)`: 変数`a`の値と変数`b`の値が異なれば`True`を返します. `_ne(#food, "ラーメン"):` `#food`スロットが`"ラーメン"`なら`False`を返します. - `_contains(x, y)` `x`が文字列として`y`を含む場合`True`を返します. 例:_contains(#sentence, "はい") : ユーザ発話が「はい」を含めばTrueを返します. - `_not_contains(x, y)` `x`が文字列として`y`を含まない場合`True`を返します. 例: `_not_contains(#sentence, "はい")` : ユーザ発話が`"はい"`を含めば`True`を返します. - `_member_of(x, y)` 文字列`y`を`':'`で分割してできたリストに文字列`x`が含まれていれば`True`を返します. 例:`_member_of(#food, "ラーメン:チャーハン:餃子")` - `_not_member_of(x, y)` 文字列`y`を`':'`で分割してできたリストに文字列`x`が含まれていなければ`True`を返します. 例:`_not_member_of(*favorite_food, "ラーメン:チャーハン:餃子")` - `_num_turns_exceeds(n)` 文字列`n`が表す整数よりも対話の最初からのターン数(ユーザの発話回数)が多いとき,`True`を返します. 例:`_num_turns_exceeds("10")` - `_num_turns_in_state_exceeds(n)` 文字列`n`が表す整数よりもその状態でのターン数(ユーザの発話回数)が多いとき,`True`を返します. 例:`_num_turns_in_state_exceeds("5")` - `_check_with_llm(task)`, `_check_with_prompt_template(prompt_template)` 大規模言語モデルを用いて判定をします.後述します. - アクションで用いる関数 - `_set(x, y)` 変数`x`に`y`をセットします. 例:`_set(&a, b)`: `b`の値を`a`にセットします. `_set(&a, "hello")`: `a`に`"hello"`をセットします. - `_set(x, y)` 変数`x`に`y`をセットします. 例:`_set(&a, b)`: `b`の値を`a`にセットします. `_set(&a, "hello")`: `a`に`"hello"`をセットします. - システム発話内で用いる関数 - `_generate_with_llm(task)`, `_generate_with_prompt_template(task)` 大規模言語モデルを用いて文字列を生成します.後述します. (llm_functinos)= #### 大規模言語モデルを用いた組み込み関数 `_check_with_llm(task)`および`_generate_with_llm(task)`は,大規模言語モデルと,対話履歴を用いて,条件の判定および文字列の生成を行います. 以下が例です. - 条件判定の例 ```python _check_with_llm("ユーザが理由を言ったかどうか判断してください.") ``` - 文字列生成の例 ```python _generate_with_llm("それまでの会話につづけて,対話を終わらせる発話を50文字以内で生成してください") ``` これらの関数を使うためには,以下の設定が必要です. - ブロックコンフィギュレーションの`llm`要素 (`chatgpt`要素でも良いですが非推奨です)に以下の要素を加える - `model` (文字列) (`gpt_model`も使えますが非推奨です.) モデル指定文字列です. - `instruction` (文字列) LLMを呼び出す際に,システムロールのメッセージとして用いられます.文字列生成の時だけ用いられます.デフォルト値は[このファイル](https://github.com/c4a-ri/dialbb/blob/main/dialbb/util/globals.py)を参照. - `temperature` (float) LLMの温度パラメータです.デフォルト値は`0.7`です.LLMが`gpt-5x`の場合は無視されます. - `temperature_for_checking` (float) 条件判定の際に用いるLLMの温度パラメータです.これが指定されていない場合は,`temperature`の値が用いられます.LLMが`gpt-5x`の場合は無視されます. - `situation` (文字列のリスト) LLMのプロンプトに書く状況を列挙したものです. この要素がない場合,状況は指定されません. - `persona` (文字列のリスト) LLMのプロンプトに書くシステムのペルソナを列挙したものです. この要素がない場合,ペルソナは指定されません. - `cautions` (文字列のリスト) LLMのプロンプトに書くシステムへの注意事項を列挙したものです. この要素がない場合,注意事項は指定されません. なお,`check_with_llm`では,この要素があっても注意事項は指定されません. 例: ```yaml llm: model: gpt-5.4-nano # temperature: 0.7 situation: - あなたは対話システムで,ユーザと食べ物に関して雑談をしています. - ユーザとは初対面です - ユーザとは同年代です - ユーザとは親しい感じで話します persona: - 名前は由衣 - 28歳 - 女性 - ラーメン全般が好き - お酒は飲まない - IT会社のwebデザイナー - 独身 - 非常にフレンドリーに話す - 外交的で陽気 cautions: - 長い発話は禁止 - 発話の最後には「.」をつけない ``` `_check_with_prompt_template(prompt_template)`および`_generate_with_prompt_template(prompt_template)`は,大規模言語モデルにプロンプトを与えて条件の判定および文字列の生成を行います.プロンプトは,引数に指定したプロンプトテンプレートのプレースホルダを値に置き換えることで作られます. これらの関数を使うにはAPIキーを適切な環境変数に設定することと,ブロックコンフィギュレーションの`llm`要素の設定が必要です. 以下が例です. - 条件判定の例 ```python _check_with_llm("ユーザが理由を言ったかどうか判断してください.") ``` - 条件判定の例 ```python _generate_with_prompt_template(" # 状況 {situation} # あなたのペルソナ {persona} # 注意事項 {cautions} # 現在までの対話 {dialogue_history} # タスク ユーザが理由を言ったかどうか判断し,yesかnoで答えてください.") ``` - 文字列生成の例 ```python _generate_with_prompt_template(" # 状況 {situation} # あなたのペルソナ {persona} # 注意事項 {cautions} # 現在までの対話 {dialogue_history} # タスク それまでの会話につづけて,対話を終わらせる発話を50文字以内で生成してください.") ``` `{`と`}`で囲まれている部分はプレースホルダです. - 利用できるプレースホルダ - `{dialogue_history}` その時点までの対話(最新のユーザ発話を含む)で置き換えられる - `{situation}` ブロックコンフィギュレーションの`llm`要素の`situation`の値で置き換えられる - `{persona}` ブロックコンフィギュレーションの`llm`要素の`persona`の値で置き換えられる - `{cautions}` ブロックコンフィギュレーションの`llm`要素の`cautions`の値で置き換えられる - `{current_time}` 対話の行われている時点の年月日,曜日,時分秒を表す文字列で置き換えられる - `{<アルファベット,数字,アンダースコアのみからなる任意の文字列>}` 文字列が`aux_data`のキーにあれば,その値を文字列に変換したもので置き換えらる.この文字列は, - プレースホルダの削除 もし置き換えられないプレースホルダが残っていて,それが`[[[`と`]]]`で囲まれていれば,その部分は消去されます. #### 組み込み関数の簡略記法 組み込み関数の記述を簡単にするために以下の簡略記法(Syntax Sugar)が用意されています. - `<変数名>==<値>` `_eq(<変数名>, <値>)`の意味です. 例: ``` #好きなラーメン=="豚骨ラーメン" ``` - `<変数名>!=<値>` `_ne(<変数名>, <値>)`の意味です. 例: ``` #NE_Person!="" ``` - `<変数名>=<値>` `_set(&<変数名>, <値>)`の意味です. 例: ``` user_name=#NE_Person ``` - `TT > <整数>` `_num_turns_exceeds("<整数>")`の意味です. 例: ``` TT>10 ``` - `TS > <整数>` `_num_turns_in_state_exceeds("<整数>")`の意味です. 例: ``` TS>5 ``` - `$<タスク文字列>$` 条件として使われた時は,`_check_with_llm("<タスク文字列>")`の意味で,システム発話中で使われた時は,`{_generate_with_llm("<タスク文字列>")}`の意味です. 条件の例: ``` $ユーザが理由を言ったかどうか判断してください.$ ``` 文字列生成を含むシステム発話の例: ``` わかりました.$それまでの会話につづけて,対話を終わらせる発話を50文字以内で生成してください.$今日はお時間ありがとうございました. ``` 以前は`$"<タスク文字列>"`の形でしたが推奨されません. - `$$$<プロンプトテンプレート>$$$` 条件として使われた時は,`_check_with_prompt_template("<プロンプトテンプレート>")`の意味で,システム発話中で使われた時は,`{_generate_with_prompt_template("<プロンプトテンプレート>")}`の意味です. (custom_functions)= #### 開発者による関数定義 開発者が関数定義を行うときには,コンフィギュレーションファイルのブロックコンフィギュレーションの`function_definition`で指定されているモジュールのファイル(DST+STNアプリケーションでは`scenario_functions.py`)を編集します. ```python def get_ramen_location(ramen: str, variable: str, context: Dict[str, Any]) -> None: location:str = ramen_map.get(ramen, "日本") context[variable] = location ``` 上記のように,シナリオで使われている引数にプラスして,文脈情報を受け取る辞書型の変数を必ず加える必要があります. シナリオで使われている引数はすべて文字列でなくてはなりません. 引数には,特殊変数・変数の場合,その値が渡されます. また,変数参照の場合は`'&'`を除いた変数名が,定数の場合は,`""`の中の文字列が渡されます. #### 関数中のロギング シナリオ関数の中で,以下の関数を用いてロギングができます.セッションIDつきで標準出力に書き出されます. - `dialbb.builtin_blocks.stn_management.util.scenario_function_log_debug(message: str)` debugレベルのログが書き出されます. - `dialbb.builtin_blocks.stn_management.util.scenario_function_log_info(message: str)` infoレベルのログが書き出されます. - `dialbb.builtin_blocks.stn_management.util.scenario_function_log_warning(message: str)` warningレベルのログが書き出されます. - `dialbb.builtin_blocks.stn_management.util.scenario_function_log_error(message: str)` errorレベルのログが書き出されます.デバッグモードの時にはExceptionを投げます. ### 連続遷移 システム発話(の1番目)が`$skip`である状態に遷移した場合,システム応答を返さず,即座に次の遷移を行います.これは,最初の遷移のアクションの結果に応じて二つ目の遷移を選択するような場合に用います. ### 言語理解結果候補が複数ある場合の処理 入力の`nlu_result`がリスト型のデータで,複数の言語理解結果候補を含んでいる場合,処理は次のようになります. リストの先頭から順に,言語理解結果候補の`type`の値が,現在の状態から可能な遷移のうちのどれかの`user utterance type`の値に等しいかどうかを調べ,等しい遷移があれば,その言語理解結果候補を用います. どの言語理解結果候補も上記の条件に合わない場合,リストの先頭の言語理解結果候補を用います. ### リアクション アクション関数の中で,文脈情報の`_reaction`に文字列をセットすると,状態遷移後のシステム発話の先頭に,その文字列を付加します. 例えば,`_set(&_reaction, "そうですね")`というアクション関数を実行した後に遷移した状態のシステム発話が`"ところで今日はいい天気ですね"`であれば,`"そうですね ところで今日はいい天気ですね"`という発話をシステム発話として返します. 遷移先状態が`#initial`の時は、この機能は使えません。 ### Subdialogue 遷移先の状態名が`#gosub:<状態名1>:<状態名2>`の形の場合,`<状態名1>`の状態に遷移して,そこから始まるsubdialogueを実行します.そして,その後の対話で,遷移先が`:exit`になったら,`<状態名2>`の状態に移ります. 例えば,遷移先の状態名が`#gosub:request_confirmation:confirmed`の形の場合,`request_confirmatin`から始まるsubdialogueを実行し,遷移先が`:exit`になったら,`confirmed`に戻ります. subdialogueの中でsubdialogueに遷移することも可能です. ### 外部データベースへの文脈情報の保存 コンフィギュレーションに`context_db`要素があるとき,文脈情報を外部DB(MongoDB)に保存します.`context_db`の指定の仕方は,{numref}`context_db`を見てください. (ver. 1.2でcontext_dbはブロックコンフィギュレーションではなく,コンフィグレーションのトップレベルでしていするように変更されました.) (handling_speech_input)= ### 音声入力を扱うための仕組み ver. 0.4.0で,音声認識結果を入力として扱うときに生じる問題に対処するため,以下の変更が行われました. #### ブロックコンフィギュレーションパラメータの追加 - `input_confidence_threshold` (float.デフォルト値`0.0`) 入力が音声認識結果の時,その確信度がこの値未満の場合に,確信度が低いとみなします.入力の確信度は,`aux_data`の`confidence`の値です.`aux_data`に`confidence`キーがないときは,確信度が高いとみなします.確信度が低い場合は,以下に述べるパラメータの値に応じて処理が変わります. - `confirmation_request`(オブジェクト) これは以下の形で指定します. ```yaml confirmation_request: function_to_generate_utterance: <関数名(文字列)> acknowledgement_utterance_type: <肯定のユーザ発話タイプ名(文字列)> denial_utterance_type: <否定のユーザ発話タイプ名(文字列)> ``` これが指定されている場合,入力の確信度が低いときは,状態遷移をおこなわず,`function_to_generate_utterance`で指定された関数を実行し,その返り値を発話します(確認要求発話と呼びます). そして,それに対するユーザ発話に応じて次の処理を行います. - ユーザ発話の確信度が低い時は,遷移を行わず,前の状態の発話を繰り返します. - ユーザ発話のタイプが`acknowledgement_utterance_type`で指定されているものの場合,確認要求発話の前のユーザ発話に応じた遷移を行います. - ユーザ発話のタイプが`denial_utterance_type`で指定されているものの場合,遷移を行わず,元の状態の発話を繰り返します. - ユーザ発話のタイプがそれ以外の場合は,通常の遷移を行います. ただし,入力がバージイン発話の場合(`aux_data`に`barge_in`要素があり,その値が`True`の場合)はこの処理を行いません. `function_to_generate_utterance`で指定する関数は,ブロックコンフィギュレーションの`function_definitions`で指定したモジュールで定義します.この関数の引数は,このブロックの入力の`nlu_result`と文脈情報です.返り値はシステム発話の文字列です. - `utterance_to_ask_repetition`(文字列) これが指定されている場合,入力の確信度が低いときは,状態遷移をおこなわず,この要素の値をシステム発話とします.ただし,バージインの場合(`aux_data`に`barge_in`要素があり,その値が`True`の場合)はこの処理を行いません. `confirmation_request`と`utterance_to_ask_repetition`は同時に指定できません. - `ignore_out_of_context_barge_in` (ブール値.デフォルト値`False`) この値が`True`の場合,入力がバージイン発話(リクエストの`aux_data`の`barge_in`の値が`True`)の場合,デフォルト遷移以外の遷移の条件を満たさなかった場合(すなわちシナリオで予想された入力ではない)か,または,入力の確信度が低い場合,遷移しません.この時に,レスポンスの`aux_data`の`barge_in_ignored`を`True`とします. - `reaction_to_silence` (オブジェクト) `action`要素を必ず持ちます.`action` 要素の値は文字列で`"repeat"`か`"transition"`です.`action` 要素の値が`transition`の場合,`destination` 要素が必須です.その値は状態名(文字列)です. 入力の`aux_data`が`long_silence`キーを持ちその値が`True`の場合で,かつ,デフォルト遷移以外の遷移の条件を満たさなかった場合,このパラメータに応じて以下のように動作します. - このパラメータが指定されていない場合,通常の状態遷移を行います. - `action`の値が`"repeat"`の場合,状態遷移を行わず直前のシステム発話を繰り返します. - `action`の値が`transition`の場合,`destination`で指定されている状態に遷移します. #### 組み込み条件関数の追加 以下の組み込み条件関数が追加されています. - `_confidence_is_low()` 入力の`aux_data`の`confidence`の値がコンフィギュレーションの`input_confidence_threshold`の値以下の場合にTrueを返します. - `_is_long_silence()` 入力の`aux_data`の`long_silence`の値が`True`の場合に`True`を返します. #### 直前の誤った入力を無視する 入力の`aux_data`の`rewind`の値が`True`の場合,直前のレスポンスを行う前の状態から遷移を行います. 直前のレスポンスを行った際に実行したアクションによる文脈情報の変更も元に戻されます. 音声認識の際に,ユーザ発話を間違って途中で分割してしまい,前半だけに対する応答を行ってしまった場合に用います. 文脈情報は元に戻りますが,アクション関数の中でグローバル変数の値を変更していたり,外部データベースの内容を変更していた場合にはもとに戻らないことに注意してください.