FessのAI検索モードでは、セッション内の会話履歴をLLMに渡すことで文脈を維持した回答を生成しています。しかし、会話が長くなるとアシスタントの応答が大きくなり、コンテキストウィンドウを圧迫するという課題がありました。そこで、会話履歴のコンテキストの扱いを見直し、smart_summaryモードの導入やターンベースの履歴パッキングなどの改善を行いました。今後も調整していく可能性はありますが、現時点での変更内容を紹介します。
背景
AI検索モードでは、ユーザーとアシスタントの過去のやり取りを会話履歴としてLLMに渡しています。これにより「さっきの検索結果について詳しく教えて」といった文脈依存の質問に対応できます。
従来は、アシスタントの応答を履歴に含める際のデフォルトモードとしてsource_titles(参照したドキュメントのタイトルのみを残す)を使用していました。しかし、タイトルだけでは前の応答の内容を十分に把握できず、文脈が途切れるケースがありました。
smart_summaryモードの導入
新しいデフォルトモードとしてsmart_summaryを導入しました。このモードでは、長いアシスタント応答の先頭60%(直接的な回答部分)と末尾40%(まとめ部分)を保持し、中間部分を省略します。
[先頭60%: 直接的な回答]
...[omitted]...
[末尾40%: まとめ・結論]
[Referenced documents: ドキュメントタイトル1, タイトル2]
LLMの応答は一般的に、冒頭に質問への直接的な回答があり、末尾にまとめや結論が来る構成になっています。中間部分は詳細な説明や補足情報であることが多いため、省略しても文脈の維持に必要な情報は残りやすいという考え方です。
なお、応答が短い場合はそのまま全文が保持されます。
ターンベースの履歴パッキング
履歴をLLMに渡す際の詰め込み方式も改善しました。従来はメッセージ単位で個別に予算に収まるかを判定していたため、ユーザーの質問だけが入ってアシスタントの応答が入らない、といった不自然な切れ方が起きる可能性がありました。
新しい方式では、ユーザーメッセージとアシスタント応答をペア(ターン)として扱い、ターン単位で予算内に収まるかを判定します。これにより、質問と回答の対応関係が維持されます。
履歴設定のLlmClientへの移動
これまでfess_config.propertiesで静的に設定していた履歴関連のパラメータを、LlmClientインターフェースのメソッドに移動しました。
| パラメータ | 説明 | デフォルト値 |
|---|---|---|
getHistoryAssistantMaxChars() | アシスタントメッセージの最大文字数 | 800 |
getHistoryAssistantSummaryMaxChars() | サマリーの最大文字数 | 800 |
getIntentHistoryMaxMessages() | インテント検出用の最大メッセージ数 | 6 |
getIntentHistoryMaxChars() | インテント検出用の最大文字数 | 3000 |
これにより、fess-llm-openai、fess-llm-ollama、fess-llm-geminiなどのLLMプラグインが、それぞれのモデルの特性に合わせてパラメータをオーバーライドできるようになりました。
その他の変更
- 会話履歴の最大メッセージ数のデフォルトを20から30に増加
- インテント検出用の履歴メッセージ数のデフォルトを4から6に増加し、文字数による予算制御も追加
- 削除された設定プロパティ:
rag.chat.history.max.chars、rag.chat.history.assistant.max.chars、rag.chat.history.assistant.summary.max.chars、rag.chat.intent.history.max.messages
まとめ
今回の変更により、AI検索モードでの会話履歴の扱いがより効率的になりました。smart_summaryモードによって、限られたコンテキストウィンドウの中でも会話の文脈を維持しやすくなっています。また、LLMプラグインごとにパラメータを調整できるようにしたことで、モデルの特性に合わせた最適化が可能になりました。今後も実際の利用状況を見ながら調整を続けていく予定です。
詳細はPR #3084を参照してください。