From 12bc94796a05f1cae2508705e93dfcf955f9fea8 Mon Sep 17 00:00:00 2001 From: OG T Date: Sat, 4 Apr 2026 11:43:59 +0800 Subject: [PATCH] =?UTF-8?q?fix(knowledge):=20asyncpg=20=E4=B8=8D=E6=94=AF?= =?UTF-8?q?=E6=8F=B4=20:param::type=EF=BC=8C=E6=94=B9=E7=94=A8=20CAST(:par?= =?UTF-8?q?am=20AS=20vector)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit asyncpg 使用 $1 位置參數,:emb::vector 語法導致 PostgresSyntaxError。 save_embedding 和 semantic_search 均改用 CAST(:emb AS vector) 語法。 Co-Authored-By: Claude Sonnet 4.6 --- apps/api/src/repositories/knowledge_repository.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/apps/api/src/repositories/knowledge_repository.py b/apps/api/src/repositories/knowledge_repository.py index 31cf2653..0fbb0841 100644 --- a/apps/api/src/repositories/knowledge_repository.py +++ b/apps/api/src/repositories/knowledge_repository.py @@ -196,12 +196,14 @@ class KnowledgeDBRepository: 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 欄位 + """儲存向量 embedding (768 維) + + 注意: asyncpg 不支援 :param::type 語法,必須用 CAST(:param AS vector) + """ from sqlalchemy import text as sa_text result = await self.db.execute( sa_text( - "UPDATE knowledge_entries SET embedding = :emb::vector WHERE id = :id" + "UPDATE knowledge_entries SET embedding = CAST(:emb AS vector) WHERE id = :id" ), {"emb": str(embedding), "id": entry_id}, ) @@ -221,12 +223,12 @@ class KnowledgeDBRepository: """ from sqlalchemy import text as sa_text sql = sa_text(""" - SELECT id, 1 - (embedding <=> :emb::vector) AS score + SELECT id, 1 - (embedding <=> CAST(:emb AS vector)) AS score FROM knowledge_entries WHERE status != 'ARCHIVED' AND embedding IS NOT NULL - AND 1 - (embedding <=> :emb::vector) >= :threshold - ORDER BY embedding <=> :emb::vector + AND 1 - (embedding <=> CAST(:emb AS vector)) >= :threshold + ORDER BY embedding <=> CAST(:emb AS vector) LIMIT :limit """) rows = await self.db.execute(