配信を想定したキャラクター応答の解析・評価
評価日: 2026-09-24。対象: HEAD 91a5529a と未コミット変更を含むローカル作業ツリー。
9月22日の横断解析に、9月23〜24日の実装を反映した追加評価。
判定
応答・自発発言の前に状況を整理する方針は、現在の設計と整合している。ただし、配信で「話を分かってくれる」「テンポがよい」「続きを聞きたい」と感じられるかは未実証。 推論量を増やす前に、状況を読む材料、演出の選択、実際に聞こえるタイミングを揃える必要がある。
特に優先したいのは、①挨拶を含む相談や短い訂正を軽く扱う判定、②「思考過程を見せる」と「出力しない」の指示の競合、③発話中の反応を今の発話に対応付けられない点。これらはコードと局所的な実行で確認した。誤ったLLM応答が実配信で発生した割合を測った結果ではない。
今回の自動検証は Unity EditMode 487/487成功、既存の評価器の Python テスト 8/8成功。さらにコンパイル済みの実クラスへ架空入力を与え、21件の判定結果を保存した。LLM生成、実音声、視聴端末での遅延、視聴者の満足度は測っていない。点数を推定で埋めることはしない。
評価の範囲と根拠
| 区分 | 実施内容 | 分かること / 分からないこと |
|---|---|---|
| 静的解析 | コメント受付→演出→生成→音声→記憶、台本、自発発話、反応の観測、評価ツールを追跡 | 制御・指示の競合と経路の差。実際の話し方は不明 |
| 自動回帰 | 会話、訂正、Situation、台本継続、文字数、配送、質問待ち、投げ銭台帳、Discord関連の選択テスト | 対象の契約が成立すること。プロジェクト全体の全テストではない |
| 局所実行 | broadcast_probe.csxで実クラスを呼ぶ | 分類、反応候補の選択、反復抑制、指示文の実際の戻り値。配信の再現ではない |
| 実モデル比較 | 未実施 | キャラらしさ、訂正への回答、面白さ、推論による改善幅は未評価 |
| 実配信・音声 | 未実施 | 可聴率、声色、間、表情、混雑時の取りこぼしは未評価 |
成果物: 検証記録、局所実行21件、限定導入の証拠照合。調査したリポジトリ内の評価資料、および Logs/・UserSettings/ の関連ファイル名からは、採用判定に使える実モデル比較の保存結果は見つからなかった。別端末や外部保管の実績がないとは断定しない。
配信の流れに沿った評価
| 場面 | 現在の強み | 制約・確認が必要な点 | 判定 |
|---|---|---|---|
| 挨拶・短いリアクション | 完全一致の挨拶は生成5秒、推論none。短文演出もある | 生成5秒は初音声までの保証ではない。挨拶+本題の判定が粗い | 要改善 |
| コメントへの回答 | 9/23に無関係な台本話題と「話を戻すね」を返答へ足す指示を抑制 | 制御文の回帰は確認。実生成で脱線・冗長さが減ったかは未測定 | 構造確認・内容未評価 |
| 取り違えの訂正 | 同じ視聴者との直近3往復を参照。明示的訂正を保持し、別人・非公開履歴と分離 | 「弟の話です」等の暗黙の訂正は20秒枠・短文時の推論保護に入らない | 要改善 |
| 自発発言 | 応答と同じ状況整理、可聴履歴、反応候補を参照。任意発話は見送り可能 | 一言ごとの指示に依存。意味が同じ言い換えに対する新規性の保証はない | 部分的に成立 |
| 視聴者への質問 | 質問受付・猶予・二重質問の抑制があり、実配送で状態を進める | プラットフォームの遅延、質問の聞き終わり、回答の内容が噛み合うかは実経路で確認 | 構造確認 |
| 観客反応への展開 | 受信順ではなく投稿時刻で候補化。反応を事実・賛否へ自動昇格しない | 完了時刻を基準にするため、発話中の笑い・困惑の対応先が欠ける | 要改善 |
| 台本と寄り道 | 台本の所有権、関連話題、戻り、既出話題の管理がある | 複数視聴者・長い寄り道後に番組の主題が伝わるかは未評価 | 構造確認・内容未評価 |
| スパチャ・ギフト | 課金コメントは通常演出・Light以上。可聴完了と未完了を台帳で区別 | 本文が丁寧か、金額優先時に一般視聴者が置き去りにならないかは未評価 | 構造確認 |
| ゲーム・コラボ・カンペ | 別経路として出所と進行権を扱う | 共通の状況整理ポリシーの対象は CommentResponse / Autonomous / Script。全経路に同じ推論を適用してはいない | 適用範囲に注意 |
| 声・演技 | 可聴完了/断片/未配送を分け、未再生の全文を記憶へ確定しない | 現作業ツリーの声の検品は再合成・保留を増やし得る。声の安定と応答の可聴率を同時に測る必要がある | 実音声未評価 |
状況整理は「実装されている」が「常に推論する」ではない
会話品質v2とSituationが有効な発話に、状況照合と目的選択の指示を付ける。別の計画用LLM呼出しを常に挟む方式ではなく、生成要求内で判断させる。noneでも状況整理の指示は使えるが、追加のreasoning effortを要求する設定ではない。
コード既定は会話品質v1・effort none。対応モデルの判定もコード内の許可リストに依存する。今回、実際のキャラ・端末へ適用された設定は取得していない。 有効化されている前提で実配信の効果を述べることはできない。
優先して扱う指摘
優先度はこの機能の改善順。P1は品質比較の前に対応したいもの、P2は実配信評価と併せて詰めたいもの。
B-01 / P1: 挨拶が付くと、相談の本文より即答判定が優先される
実クラスの実行結果:
| 入力 | 複雑さ判定 | 生成の場面 |
|---|---|---|
| こんにちは! | Immediate | QuickReply / 5秒 |
| こんにちは、配信で失敗するのが怖い。どうしたらいい | Immediate | ContextualReply / 15秒 |
| 配信で失敗するのが怖い。どうしたらいい | Deep | ContextualReply / 15秒 |
QuestionComplexityAnalyzerは冒頭の挨拶・相槌に .*$ を許し、相談パターンより先に一致させる。ResponseDirectorはImmediate時に短文演出の重みを増やす。短文またはImmediateの長さが選ばれると、v2のeffortもnoneになる。一般コメントの演出は抽選を含むため、常に短文になるという意味ではない。
配信上の懸念は、挨拶を返しただけで相談を受け止めないこと。同じ本文の先頭に挨拶があるかどうかで扱いが変わる点は修正候補。挨拶だけの入力と、挨拶+質問・相談を分けて判定する。相談の長文化を必須にせず、「受け止め+本題への一答」を守った上で短くする。
根拠: QuestionComplexityAnalyzer.cs:45,147、ResponseDirector.cs:375,409,454、LLMcontroller.ConversationExperience.cs:32。局所実行 classification_0..2。
B-02 / P1: 暗黙の訂正には、短文時の推論保護が効かない
「弟の話です」「左の赤いほうです」「行くのは明日です」はいずれもImmediate / ContextualReply。短文が選ばれた場合、要求lowもnoneへ下がる。一方、「違うよ、弟の話です」はRepair / 20秒でlowを保持する。
履歴を参照して暗黙の訂正を判断する指示は存在する。しかし、その判断に使える推論量を抑える側は現在の入力の語句・長さで決まる。同じ視聴者との履歴がある短い補足では、主語・対象の照合を行う余地を確保したい。短文をすべて訂正扱いにすると「ありがとう」にも不要な待ちが出るため、直前の往復と照合して対象を限定する。
局所実行は「短文演出が選ばれた場合」の制御結果であり、noneなら必ず訂正に失敗するという判定ではない。既存の比較ケースには暗黙の訂正があるが、比較ツールはResponseDirectorを通らないので、この経路差は見えない。
根拠: ConversationGenerationPlan.cs:57、ConversationReasoningPolicy.cs:62、LLMcontroller.ConversationExperience.cs:32。局所実行 classification_3..6。
B-03 / P1: 配信で話す内容と内部の状況整理の指示が競合する
Deepの長さ指示には「思考の過程を見せながら丁寧に応答してください」が残る。一方、v2は「推論過程や計画は出力せず」と指示する。局所実行では、目標80字・上限120字で前者を含む70〜100字の指示が生成された。通常BuildPromptでは両方を追加する経路がある。
期待する配信表現を、結論とキャラクターらしい短い理由・リアクションに統一するのがよい。判断手順の説明や独り言の列挙は求めない。「考えてから話す」と「考えた手順を読み上げる」を仕様で分ける。現在の文字数テストは旧文言との一致を確認しているため、変更時はその期待値も見直す。
根拠: ResponseLengthPlanner.cs:59、LLMcontroller.MainPrompt.cs:197,428、ConversationReasoningPolicy.cs:27、ResponseLengthPlannerTest.cs:33。局所実行 deep_prompt_contract。競合する指示の存在を確認したもので、実際の生成で内部推論が出力されたことを示すものではない。
B-04 / P1: 発話中のリアクションが今の発話へ結び付かない
共通履歴は配送の完了・途中終了を確定した時刻を持つ。反応候補は、その時刻より2秒以上後、受信まで45秒未満のコメントに限定される。
再現条件: 発話Aが0秒に完了。発話Bは5〜20秒に再生中。Bへの「もっと聞きたい」が10秒に投稿、11秒に受信される。
- Bはまだ共通履歴にないため、観測サービスはAを候補として返す。
- 配信最初の発話で過去の履歴がない場合は候補を作れない。
- 完了1秒後の投稿も採用されず、2秒後なら採用される。
これは反応候補の経路の制約。コメントそのものが通常の返答キューから消えることを意味しない。また「関連未確認」の指示があり、LLMが誤関連を必ず信じるわけでもない。
配信ではオチの途中で笑い、説明の途中で困惑が来る。発話開始・終了・話題IDと、プラットフォームの遅延を対応付ける評価が必要。未完了の全文を「発話済み」にするのではなく、「現在再生中」の別情報で扱う。文字列の近さだけで笑いや支持を認定しない。
根拠: SituationContextService.cs:302,361、SituationContextService.AudienceFeedback.cs:20。局所実行 feedback_*。実配信の配送遅延を再現したものではなく、時刻を明示して観測サービスへ与えた結果。
B-05 / P2: 反復抑制は、話が進んだことの保証にはならない
任意自発発話の新しいガードは、90秒以内・正規化後30文字以上・可聴完了履歴との全文一致が対象。同じ文は抑制され、語句を変えて同じ提案をした文はこのガードを通る。Script経路もこのガードの対象外。
別に SpeechLoopDetector の文字bigram類似度、台本の類似発話再生成、既出話題管理があるため、「繰り返し対策が存在しない」という評価ではない。しかし、新しい具体例・視点・反応・回収が増えたかをこれらの文字比較だけでは保証しない。
自発発言の評価は「同じ文字列でない」から「直前から何が一つ増えたか」へ広げる。一方、持ちネタや意図した前振り回収は反復として減点しない。
根拠: ConversationContinuityPolicy.cs:48、LLMcontroller.Monologue.cs:166、SpeechLoopDetector.cs:101,197,364。局所実行 repeat_* は新しいガード単体の結果。
B-06 / P1: 比較ツールの合格だけでは、通常配信の改善を証明できない
比較ツールは練習用人格プロンプト+1〜3文・180字以内の共通制約を用い、SendMonologueRequestへ送る。通常のコメント受付、ResponseDirector、全文のBuildPrompt、台本所有権、TTS待ちを含む経路ではない。仮想配送の時間も10秒刻み。
そのため、B-01〜03の演出・プロンプト合成の問題、9/23追加の最初の試行打ち切り、声の検品による保留は、現在の比較ツールだけでは評価できない。部品の比較と、通常経路を通すリハーサルの両方を採用条件にする。
評価器にも制約がある。全体平均の非劣化ではケース別の悪化が相殺され得る。ローカルモデルでlow比較を実行できなくても、現評価器は3条件すべてを要求するため限定導入Readyにはならない。独立した採点、ケース別比較、対応モデル別の条件定義が必要。
根拠: LLMcontroller.ConversationRehearsal.cs:41、ConversationRehearsalSession.cs:62、assess.py:12,108,112。現在の証拠照合はReady=false。旧候補のソース指紋も現作業ツリーと異なる。判定を通す目的で候補の指紋だけ更新していない。
B-07 / P2: 「生成成功」「TTS正常」と「視聴者に返せた」を分けて測る
v2の生成上限は挨拶5秒、一般15秒、明示的訂正20秒、自発8秒、台本25秒。残り尺・コメント期限でさらに短くなる。最初の試行打ち切りは通常の SendRequest 経路にあり、残り9秒以上なら再試行用5秒を残す。自発・台本の SendMonologueRequest、Assistants/Response専用分岐には同じ打ち切り再試行を適用していない。 25秒→20秒という局所計算だけで、台本でもその再試行が走ると解釈してはいけない。
生成上限とは別に、コメント取得・キュー・発話権・TTS・送出の遅延がある。単一コメントの配送台帳は初音声を測れるが、バッチ・自発発話の全経路を同じ指標で覆っていない。最大256件の手動書き出しも、混雑した1時間の全件保存を保証しない。
さらに現作業ツリーの声の検品は、音声を作り直しても一致しない場合に再生を保留する。これは設計上の選択だが、TTSの障害率に数えないため、TTSが正常でも視聴者には返事が聞こえないケースがある。検品保留率・再合成回数・最初に聞こえるまでの時間・途中可聴率を合わせて見る。今回GPUでの検品・声の実測はしていない。
根拠: ConversationGenerationPlan.cs:29、ConversationAttemptTimeout.cs:20、LLMController.cs:715,767,889、LLMcontroller.Monologue.cs:137、TTSController.cs:2619,2651、ConversationDeliveryTiming.cs:30。
実配信に近い評価シナリオ
以下は新たに整理した未実施の実経路評価。内容を分析に使ったケースなので、盲検の採用評価用holdoutとは呼ばない。既存の16ケース・37ターンはそのまま残す。
| ID | 流れ | 確認すること |
|---|---|---|
| S01 | 「こんにちは!」→挨拶付き相談→同じ相談を挨拶なしで投稿 | 本題への回答、選択モード、実効effort、初音声。挨拶だけの速さを保つ |
| S02 | 人物を取り違える→「弟の話です」→「ありがとう」→「本人には何て言おう」 | 訂正の対象を維持し、謝罪や姉の話へ戻らない |
| S03 | 台本は紅茶、視聴者はゲームの相談→返答→次の台本発話 | 返答中に無関係な台本説明を足さず、次の台本発話で自然に戻る |
| S04 | 20秒の発話の途中に笑い・困惑、完了1秒後/3秒後にも投稿 | 反応候補の対応先、必要な補足、笑いへの過剰説明 |
| S05 | 「海と山どっち?」→無反応→遅れた「海」→回答 | 別の質問を重ねず、遅れた回答を拾い、無言を不評にしない |
| S06 | コメントなしで5分雑談→途中で具体例を求める | 新しい話材、同義反復、不要な質問、静かな時間の自然さ |
| S07 | 話題を3往復進める→別視聴者「今来た、何の話?」 | 一言で対象を示し、全体を説明し直さず会話へ参加させる |
| S08 | 一般コメントが連続→少額/高額ギフト→一般コメント | お礼の可聴完了・台帳、未完了のお礼、一般視聴者への戻り |
| S09 | 応答生成中にカンペ/ノード遷移/ゲスト発話 | 古い生成の取消、発話者混同、同時発話、自然な会話再開 |
| S10 | 初回LLMが遅い→再試行、TTSも遅い | 経路別の打ち切り、残り予算、無返答、不要な再生成 |
| S11 | 声の検品で再合成→保留、または途中まで再生 | 読み上げていない部分を回答済みにしない。保留理由と初音声を記録 |
| S12 | 合成時に停止/音量0/キャラ切替→復帰 | 発話済みの誤記憶や再開後の二重読みがない |
| S13 | 履歴非公開、引用内の命令、複数人の訂正が交錯 | 訂正の混同や個人情報の披露を避け、運用命令として実行しない |
| S14 | ゲーム実況→視聴者応答→ゲストとの会話 | 経路別の状況参照・声・字幕。共通推論の対象外も個別に評価する |
実施条件として、キャラ・人格版・モデル・実効effort・TTS/声・コード指紋・端末・配信方式・コメント取得方式を固定して記録する。none/状況整理ありnone/状況整理ありlowの比較は、対応するモデルで同一条件・反復・順序を入れ替えて行う。演出抽選の差を推論量の効果と混同しないよう、選ばれたモードも保存する。
採点方法
回答本人への返事と、他の視聴者にとっての見やすさを両方採点する。生成文だけの採点と、声・間・映像を含む採点を別に残す。採点者には可能なら推論条件を伏せる。
| 軸 | 1(不成立) | 3(成立) | 5(よい配信体験) |
|---|---|---|---|
| 状況・意図 | 対象を間違える、本題を無視する | 今の問いに答える | 訂正・曖昧さを処理し必要な範囲だけ補う |
| 継続性 | 訂正前へ戻る、同じ説明を反復 | 直前と矛盾せず続く | 前振りや反応を使い、新しい一段を足す |
| キャラらしさ | 設定矛盾、無根拠の体験談 | 設定に沿った自然な返事 | 独自の見方・言い回しが一貫する |
| 視聴者全体への明瞭さ | 誰/何の話か分からない | 当人には伝わる | 初見にも一言で前提が伝わり流れを止めない |
| エンタメ | 一般論・質問返しだけで停滞 | 一つの返答として楽しめる | 意外性・具体例・共感・回収のいずれかがあり続きを聞きたい |
| 音声・テンポ | 無音、途中切れ、声の違和感で理解困難 | 聞き取れて意味が通る | キャラの声・間・表情が内容と合い、会話の受け渡しが自然 |
「常に笑わせる」「常に質問で締める」を高得点条件にしない。静かな聞き役、短い相槌、意図した沈黙も場面に合えばよい。安全・公開範囲の逸脱、未再生を配送済みにする挙動は平均点で相殺せず個別に不合格として扱う。
最低限集計する値は、ケース別の回答成立率、暗黙訂正の維持率、無関係な台本話題の混入率、意味上の反復、未回収の質問、可聴完了/途中/未配送、投稿または正規化→初音声、処理開始→初音声、TTS依頼→初音声のp50/p95。時刻の出所とサンプル数を付ける。今回の値は未測定。生成予算を体感待ち時間の目標値として転用しない。
検証手順と今回の変更
初回のUnity検証は485成功/2失敗。両失敗ともReflectionを使うテストのAPI追従漏れだったため、次だけ修正した。製品の応答ロジックは変更していない。
FreeTalkConversationTest:CommitAudienceTopicAfterReplyの追加optional引数を明示。TtsCircuitBreakerIntegrationTest: コンストラクタの引数個数への依存をやめ、公開のPartialfactoryで部分配送receiptを生成。部分可聴を全文再試行しないという検証内容は維持。
再実行は487成功/0失敗(2026-09-24 22:14 JST)。Python評価器は8成功。Unityテストの全名称・結果と参照ソースの指紋は evaluation.json に収録。
局所実行は、同じ作業ツリーをUnityでコンパイルしてから次を実行する。コンパイル前の古いDLLでは評価しない。
UNITY_MONO=/Applications/Unity/Hub/Editor/2022.3.15f1/Unity.app/Contents/MonoBleedingEdge
"$UNITY_MONO/bin/mono" "$UNITY_MONO/lib/mono/4.5/csi.exe" \
-r:Library/ScriptAssemblies/Assembly-CSharp.dll \
-r:Library/ScriptAssemblies/Aituber.AI.Situation.dll \
-r:Library/ScriptAssemblies/Aituber.AI.SpeechLimit.dll \
scripts/conversation-quality/broadcast_probe.csx
これは架空入力を使うローカルの制御観測で、実モデルの代替でもLLMの自動採点でもない。出力はJSON Lines。観測を失敗と隠さず保存し、今後修正したときの比較に使う。
今回の結論として、状況整理を増やすだけでなく、その前の判定と後の配送を含めて評価することが必要。実モデルと実音声の採用判断は、上のシナリオと対象条件を揃えた実測が残る。