Personal Project / Site Feature

履歷 AI 問答系統

只根據公開履歷內容回答問題,不接受忽略規則的指示,也不會為了回答完整而編造沒有的經驗;每個關鍵設計都用真實 API 呼叫驗證過。

履歷網站首頁畫面,右下角為 RAG 問答聊天機器人入口
上線中
Type
Site Feature
Status
上線中
Focus
OpenAI Embeddings / Qdrant
Stack
OpenAI Embeddings / Qdrant / FastAPI
01 / Project Scope

部署架構圖

只畫 RAG 問答系統實際會經過的部署元件——聊天元件所在的前端頁面/文章同步用的外部 API 跟這個問答流程無關,不畫進來;但資料庫因為每次問答都會記錄問答紀錄與訪客回饋,確實是流程的一部分,畫回來了。

CLIENT訪客瀏覽器Chat Widget(SSE Client)ORACLE CLOUD VM · 單機部署EDGENginx反向代理(SSE 停用緩衝)BACKEND後端 APIFastAPI 服務VECTOR DBQdrant向量資料庫CACHERedis限流計數(IP + 全站)SHARED SERVICEPostgreSQL問答紀錄與訪客回饋ONE-OFF JOB索引同步工作內容變更時觸發,寫入向量資料庫內部呼叫跨網路的對外 HTTPS 呼叫EXTERNAL · 外部服務THIRD-PARTY APIOpenAI APIEmbeddings + 生成/重排序模型查詢流程呼叫索引流程呼叫(Embeddings)
02 / Project Scope

系統流程圖

每個節點右上角的編號(I-01…I-04 索引流程/Q-01…Q-07 查詢流程)對應下方「03 技術地圖」每一列左邊的標籤,可以直接對照同一個技術在流程圖裡的位置。

INDEXING · 離線/內容更新時執行一次SOURCEI-01Markdown 內容公開履歷內容目錄CHUNKINGI-02切塊 + Content Hash穩定 chunk ID,增量同步EMBEDDINGI-03OpenAI Embeddings文字轉向量VECTOR STOREI-04Qdrant向量庫 · cosine similarity沿用索引流程建立的同一個 Qdrant 集合QUERY · 每次訪客提問即時執行INPUTQ-01使用者提問+ 最近幾輪對話歷史RETRIEVALQ-02Qdrant 向量檢索撈寬候選池 15 筆Q-03Top-1 分數≥ 0.30?是否STOP拒答固定文案,不呼叫生成模型RERANKQ-04LLM 重排序15 筆 → 精選 7 筆GENERATEQ-05生成模型+誠實規則約束DELIVERYQ-06SSE 串流逐句回傳訪客瀏覽器best-effortLOGGINGQ-07寫入問答紀錄寫進資料庫,不阻塞回答失敗只記 log,不影響訪客體驗
03 / Project Scope

技術地圖:用了什麼、放在哪、做什麼、怎麼優化

索引流程 · Indexing

I-01–I-02

Markdown 切塊 + Content Hash

公開內容依標題結構切塊,每塊配一組穩定 chunk ID,內容更新時只需重算真的變更過的區塊,不用整庫重建。

初始設計即採用,沒有額外調整。

I-03

OpenAI Embeddings

索引與查詢共用同一個 embedding 模型,把文字轉成向量以支援語意檢索,而不是關鍵字比對。

曾評估本機 Ollama embedding,因 Server 只有 2 OCPU、推論成本划不來,改採 OpenAI API。

I-04

Qdrant

向量資料庫,儲存所有內容區塊的向量,查詢時用 cosine similarity 找出最接近問題的候選內容。

初始設計即採用,沒有額外調整。

查詢流程 · Query

Q-01

多輪對話記憶

追問時自動帶入最近幾輪問題一起檢索,讓系統能理解代名詞指代的對象。

A/B 實測:單獨檢索追問句子,5 組配對 4 組分數落在 0.31~0.35;接上歷史後提升到 0.51~0.69,才定案採用。

Q-03

兩層信心門檻

Top-1 分數 < 0.30 直接拒答,門檻以上交給生成階段的誠實規則判斷,避免誤傷籠統但合理的問題。

第一版門檻 0.55;擴充測試集後發現籠統問題與不應答問題分數完全重疊,改成兩層分工、降到 0.30。

Q-04

LLM 重排序

候選池撈寬到 15 筆,用 LLM 評分排序後取最相關 7 筆組成回答 context,失敗時整組退回原始排序。

一度讓 TTFB 從 2.4 秒暴增到 6.6 秒;查證 reasoning_effort 參數只對排序調到最低,TTFB 壓回 3.6 秒,降低約 71%。

Q-05

生成模型 + 誠實規則

只能根據檢索到的 context 回答,資訊不足要誠實表示無法確認,避免編造經驗或跨公司誤植。

8 組對抗性測試(套話、角色扮演、忽略指示、誘導承認未做過的經驗),7/8 完全乾淨、1/8 部分洩漏但不敏感。

Q-06

SSE 逐句串流

回答以句尾符號為切點累積後才吐出,不是逐 token,降低感知延遲也避免引用標記被切斷。

採 prime-then-stream:先在 endpoint 跑完驗證與檢索、拿到第一個事件才建構串流回應,確保錯誤仍能用原本 JSON 格式呈現。

Q-07

問答紀錄與訪客回饋

每次問答寫進資料庫,訪客可以按 👍/👎,用來持續觀察與改善回答品質。

採 best-effort:寫入失敗不影響訪客拿到回答,只記 log;前端失敗時悄悄還原可點擊狀態,不彈錯誤打斷體驗。

CLIENT訪客瀏覽器Chat Widget(SSE Client)ORACLE CLOUD VM · 單機部署EDGENginx反向代理(SSE 停用緩衝)BACKEND後端 APIFastAPI 服務VECTOR DBQdrant向量資料庫CACHERedis限流計數(IP + 全站)SHARED SERVICEPostgreSQL問答紀錄與訪客回饋ONE-OFF JOB索引同步工作內容變更時觸發,寫入向量資料庫內部呼叫跨網路的對外 HTTPS 呼叫EXTERNAL · 外部服務THIRD-PARTY APIOpenAI APIEmbeddings + 生成/重排序模型查詢流程呼叫索引流程呼叫(Embeddings)
INDEXING · 離線/內容更新時執行一次SOURCEI-01Markdown 內容公開履歷內容目錄CHUNKINGI-02切塊 + Content Hash穩定 chunk ID,增量同步EMBEDDINGI-03OpenAI Embeddings文字轉向量VECTOR STOREI-04Qdrant向量庫 · cosine similarity沿用索引流程建立的同一個 Qdrant 集合QUERY · 每次訪客提問即時執行INPUTQ-01使用者提問+ 最近幾輪對話歷史RETRIEVALQ-02Qdrant 向量檢索撈寬候選池 15 筆Q-03Top-1 分數≥ 0.30?是否STOP拒答固定文案,不呼叫生成模型RERANKQ-04LLM 重排序15 筆 → 精選 7 筆GENERATEQ-05生成模型+誠實規則約束DELIVERYQ-06SSE 串流逐句回傳訪客瀏覽器best-effortLOGGINGQ-07寫入問答紀錄寫進資料庫,不阻塞回答失敗只記 log,不影響訪客體驗