Alibaba Cloud Milvus ナレッジベースを使用して、教育シナリオ向けの問題バンク Q&A アプリケーションを構築します。このナレッジベースは、教科書、指導案、問題、およびグラウンドトゥルースを検索可能な問題バンクアシスタントに変換します。学生は自然言語で質問し、出典資料への引用が付いた解説を受け取ることができます。また、学生は問題の画像をアップロードして問題バンク内の類似問題を検索し、教科書の解説と組み合わせることもできます。
ソリューション概要
エンドツーエンドパイプラインは、「Alibaba Cloud Milvus ナレッジベースを使用したインテリジェントカスタマーサービス Q&A アプリケーションの構築」と同一です。コンソールでのタグ定義 → タグによる資料の一括インポート → バージョンの公開 → SDK による検索 (タグフィルターと画像添付に対応) → LLM による出典引用付きの回答生成 → Flask による Q&A ページの配信、という流れになります。このチュートリアルでは、そのチュートリアルのプロジェクトコードを直接再利用します。このトピックでは、教育シナリオ向けに変更される部分、すなわち教科と知識ポイントのタグ、画像資料の扱い方、画像クエリの機能と制約、数式の表示についてのみ説明します。
最初のバージョンでは、1 つの学年と 1 つの教科から 5~20 件の資料のみを選択し、検証後に拡張してください。プロセス全体には約 25~40 分かかります。ドキュメントの解析時間は、資料の数とサイズによって異なります。
前提条件
「Alibaba Cloud Milvus ナレッジベースを使用したインテリジェントカスタマーサービス Q&A アプリケーションの構築」を完了していること。このチュートリアルでは、そのチュートリアルの以下のプロジェクトコードを再利用します。
kb_client.py、upload.py、app.py、templates/index.html、およびstart.shconfig.json設定ファイル
オムニモーダル (
ALL_MODAL) の Milvus ナレッジベースがあり、ナレッジベース ID (例:kd-803ae9b10cc31) が記録されていること。このチュートリアル用に新しいナレッジベースを作成するか、カスタマーサービスのチュートリアルのものを再利用できます。以下の点にご注意ください。ナレッジベースのタイプは作成後に変更できません。
構造化ナレッジベースは、xlsx、xls、csv、jsonl、faq の 5 形式しか受け付けません。画像を直接アップロードすると、パラメーターエラーが返されます。したがって、画像資料を含む問題バンクでは、オムニモーダルナレッジベースを使用する必要があります。
現在、コンソールではナレッジベース作成時に常にオムニモーダル (
ALL_MODAL) タイプが使用され、ページに他の選択肢はないため、追加の判断は不要です。既存のナレッジベースのタイプを確認するには、ナレッジベース詳細ページの [Basic Information] にある [Data Type] を表示します。
Alibaba Cloud アカウントの RAM ユーザー。RAM ユーザーに対して [Access with a permanent AccessKey] を選択し、システムポリシー
AliyunMilvusFullAccessを付与してください。OpenAI の
chat/completionsプロトコルに対応する LLM エンドポイントと API キー。Python 3.8 以降がローカルにインストールされていること。
ステップ1:学年と知識ポイントのタグ定義
ナレッジベース詳細ページの [Basic Information] セクションで、[Tags] > [Manage] を選択し、以下の 4 つのタグを追加してください。すべてのタグのタイプはstring です。
タグ名 | 説明 | 値の例 |
grade | 学年 | 8 年生 |
subject | 教科 | 数学、物理 |
knowledgePoint | 知識ポイント | 二次関数、ピタゴラスの定理 |
questionType | 資料タイプ | 教科書、練習問題、グラウンドトゥルース |
タグ値は中国語に対応しています。学年、教科、知識ポイントの中国語名を直接使用できます。
タグ管理ダイアログボックスはまとめて保存されます。ダイアログボックスを開くと、タグリストが非同期に読み込まれます。新しいタグを追加して [OK] をクリックする前に、既存のすべてのタグが表示されるまで待ってください。そうしないと、リスト全体が空のリストと新しいタグで上書きされ、既存のタグ定義が削除される可能性があります。
ステップ2:資料とインポートマニフェストの準備
documents/ディレクトリに資料を配置してください。PDF、DOCX、Markdown、TXT、および画像に対応しています。教科書、問題、グラウンドトゥルースをセットとしてアップロードしてください。解説を生成する際、モデルは教科書からの解法、元の問題文、および解答からの採点ポイントを同時に引用するため、回答の網羅性が大幅に向上します。documents.jsonlを作成し、各資料に学年、教科、知識ポイント、資料タイプを注釈付けしてください。{"path": "documents/math-grade8-textbook.pdf", "metadata": {"grade": "Grade 8", "subject": "Mathematics", "knowledgePoint": "quadratic function", "questionType": "textbook"}} {"path": "documents/math-quadratic-problem.png", "metadata": {"grade": "Grade 8", "subject": "Mathematics", "knowledgePoint": "quadratic function", "questionType": "practice question"}} {"path": "documents/math-quadratic-answers.docx", "metadata": {"grade": "Grade 8", "subject": "Mathematics", "knowledgePoint": "quadratic function", "questionType": "ground truth"}} {"path": "documents/math-pythagorean-exercise.docx", "metadata": {"grade": "Grade 8", "subject": "Mathematics", "knowledgePoint": "Pythagorean theorem", "questionType": "practice question"}}画像資料については、インポートの仕組みを理解してください。画像はまず光学文字認識 (OCR) を経てテキストに変換され、そのテキストがチャンキングされ、インデックス付けされます。したがって、
画像内のテキストが認識できるかどうかが、その画像を検索できるかどうかを左右します。テキストのない画像、たとえばテキストを含まない幾何学図形や関数グラフなどは、ほとんどヒットせず、独立した資料としてアップロードするには適していません。テキストを含む問題文と同じ画像または同じドキュメント内に配置してください。
問題の画像は鮮明にし、フォントサイズを十分に大きくし、印刷されたテキストが望ましいです。認識結果にずれが生じることがあります。たとえば、読点 (、) が別の記号として認識されたり、変数
xが乗算記号×として認識されたりすることがあります。特に数学記号でこの傾向が顕著です。
チャンキングの粒度を調整してください。問題と解説はほとんどが短い項目です。[Processing Strategy] のナレッジベース詳細ページで、[Create Strategy] をクリックしてチャンキングの粒度を調整してください。最大チャンク長の単位は文字です (デフォルト 512)。これを 580~770 文字 (約 384~512 トークン) に設定すると、問題文と解説が可能な限り同じチャンクに収まります。
ステップ3:検索パラメーターとプロンプトの設定
教育シナリオに合わせて、config.json のretrieval とscenario を調整します。
{
"retrieval": {
"page_size": 8,
"candidate_count": 64,
"min_score": 0.2,
"semantic_weight": 0.75,
"enable_query_expansion": true,
"rerank_model_name": "qwen3-rerank",
"tag_filter": {
"relation": "and",
"conditions": [
{"field": "subject", "op": "=", "value": "Mathematics"}
]
}
},
"scenario": {
"title": "教育問題バンクの検索と解説",
"system_prompt": "あなたはティーチングアシスタントです。検索された教科書、問題、グラウンドトゥルースにのみ基づいて解説してください。最初にアプローチ、次に手順、最後に答えの順で回答し、[出典 N] を引用してください。数式はプレーンテキストで記述し、LaTeX 構文は使用しないでください。検索された問題がユーザーの記述と一致しない場合は、問題バンクの回答を直接適用するのではなく、違いを明示的に指摘してください。資料が不十分な場合は、グラウンドトゥルースを推測しないでください。",
"image_enabled": true,
"sample_questions": [
"二次関数の頂点形式から最大値を見つける方法は?",
"ピタゴラスの定理を使った例題を見つけて解説してください。",
"この問題はどの知識ポイントを試していますか?"
]
}
}パラメーターの説明:
semantic_weight=0.75とqwen3-rerankの有効化:学生の質問は問題の自然言語による説明がほとんどであり、セマンティックの重みを高くすると類似問題のマッチングに有利になります。注意:再ランキングスコアとベクトルスコアは同じスケールではありません。最終スコアは
score ≈ (1-semantic_weight) × keywordScore + semantic_weight × semanticScore(ランク特徴も追加される場合があります) として計算されます。再ランキングが無効な場合、semanticScoreはベクトル類似度です。再ランキングが有効な場合、それは再ランキングモデルのスコアになり、min_scoreは常にこの最終スコアに基づいてフィルタリングを行います。テストでは、再ランキングを有効にすると、同じ質問に対する結果の数が 5 から 4 に減少しました。これはしきい値と新しいスケールの複合的な効果であり、再ランキングが再現率を悪化させることを意味するものではありません。コーパス全体に一般化できる推奨の組み合わせはありません。まず
min_scoreを 0 に設定して結果のバッチを検索し、それらの関連性を手動でラベル付けしてから、再現率と誤検出の分布に基づいてしきい値を選択してください。再ランキングモデルを切り替えたり、再ランキングをオン/オフしたり、semantic_weightを調整したりするたびに再調整してください。tag_filterでsubjectを固定すると、教科をまたいだ誤検出を効果的に防ぐことができます。テストでは、subject=Mathematicsフィルターを適用した状態で物理の知識ポイントについて質問すると 0 件の結果が返され、モデルはプロンプトに従って「資料が不十分です」と回答しました。opについては、実際に有効なのは=、in、not inの 3 つの演算子のみです。eq、==、equal、likeなどのエイリアスは400 Unsupported tag filter operatorを返し、すべてのクエリが失敗します。そのエラーメッセージの「サポートされている演算子」リストに≠、>、<、≥、≤、empty、not empty、start with、end withが表示されますが、テストしたところ、条件は暗黙的に無視され、フィルターされていないすべてのデータが返されました。注意:
containsとnot containsは単にin/not inのエイリアスです。これらは部分文字列の一致チェックは行わず、値として文字列の断片を渡すと 0 件の結果が返されます。範囲でフィルタリングするには、
inで値を列挙してください。タグが空かどうかを確認するには、= ""を使用してください。設定後、フィルターが有効であることを確認するために、フィルターの有無による結果の総数を常に比較してください。system_promptで、「数式はプレーンテキストで」と明示的に記述してください。教育関連のプロンプトはモデルに LaTeX を出力させる傾向がありますが、サンプルページは<pre>プレーンテキストで表示されるため、数式はレンダリングされず、生のドル記号やバックスラッシュとして表示されます。LaTeX を保持したい場合は、KaTeX や MathJax をページに統合してください。
ステップ4:アップロード、公開、検証
資料をアップロードします。
MetaFieldsはバッチ全体に適用されます。スクリプトはまずタグで資料をグループ化し、バッチで送信します。python upload.py --manifest documents.jsonlコンソールの [Data Management] ページで、資料のステータスが [Processed] であることを確認してください。画像資料については、[View Chunks] をクリックし、認識されたテキストが画像の内容と一致することを確認してから、バージョンを公開してください。
[Version Management] ページで、[Publish Version] をクリックしてください。3 ステップのウィザードを完了した後、新しいバージョンのステータスが [Published] であることを確認してください。
重要同時に存在できる公開済みバージョンは最大 3 つです。上限に達すると、[Publish Version] ボタンはグレーアウトされますが、ページには「現在、公開待ちの変更が N 件あります」と表示されたままになります。まず、バージョン履歴で不要になった古いバージョンを削除する必要があります。バージョンの削除は元に戻せません。問題バンクには通常、学期ごとまたは単元ごとに資料が追加されるため、「現在のバージョン + 最新の履歴バージョン」のみを保持してください。
サービスを開始してください。Q&A ページは
http://127.0.0.1:7860で配信されます。python app.py問題バンクに画像資料が含まれている場合は、画像クエリを試してください。
app.pyの/api/askエンドポイントは、オプションのimage_urlパラメーターを受け取り、それをSearchKnowledgeBaseのimageフィールドに渡します。画像は、参照が不明確な問題に最も役立ちます。テストでは、「この問題はどの知識ポイントを試していますか?」という同じ質問に対して、画像がない場合はピタゴラスの定理の演習問題がヒットしました (関連度 0.431、意図した問題ではない)。二次関数の問題の画像を添付すると、問題バンク内の二次関数の問題がヒットしました (0.583)。画像が検索のための重要なセマンティクスを提供しました。curl -sS http://127.0.0.1:7860/api/ask \ -H 'Content-Type: application/json' \ -d '{"question":"この問題はどの知識ポイントを試していますか?","image_url":"https://<パブリックにアクセス可能な画像 URL>"}'結果を以下の 4 つのチェック項目で検証してください。
http://127.0.0.1:7860のページが正常に開くこと。教育シナリオでは、問題画像の URL の入力ボックスが追加で表示されます。質問を送信すると、回答と検索ソースの両方が返されます。回答内の各
[出典 N]に、下のソースセクションに対応する資料チャンクがあります。問題バンクがカバーしていない内容について質問した場合、回答は回答を捏造するのではなく、資料が不十分であることを明示的に伝えます。
資料を追加してバージョンを再公開した後、ページは新しいコンテンツを検索できます。
セマンティック検索の検証をもう 1 つ追加します。ファイル名ではなく、資料の内容にのみ現れる情報 (たとえば、問題番号) で質問し、対応する資料がヒットすることを確認します。このチェックは、画像が正しく認識されインポートされたかどうかを検証するのにも適用されます。
画像クエリの機能と制約
画像は検索にのみ使用され、LLM には送信されません。システムの動作は、「画像に基づいて問題バンク内で最も類似した問題を検索し、検索された資料に基づいて解説する」ことであり、「画像内の問題を認識して解く」ことではありません。問題バンクに存在しない新しい問題をアップロードすると、システムはバンク内で最も類似した問題で応答し、その回答は画像内の問題と異なっていても気づかれないことがあります。たとえば、y=-(x-1)²+4 (最大値は 4) をアップロードしたときに、問題バンクにy=-2(x-3)²+5 が存在する場合、回答は最大値 5 を返すかもしれません。したがって、
ページに「画像は問題バンク内の類似問題を検索するために使用されます」というヒントを表示します。
プロンプトでモデルに、検索結果とユーザーの記述との違いを指摘するように要求します。
したがって、この機能は「画像支援検索」または「画像ベースの問題検索」と呼ぶべきであり、外部に対して「写真による解答」として提示してはなりません。画像内の新しい問題を解くには、アプリケーション層が元の画像をマルチモーダル入力に対応する LLM に別途渡し、検索された資料と照合するように LLM に指示する必要があります。ナレッジベースの検索だけに依存しないでください。
image_url はパブリックにアクセス可能なアドレスでなければなりません。サーバー側で次のように検証されます。
入力 | サーバーの応答 |
イントラネットまたはローカルアドレス (例: |
|
画像以外のリソースへのリンク |
|
解決できないドメイン名 |
|
空のままにする | プレーンテキスト検索にフォールバックします (正常な動作) |
画像認識には以下の制約があり、問題バンクの資料を準備する前に理解しておく必要があります。
フォーマット:JPG、JPEG、PNG、GIF のみを使用してください。基盤となるファイル認識は WebP や TIFF などのフォーマットも受け付ける場合がありますが、公式にサポートされているわけではないため、それらに依存しないでください。
サイズ:API には画像のバイト数やピクセル数に関する個別のハードリミットはありませんが、実際にはアップロードゲートウェイ、画像デコード、メモリ、および画像からテキストへの変換モデルサービスによって複合的に制約されます。大きすぎる画像は失敗する可能性があります。
認識精度:手書き、数式、幾何学図形、または座標系に対して、保証された精度指標はありません。テキストのない画像は、画像からテキストへの変換によって説明が生成される場合がありますが、検索ヒットは保証されません。今回のテストでは、
xが×として認識され、読点が単一のドットストローク文字として認識されました。特に数学記号は手動でのスポットチェックが必要です。認識品質のしきい値なし:画像がデコードでき、パイプラインがエラーを報告しない限り、認識されたテキストが非常にまばらであったり間違っていたりしても、ドキュメントのステータスは [Processed] になります。デコードが失敗した場合や、必要なモデル呼び出しでエラーが発生した場合にのみ、Processing Failed が表示されます。したがって、アップロード後に [Data Management] ページでチャンクテキストをスポットチェックする必要があります。ステータスだけに依存しないでください。
教育シナリオでの使用上の注意
教科書、問題、解答をセットとしてアップロードし、
questionTypeで区別して、必要に応じてフィルタリングできるようにしてください (たとえば、学生には「練習問題」のみを検索させ、教師には「グラウンドトゥルース」を検索させるなど)。教科ごとに独立したエントリを作成してください:
tag_filterでsubjectを固定すると、そのエントリはその教科の質問にしか答えられなくなります。サンプル質問も同じ教科に保ってください。そうしないと、他の教科について質問する学生は「資料が不十分です」という回答しか得られません。解答資料へのアクセスを別途制限してください:学生がグラウンドトゥルースを直接取得できないようにする場合は、学生向けのエントリで
questionType not in ["ground truth"]のような条件でフィルタリングしてください。検索結果には
imagesフィールドが含まれています。設計上、このフィールドはチャンクに関連付けられた画像を返し、サーバーは永続化された画像に対して短期間有効な署名付き URL を生成します。このフィールドは実装済みの機能であり、予約済みの空フィールドではありません。ただし、現在このフィールドは画像 URL を返しません。画像ドキュメントがヒットしてもフィールドが空の場合、これらの資料の画像は解析およびチャンキングの段階で対応するチャンクに永続化されなかったか、署名の関連付けが確立されなかったかのいずれかであり、ドキュメントごとに調査が必要なパイプラインの問題です。これを有効にするリクエストパラメーターはないため、「常に空である」ことを製品設計として扱わないでください。長期的には「ファイル名 → 画像 URL」のマッピングテーブルを自分で維持する必要はありません。短期的にはページは認識されたテキストの表示にフォールバックできます。元の問題画像を表示する必要がある場合は、インポートマニフェストとdocumentIdを介して関連付けることで一時的に対処してください。重要な結論については手動でのレビューを継続し、公式の教科書と教師の解説が優先されることを学生に念押ししてください。
よくある質問
症状 | 原因と解決策 |
クエリが 500 を返し、ログに |
|
タグフィルターを追加しても、結果の数がフィルターなしの場合とまったく同じ | サポートされていない演算子 ( |
アップロード後に画像資料が見つからない | 順に確認してください:ナレッジベースのデータタイプが画像に対応しているか。データのステータスが [Processed] になっているか。[View Chunks] で認識されたテキストが空であったり、画像と一致していなかったりしないか (テキストのない画像、フォントサイズが小さすぎる、手書きなどは認識失敗の原因となり得ます)。 |
問題の画像で質問したが、回答が別の問題に関するものだった | 想定される動作です。画像は類似の問題を検索するためにのみ使用され、モデルは検索された問題を解説します。 |
クエリが |
|
ページ上で数式が | モデルが LaTeX を出力しましたが、ページがそれをプレーンテキストとしてレンダリングしています。プロンプトでプレーンテキストの数式を要求するか、数式レンダリングライブラリをページに統合してください。 |
再ランキングを有効にすると結果が少なくなる | 再ランキングスコアとベクトルスコアのスケールが異なるため、 |
タグフィルターが常に 0 件の結果を返す | タグ名のスペルが定義と異なっていることが原因です (API はエラーを報告せず、単に 0 件の結果を返します)。ナレッジベース詳細ページ → [Tags] → [Manage] で確認してください。 |
アップロードが | バッチ内のすべてのファイルが、名前が同一であるために重複排除されました。ファイル名を変更するか、まずコンソールで古いデータを削除してください。 |
検索が | バージョンが公開されていないか、指定されたバージョン番号が存在しません。 |