信託信用卡智能助理
別再被卡片淹沒——根據使用者的需求,得到有來源的推薦
面試者: 余孟潔
使用者不用先懂卡片分類,只要說出消費情境
02
ctbc-card-rag-assistant | FastAPI + React/Vite + RAG
LINE Pay
旅遊
哩程
網購
加油
foodpanda
停車
保險
新戶
我想幫他快速找到第一批適合申辦的卡,而不是一張一張比。
既有客戶
當消費習慣改變時,可以重新比較哪張卡現在更適合。
客服 / 行銷
同一套資料也能支援一致、有來源的產品說明。
目標使用者與業務問題定義
03
ctbc-card-rag-assistant | FastAPI + React/Vite + RAG
使用者端
優惠太多,期限、通路、上限、登錄條件混在一起,容易看完還是不確定。
業務端
官網資訊完整,但使用者很難跨卡比較;也少了最後一步的申辦引導。
我觀察到的官網體驗痛點
使用者用情境思考,但網站通常用產品頁呈現
04
ctbc-card-rag-assistant | FastAPI + React/Vite + RAG
資訊分散
卡片頁、活動頁、條款與申請條件散在不同位置。
分類落差
使用者說「出國、網購、LINE Pay」,不一定知道要點哪個卡別。
理解成本高
回饋率、上限、登錄、期間與排除條件常需要反覆確認。
比較不足
使用者需要自己整理差異,下一步申辦也不一定順。
我的解法與預期價值
自然語言需求解析 + RAG + 混合檢索 + 有根據的回答
05
ctbc-card-rag-assistant | FastAPI + React/Vite + RAG
使用者價值
少花時間找資料,直接看到適合情境的候選卡和注意事項。
業務價值
提升產品探索與申辦導流,也降低重複客服問答。
營運價值
把使用者問題轉成情境標籤,累積可分析的需求資料。
使用者需求
理解意圖
混合檢索
重新排序
有來源回答
申辦導流
我做的系統架構
前端負責體驗,後端負責 RAG 流程與可追溯性
06
ctbc-card-rag-assistant | FastAPI + React/Vite + RAG
React / Vite
呈現 Markdown 回答、卡片圖片、來源與申辦連結。
FastAPI
提供 /chat、/cards/search、/health,也保留 reindex 能力。
CardRAGEngine
整合意圖判斷、推薦卡片、引用來源與回答格式。
HybridRetriever
用 BM25 + dense + RRF 兼顧關鍵字與語意召回。
Chroma / fallback
可接本機或外部 embedding;沒模型時仍可跑 demo。
架構Overview
07
ctbc-card-rag-assistant | FastAPI + React/Vite + RAG
ctbc-card-rag-assistant | FastAPI + React/Vite + RAG
資料處理
08
cardlist
JSON
detail
pages
clean /
normalize
semantic
chunks
metadata
BM25 +
Chroma
我怎麼理解問題與找資料
先判斷使用者想做什麼,再用兩種檢索互補
09
ctbc-card-rag-assistant | FastAPI + React/Vite + RAG
Intent
分成推薦、單卡問答、跨卡比較、一般規則問題。
Query expansion
把「出國、網購、外送」這類口語需求展開成官網資料常用詞。
BM25
處理卡名、通路、活動關鍵字;中文用斷詞與欄位加權。
Dense + RRF
補足語意相近但字面不同的問題,再用 RRF 融合排序。
我怎麼找資料與排序
BM25 找精準字,Chroma dense 補語意,RRF 負責融合排名
10
ctbc-card-rag-assistant | FastAPI + React/Vite + RAG
Chunks
檢索的單位是 chunks:卡片簡介、主要回饋、適合族群、注意事項、活動提醒與詳細 tabs;每個 chunk 都帶卡名、來源、申辦連結和 section。
BM25
BM25 不是只看正文,也看卡名、分類、情境標籤與段落;例如 card_name 3.5、scenario_tags 2.0,讓明確卡名或通路更容易命中。
Chroma dense
用 OpenAI text-embedding-3-small 查語意相近的 chunks,補足使用者口語和官網用語不同的情況。
RRF + card ranking
BM25 與 dense 各自排序後用 RRF 融合;再把 chunks group 回卡片,依提到的卡、比較題、上下架、情境 priority 與 RRF score 排序。
我怎麼讓 OpenAI 回答但不亂猜
LLM 負責把 citations 講清楚,不負責自己查資料或猜答案
11
ctbc-card-rag-assistant | FastAPI + React/Vite + RAG
Prompt inputs
我只把 intent、使用者原問題、已檢索出的 citation context 放進 prompt。
Grounding
Prompt 明確要求:只能根據 context 回答,不能編造回饋率、期限、申請條件或活動限制。
Output
用繁中客服語氣整理推薦理由、限制提醒與下一步行動;來源由 citations 欄位呈現。
Fallback
OpenAI 成功會標記 llm_used;如果呼叫失敗,就回 deterministic template,確保 demo 可執行。
我的技術選擇與取捨
我優先確保 Demo 穩定,同時保留上線後可擴充
12
ctbc-card-rag-assistant | FastAPI + React/Vite + RAG
React / Vite + FastAPI
前後端分離,Demo 好展示,之後也容易接正式服務。
BM25 + dense + RRF
避免只靠 LLM;關鍵字命中與語意召回可以互補。
OpenAI API
Demo確定穩定性,後續可與地端模型混和搭用,更可以方便在資料控管與效果間切換。
Deterministic + seed fallback
就算沒有 LLM 或網路,也能完整展示資料到回答的流程。
13
ctbc-card-rag-assistant | FastAPI + React/Vite + RAG
Thanks