全部產品
Search
文件中心

Vector Retrieval Service for Milvus:通過阿里雲Milvus知識庫搭建教育題庫問答應用

更新時間:Aug 28, 2026

阿里雲 Milvus 知識庫可以把教材、教案、題目與標準答案建成可檢索的題庫助手:學生用自然語言提問即可拿到講解與原文依據,也可以上傳題目圖片,從題庫中找出相似題並結合教材講解。

方案說明

整體鏈路與通過阿里雲Milvus知識庫搭建智能客服問答應用完全一致:控制台定義標籤 → 按標籤大量匯入資料 → 發布版本 → SDK 檢索(可按標籤過濾、可附帶圖片)→ 大模型產生帶來源標註的回答 → Flask 提供問答頁面。工程代碼(kb_client.py、upload.py、app.py、templates/index.html、start.sh)請直接複用該文,本文只說明教育情境需要改動的部分:學科與知識點標籤、圖片資料的處理方式、圖片查詢的能力邊界、以及公式展示。

建議第一版只選擇一個年級、一個學科的 5~20 篇資料,驗證後再擴大範圍。整體耗時約 25~40 分鐘,其中文檔解析耗時取決於資料數量與大小。

前提條件

  • 已建立 Milvus 知識庫並記錄知識庫 ID(形如 kd-803ae9b10cc31)。

  • 建立一個全模態知識庫。當前控制台建立知識庫時固定使用全模態(ALL_MODAL)類型,頁面上沒有其他選項,因此無需額外判斷;該屬性建立後不可修改,可在知識庫詳情頁的基本資料中查看資料類型。需要注意的是,結構化類型的知識庫只接受 xlsx、xls、csv、jsonl、faq 五種格式,上傳圖片會直接返回參數錯誤,因此題庫這類含圖資料必須使用全模態知識庫。

  • 已使用主帳號建立 RAM 使用者、勾選使用永久 AccessKey 訪問,並授予系統策略 AliyunMilvusFullAccess。

  • 已準備支援 OpenAI chat/completions 協議的大模型地址與 API Key。

  • 本地已安裝 Python 3.8 或以上版本,並已按上文教程建好工程目錄。

步驟一:定義年級與知識點標籤

在知識庫詳情頁的基本資料下方單擊標籤 > 管理,添加以下四個標籤(類型均為 string):

標籤名

說明

樣本值

grade

年級

八年級

subject

學科

數學、物理

knowledgePoint

知識點

二次函數、勾股定理

questionType

資料類型

教材、練習題、標準答案

標籤值支援中文,可直接使用年級、學科與知識點的中文名稱。

重要

標籤管理對話方塊是整體儲存的。對話方塊開啟後標籤列表為非同步載入,請等到已有標籤全部顯示出來,再添加新標籤並單擊完成;否則可能以"空列表 + 新標籤"整體覆蓋,導致已有標籤定義被清除。

步驟二:準備資料與匯入清單

  1. 把資料放進 documents/ 目錄,支援 PDF、DOCX、Markdown、TXT 與圖片。建議教材、題目、標準答案成套上傳:講解時模型會同時引用教材中的方法、題目原文與答案中的評分要點,回答完整度明顯更高。

  2. 建立 documents.jsonl,為每篇資料標註年級、學科、知識點與資料類型。

    {"path": "documents/math-grade8-textbook.pdf", "metadata": {"grade": "八年級", "subject": "數學", "knowledgePoint": "二次函數", "questionType": "教材"}}
    {"path": "documents/math-quadratic-problem.png", "metadata": {"grade": "八年級", "subject": "數學", "knowledgePoint": "二次函數", "questionType": "練習題"}}
    {"path": "documents/math-quadratic-answers.docx", "metadata": {"grade": "八年級", "subject": "數學", "knowledgePoint": "二次函數", "questionType": "標準答案"}}
    {"path": "documents/math-pythagorean-exercise.docx", "metadata": {"grade": "八年級", "subject": "數學", "knowledgePoint": "勾股定理", "questionType": "練習題"}}
  3. 關於圖片資料,需要瞭解其入庫方式:圖片會先經過文字識別(OCR)轉成文本,再按文本切片建立索引。因此:

    • 圖中文字能否被識別,決定這張圖能否被檢索到。純圖形(沒有文字的幾何圖、函數圖象)幾乎無法被命中,不適合作為獨立資料上傳,建議與含文字的題幹放在同一張圖或同一篇文檔中。

    • 題目圖片應保持清晰、字型大小足夠、盡量使用印刷體。識別結果可能出現偏差(例如把頓號識別成其他符號、把變數 x 識別成乘號 ×),數學符號尤其容易受影響。

    • 上傳後建議到資料管理頁單擊查看切片,確認識別出的文本與圖中內容一致,再發布版本。

  4. 題目與解析多為短條目,可在知識庫詳情頁的處理策略中單擊建立策略調整切片粒度。最大分段長度的單位是字元(預設 512),建議設定為 580~770 字元(約相當於 384~512 tokens),盡量讓"題幹 + 解析"保持在同一個切片內。

步驟三:配置檢索參數與提示詞

在 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": "數學"}
      ]
    }
  },
  "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(另可能疊加 rank feature),未啟用重排時 semanticScore 是向量相似性,啟用重排後它變成重排模型分數,而 min_score 始終在這個最終分數上過濾。因此實測同一問題在啟用重排後返回條數由 5 條降為 4 條,是閾值與新量綱共同作用的結果,並不說明重排讓召回變差。

    沒有跨語料通用的推薦組合:建議先把 min_score 設為 0 取回一批結果並人工標註相關性,再按召回與誤召回的分布選閾值;每次切換重排模型、開關重排或調整 semantic_weight 後都要重新校準。

  • tag_filter 固定 subject:可有效防止跨學科誤召回。實測在 subject=數學 過濾下提問物理知識點,返回 0 條,模型會按提示詞回答"資料不足"。

  • op 實際只有 =、in、not in 三個運算子生效。寫成 eq、==、equal、like 等別名會返回 400 Unsupported tag filter operator,導致每次提問都失敗;而 ≠、>、<、≥、≤、empty、not empty、start with、end with 雖然出現在該報錯列出的 "Supported operators" 清單中,實測條件會被靜默忽略、返回未經過濾的全部資料。

    其中 contains、not contains 只是 in/not in 的別名,並不是字串包含,按字串片段傳值只會返回 0 條。

    需要按區間篩選時請用 in 枚舉取值,需要判斷標籤為空白時請用 = "";配置後務必與不加過濾的結果對比總條數,確認過濾生效。

  • system_prompt 中建議明確"公式使用純文字":教學類提示詞容易讓模型輸出 LaTeX,而樣本頁面用 <pre> 純文字展示,公式不會渲染,會顯示為原始的貨幣符號與反斜線。若希望保留 LaTeX,請在頁面中引入 KaTeX 或 MathJax。

步驟四:圖片查詢的用法與能力邊界

app.py 的 /api/ask 接受可選的 image_url 參數,並透傳給 SearchKnowledgeBase 的 image 欄位:

curl -sS http://127.0.0.1:7860/api/ask \
  -H 'Content-Type: application/json' \
  -d '{"question":"這道題考查了哪些知識點?","image_url":"https://<可公網訪問的圖片地址>"}'

圖片對指代不明的提問協助最大。實測同一個問題「這道題考查了哪些知識點?」:不帶圖片時命中的是勾股定理練習(相關度 0.431,並不是想問的題);帶上二次函數題目圖片後,命中的是題庫中的二次函數題目(0.583),可見圖片為檢索提供了關鍵語義。

重要

圖片只參與檢索,不會被送給大模型。 系統的行為是"根據圖片在題庫中找出最相似的題目,然後依據檢索到的資料講解",不是"識別並解答圖片中的題目"。若上傳的是一道題庫中不存在的新題,系統會拿最相似的庫內題目作答,答案可能與圖中題目不同且不易察覺。例如上傳 y=-(x-1)²+4(最大值為 4)時,若題庫中存在 y=-2(x-3)²+5,回答可能給出最大值 5。 因此建議:在頁面上提示"圖片用於尋找題庫中的相似題";在提示詞中要求模型指出檢索結果與使用者描述的差異;因此這項能力應當被稱為「圖片輔助檢索」或「以圖搜題」,不能對外表述為「拍照解題」。若確實需要解答圖中的新題,必須由應用程式層把原圖另外傳給支援多模態輸入的大模型,並要求它同時核對檢索到的資料,而不是只依賴知識庫檢索。

圖片的識別能力有以下邊界,準備題庫素材前需要瞭解:

  • 格式:建議只使用 JPG、JPEG、PNG、GIF。底層檔案識別可能還接受 WebP、TIFF 等格式,但沒有統一的對外約定,不建議依賴。

  • 大小:介面沒有單獨的圖片位元組數或像素硬上限,但實際會受上傳網關、映像解碼、記憶體以及圖文轉換模型服務的共同限制,超大圖仍可能失敗。

  • 識別準確率:手寫體、數學公式、幾何圖形、座標系都沒有承諾的準確率指標。純圖形可能由圖文轉換產生一段描述,但不保證能被檢索命中。本文實測中,x 被識別成 ×、頓號被識別成「丶」,數學符號尤其需要人工抽查。

  • 沒有識別品質閾值:只要圖片能被解碼且流程未報錯,文檔狀態就是處理完成,即使識別出的文本很少或有錯誤;只有解碼失敗或所需模型調用報錯才會顯示處理失敗。因此上傳後必須到資料管理頁抽查切片文本,不能只看狀態。

關於圖片地址,image_url 必須是可公網訪問的地址,服務端會校正:

傳入內容

服務端返回

內網或本機地址(如 127.0.0.1)

400 URL resolves to a non-public or blocked address

非圖片資源的連結

400 image_query URL must point to an image.

無法解析的網域名稱

400 Could not resolve hostname

留空

退化為普通文字檢索(正常行為)

最後是回顯原題圖的問題。檢索結果裡有一個 images 欄位,用於返回切片關聯的圖片(服務端會為已持久化的圖片產生短期有效簽名地址)。該欄位本身是已實現的能力,並非預留的空欄位;如果命中了圖片文檔但它仍然返回空,說明這批資料在解析切片階段沒有把圖片 ID 持久化到對應切片,或者簽名關聯沒有建立,屬於需要按具體文檔排查的鏈路問題,沒有任何請求參數可以開啟它。因此不要把「一直為空白」當作產品設計,也不需要為此長期自我維護一份「檔案名稱 → 公網圖片地址」的映射表;在它為空白期間,頁面可以先降級展示識別出的題目文本。

步驟五:上傳、發布與驗證

  1. 上傳資料(MetaFields 對整批生效,指令碼會先按標籤分組再分批提交)。

    python upload.py --manifest documents.jsonl
  2. 到控制台資料管理頁確認資料狀態為處理完成,並對圖片資料單擊查看切片核對識別文本。

  3. 在版本管理頁單擊發布版本,完成三步嚮導後確認新版本狀態為發行。

    重要

    同時最多隻能存在 3 個發行版本。達到上限後發布版本按鈕會置灰,而頁面仍會顯示"當前有 N 條待發布變更",需要先在版本記錄中刪除不再需要的舊版本。版本刪除不可恢複。題庫通常每學期或每單元都會補充資料,建議只保留"目前的版本 + 最近一個歷史版本"。

  4. 啟動服務並驗證。

    python app.py

    按以下四條驗收:

    • 頁面能正常開啟(教育情境會額外顯示題目圖片 URL 輸入框),提交問題後同時返回答案與檢索來源。

    • 回答中的 [來源N] 能在下方來源區找到對應的資料切片。

    • 提問題庫未覆蓋的內容時,回答明確說明資料不足,而不是補寫答案。

    • 補充資料並重新發布版本後,頁面能檢索到新內容。

建議再補一條針對語義召回的驗證:用只出現在資料內容裡、不出現在檔案名稱中的資訊提問(例如題目編號),確認能命中對應資料。這條同樣適用於檢查圖片是否被正確識別入庫。

教育情境注意事項

  • 教材、題目、答案成套上傳,並用 questionType 區分,便於按需過濾(例如只給學生檢索"練習題",給教師檢索"標準答案")。

  • 按學科建立獨立入口:tag_filter 固定 subject 後,該入口只能回答該學科的問題,樣本問題也應保持同一學科,否則學生提問其他學科只會得到"資料不足"。

  • 答案類資料建議單獨控制訪問:若不希望學生直接拿到標準答案,可在學生入口用 questionType not in ["標準答案"] 之類的條件過濾。

  • 檢索結果的 images 欄位當前取不到圖片地址,頁面展示的是識別後的文本。該欄位本身是已實現的能力,取不到值屬於解析鏈路未把圖片關聯到切片,不需要為此長期自我維護「檔案名稱 → 圖片地址」的映射表:短期內頁面可先降級展示識別文本,需要回顯原題圖時再按 documentId 關聯匯入清單臨時處理。

  • 關鍵結論建議保留人工核對,並提示學生以正式教材與教師講解為準。

常見問題

現象

原因與處理

提問返回 500,日誌顯示 400 Unsupported tag filter operator

op 使用了 eq、==、like 等別名,改用 =、in、not in。

加了標籤過濾但結果條數與不加過濾時完全一樣

使用了不生效的運算子(如 >、≥、≠、empty)。只有 =、in、not in 會生效。

圖片資料上傳後搜不到

依次確認:知識庫資料類型是否支援圖片;資料狀態是否為處理完成;查看切片中識別出的文本是否為空白或與圖中不符(純圖形、字型大小過小、手寫體都可能導致識別失敗)。

上傳圖片提問,回答的卻是另一道題

預期行為。圖片只用於檢索相似題,模型講解的是檢索到的題目,詳見步驟四。

提問返回 400 URL resolves to a non-public or blocked address

image_url 指向內網或本機地址,需改為可公網訪問的圖片地址。

頁面上公式顯示成 $y = a(x-h)^2 + k$

模型輸出了 LaTeX 而頁面按純文字展示。在提示詞中要求使用純文字公式,或在頁面引入公式渲染庫。

啟用重排後結果反而變少

重排分數與向量分數量綱不同,與 min_score 疊加會過濾更多結果。可先降低 min_score 或關閉重排對比效果。

按標籤過濾後總是 0 條

標籤名拼字與寫入時不一致(介面不會報錯,只返回 0 條)。在知識庫詳情頁 → 標籤 → 管理中核對。

上傳返回 400 No OSS document can be registered.

整批檔案都因同名被去重。修改檔案名稱或先在控制台刪除舊資料。

檢索返回 404 Knowledge base version ... does not exist

尚未發布版本,或指定的版本號碼不存在。