DominoIQ のセットアップが完了し、使い始めたときに最初に体験すると思われるトラブルについて紹介します。その現象は、DominoIQ の返答が最後まで生成されず、途切れるというものです。
なお、この現象は LLM が回答を生成する際に発生するため、RAG サポートの有無にかかわらず起こり得ます。
LotusScript と DominoIQ
以前紹介した評価用サンプル から DominoIQ に問い合わせを行う部分を抜粋すると次の通りです。NotesLLMRequest クラスが問い合わせを担当し、Completion メソッドで問い合わせを実行します。その戻り値は NotesLLMResponse のオブジェクトで Content プロパティから返答(テキスト)を取得できます。
| Sub Click(Source As Button) ・・・ Dim llmreq As NotesLLMRequest Dim llmres As NotesLLMResponse ・・・ sText = nd.Prompt(0) '質問文の取得 sCmd = nd.IQCommand(0) 'コマンドの取得 'DominoIQ へ問い合わせ Set llmreq = ns.CreateLLMRequest() Set llmres = llmreq.Completion(ns.CurrentDatabase.Server, sCmd, sText) 'DominoIQ の返答を記録 nd.Results = llmres.Content nd.FinishReason = llmres.FinishReason End Sub |
今回紹介したいのは FinishReason プロパティです。
ヘルプによるとプロパティの値は『The reason the language model stopped generating a response.』となっています。翻訳すると「言語モデルが応答の生成を停止した理由」となります。エラーの原因を示すプロパティのようにも読めますが、実際には、正常終了した場合や、生成トークン数の上限に達した場合など、生成が終了した理由を表します。
このプロパティが取り得る値は次のとおりです。1 が返された場合は、LLM がテキストの生成を完了(正常終了)したことを示します。
| 値 | 定数 | 説明 |
| 0 | LLM_FINISH_REASON_NONE | エラーが発生したことを示します |
| 1 | LLM_FINISH_REASON_STOP | 言語モデルがテキストの生成を完了したことを示します |
| 2 | LLM_FINISH_REASON_LENGTH | トークンの上限に達したことを示します |
| 3 | LLM_FINISH_REASON_FUNCTION_CALL | 現在サポートされていません |
今回取り上げている「回答が最後まで生成されない」現象では、戻り値が 2 になるということですね。
トークン数の確認
上記プロパティからわかるのは、トークン数の上限に達したことまでです。これだけでは原因を詳しく調べるには情報が足りず判断しかねますよね。
こんな時に頼りになるのが LLM 問い合わせの詳細ログ domiqllmthr・・・.log となります。
DATA-IN の値からは、DominoIQ からの返答を詳しく確認できます。content の部分が回答になりますが、最後が「3.開発支援」「Lotus」で終わっていることが確認できます(青字)。冒頭に掲載した画像の状況と一致しています。
|
{ "choices": [ { "finish_reason": "length", "index": 0, "message": { "role": "assistant", "content": "はい、**dxlSuite** は IBM Domino(以前はLotus Domino)の開発者向けツールで、データベース(NSFファイル)を DXL(Domino XML)形式に変換したり、逆にDXLからNSFに復元したりするのに便利です。初心者にもわかりやすく説明します。\n\n---\n\n### **dxlSuite とは?**\ndxlSuite は、IBM Domino データベース(NSFファイル)と DXL(Domino eXtensible Markup Language)の間でデータをやりとりするためのツールです。 \nDXLは、XML形式のデータ表現で、NSFファイルを「テキストとして扱える」形式です。\n\n---\n\n### **主な用途**\n1. **データのバックアップや復元** \n - NSFファイルをDXLに変換して、他の場所に保存したり、復元したりできます。\n - データの移行や、開発環境と本番環境の同期に役立ちます。\n\n2. **データの抽出・編集** \n - DXLでデータを編集(例:レコードの追加・削除)後、NSFに戻して利用できます。\n - データの検証や、特定の項目の抽出にも便利です。\n\n3. **開発支援** \n - Lotus", "reasoning_content": "Okay, the user is asking if I know about dxlSuite. Let me start by confirming that I do. ・・・ Alright, that should cover the basics without overwhelming the user.\n" } } ], "created": 1792030923, "model": "Qwen3-8B-Q5_K_M.gguf", "system_fingerprint": "b8691-0e950cfc9", "object": "chat.completion", "usage": { "completion_tokens": 512, "prompt_tokens": 55, "total_tokens": 567, "prompt_tokens_details": { "cached_tokens": 45 } }, ・・・ |
このログで確認すべき項目は、finish_reason と completion_tokens です(赤字)。
finish_reason が "length" の場合、生成トークン数の上限に達して回答の生成が終了したことを示します。今回の completion_tokens は 512 となっており、この値で生成されたトークン数が上限に達していることがわかります。
ちなみに、正常終了したときの finish_reason は stop となります。
| "finish_reason":"stop", |
先ほど紹介した NotesLLMResponse クラスの FinishReason プロパティで正常終了の定数名が LLM_FINISH_REASON_STOP と命名されている理由はこのためですね。
トークン数の上限
では、なぜ 512 で上限を超えたと判断されたのでしょうか?
その理由も domiqllmthr ログを見ればわかります。今度は、LLM に対するリクエスト部分である DATA-OUT を確認します。すると、すぐにわかりますね。max_tokens が 512 に設定されているためです。
|
{ "model": "Qwen/Qwen3-8B-GGUF", "messages": [ { "role": "system", "content": "あなたは LotusScript と dxlSuiteの専門家です。 初心者にも分かりやすく説明してください。 回答は日本語で行ってください。" }, { "role": "user", "content":"dxlSuite を知っていますか?" } ], "max_tokens": 512, "temperature": 0.7 } |
この 512 という値は、Domino IQ Configuration DB の LLM Command 文書に設定されています。DominoIQ を設定した作業を思い出した方は気が付いたかもしれませんね。
上限の変更とまとめ
トークン数の上限を変更するには、LLM Command 文書の Maximum tokens の値を変更します。
試しに 1024 や 2048 に設定してみましたが、いずれも生成トークン数の上限に達してしまいました。4096 に設定したところ、finish_reason が "stop" となり、回答の文章が最後まで出力されました。
今回の質問があいまいだったことも影響しているのかもしれませんが、どうやら今回利用している LLM は、なかなかのおしゃべり好きのようですね...。
もちろん、生成するトークン数が増えれば、回答の生成に時間がかかる可能性があります。長い回答が必要な場合には上限を大きくする必要がありますが、ユーザがいつまでも回答を待つことになっては、システムとして使い勝手がよくありません。
DominoIQ を導入したマシンのスペックやユーザの利用頻度、想定する回答の長さなどを考慮して、適切な値を設定する必要がありそうです。
また、LotusScript から DominoIQ に問い合わせる場合は、NotesLLMResponse クラスの FinishReason プロパティを確認することで、回答の生成が正常に終了したかどうかを判定できます。LLM_FINISH_REASON_LENGTH が返された場合に、生成途中の回答をそのまま表示するのか、質問を具体的にするようユーザに促すのかなど、アプリケーション側でも仕様を決めておくとよさそうですね。
0 件のコメント:
コメントを投稿