「最好的 AI Agent 不是固定不變的系統,而是在每一次與使用者的對話中,自動汲取經驗並寫回知識庫、自我進化的系統。」
在 Day 06 中,我們介紹了 SQLite 持久化長效記憶(conversation_memory.py)。今天我們將深入探討 AI 核心架構的最後一塊拼圖——背景自動學習模組 app/services/learning_module.py。
為了不增加使用者的等待時間,Angelina AI Agent 採用了 Non-blocking 架構:對話回應生成後立即交付給前端,隨後在背景觸發 LearningModule,透過 Gemini API 提煉該輪對話中的金融知識點,經由 ChromaDB Deduplication 後,自動存入向量知識庫中。
傳統的知識庫更新通常需要人工手動匯入檔案,而 LearningModule 實現了對話即學習(Conversation-driven Learning):
1. 非阻塞式背景任務:透過 asyncio.create_task(_learning_module.extract_and_store(...)) 觸發,完全獨立於 API 響應流程外執行。
2. Silent Error Handling:背景任務若遇到網路波動或解析失敗,僅記錄結構化日誌(log.error),絕不干擾或崩潰主應用程式。
3. 領域聚焦萃取:限定僅萃取「投資策略、稅務規則、預算原則、風險管理指引與市場數據」等五大金融領域知識點。
Python
async def _extract_knowledge_points(self, turn: Turn) -> list[dict]:
"""呼叫 Gemini API 識別對話中的金融知識點"""
try:
response = await self._gemini_gateway.generate(
system_prompt=_EXTRACTION_SYSTEM_PROMPT,
context_turns=[],
knowledge_chunks=[],
user_message=turn.content,
language="en", # 使用英文 Prompt 保持 extraction 指令穩定度
)
return self._parse_extraction_response(response.text, turn)
except Exception as exc:
log.warning("Knowledge extraction Gemini call failed", error=str(exc))
return []
ChromaDB 語意去重機制 (_is_duplicate)
為了避免資料庫充斥重複或高度相似的敘述,提取出知識點後,系統會先對 ChromaDB 發起 top_k=1 的語意搜尋。
若最大相似度得分大於等於 0.85(DEDUP_SIMILARITY_THRESHOLD),則認定該知識點已存在並自動過濾;若比對過程中發生異常,則採 Fail-open 策略(允許寫入),優先保證知識不遺漏:
Python
DEDUP_SIMILARITY_THRESHOLD = 0.85
async def _is_duplicate(self, text: str) -> bool:
"""檢查知識點是否與 ChromaDB 既有內容重複 (相似度 >= 0.85)"""
try:
results = await self._rag_engine.search(query=text, top_k=1)
if not results:
return False
max_similarity = results[0].similarity
return max_similarity >= DEDUP_SIMILARITY_THRESHOLD
except Exception as exc:
log.warning("Deduplication check failed, allowing write", error=str(exc))
# Fail-open 策略:發生異常時仍允許寫入,避免阻斷學習
return False
Python
REBUILD_THRESHOLD = 50
async def extract_and_store(self, turn: Turn, session_id: str) -> None:
# 1. 提煉知識點...
# 2. 去重並批次新增新 Chunk...
if new_chunks:
await self._rag_engine.add_chunks(new_chunks)
added_count = len(new_chunks)
self._new_points_since_rebuild += added_count
# 3. 累積滿 50 筆,自動觸發向量索引重構
if self._new_points_since_rebuild >= REBUILD_THRESHOLD:
await self._trigger_rebuild()
到這裡,「AI 核心推理、記憶與 RAG 檢索」已大致實作完畢!我們建立了一套高可用、低成本且自我演化的完整架構:
1. gemini_gateway.py:Sliding Window Rate Limit (15 RPM) 與 429 配額 UTC Midnight 自動復原。
2. rag_engine.py:ChromaDB + sentence-transformers 本地端零成本語意檢索,asyncio.to_thread 解耦 CPU 密集運算。
3. conversation_memory.py:aiosqlite 持久化記憶,百輪對話 Transaction 原子化摘要壓縮。
4. learning_module.py:非同步背景萃取、0.85 門檻語意去重與 50 筆門檻自動索引重構。
下週開始,我們將進入 數據管線自動化與周邊服務整合——實作 Google Drive 知識自動同步 (drive_sync.py)、TWSE/美股每日分析 Telegram 播報 (daily_analysis.py) 與 Google Sheets 追蹤 (sheets_tracker.py)!
明日預告:【Day 08】知識管線自動化:Google Drive 檔案同步與 /learn 指令排程注入 (drive_sync.py)