fix(knowledge): 首席架構師 Review 修復 C1+C2+I1+I2 (71→~88/100)
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 7m16s
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 7m16s
C1: IKnowledgeRepository Protocol 補齊 save_embedding + semantic_search +
list_unembedded_entries,恢復 Interface 先行保護層
C2: embed_all_entries Service 層 raw SQL 移至 Repository.list_unembedded_entries()
Service 改透過 Protocol 呼叫,符合 leWOOOgo 積木化原則
I1: asyncio.create_task 加入 _pending_tasks set 持有引用,防 GC 回收與
Shutdown 時 Task 遺失;task done 後自動 discard
I2: OllamaEmbeddingService 從每次 new 改為 KnowledgeService.__init__ 注入,
單一實例重用
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -272,6 +272,25 @@ class IKnowledgeRepository(Protocol):
|
||||
"""view_count +1"""
|
||||
...
|
||||
|
||||
async def save_embedding(self, entry_id: str, embedding: list[float]) -> bool:
|
||||
"""儲存向量 embedding (768 維, pgvector)"""
|
||||
...
|
||||
|
||||
async def semantic_search(
|
||||
self,
|
||||
query_embedding: list[float],
|
||||
limit: int = 10,
|
||||
threshold: float = 0.5,
|
||||
) -> list[tuple["KnowledgeEntry", float]]:
|
||||
"""語意搜尋 — cosine similarity, 回傳 (entry, score) 降序"""
|
||||
...
|
||||
|
||||
async def list_unembedded_entries(
|
||||
self,
|
||||
) -> list[tuple[str, str, str]]:
|
||||
"""列出尚未產生 embedding 的條目 [(id, title, content)]"""
|
||||
...
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
class IPlaybookRepository(Protocol):
|
||||
|
||||
@@ -184,6 +184,17 @@ class KnowledgeDBRepository:
|
||||
)
|
||||
return result.rowcount > 0
|
||||
|
||||
async def list_unembedded_entries(self) -> list[tuple[str, str, str]]:
|
||||
"""列出尚未產生 embedding 的條目 [(id, title, content)]"""
|
||||
from sqlalchemy import text as sa_text
|
||||
result = await self.db.execute(
|
||||
sa_text(
|
||||
"SELECT id, title, content FROM knowledge_entries "
|
||||
"WHERE embedding IS NULL AND status != 'ARCHIVED'"
|
||||
)
|
||||
)
|
||||
return [(row.id, row.title, row.content) for row in result.fetchall()]
|
||||
|
||||
async def save_embedding(self, entry_id: str, embedding: list[float]) -> bool:
|
||||
"""儲存向量 embedding (768 維)"""
|
||||
# 直接用 raw SQL 寫入 pgvector 欄位
|
||||
|
||||
Reference in New Issue
Block a user