Add knowledge retrieval configuration to Assistant model and related components

- Introduce new fields for knowledge retrieval configuration in AssistantConfig and Assistant models, including mode, top_n, and score_threshold.
- Implement KnowledgeRetrievalConfig schema with validation for top_n.
- Update backend services and routes to handle knowledge retrieval settings.
- Enhance frontend components to support knowledge retrieval configuration, including a new dialog for advanced settings.
- Add tests for knowledge retrieval configuration validation and description generation.
This commit is contained in:
Xin Wang
2026-07-12 18:57:56 +08:00
parent 7ee3e22152
commit 7c9a18c806
13 changed files with 465 additions and 47 deletions

View File

@@ -203,7 +203,13 @@ async def recover_interrupted_documents() -> None:
await session.commit()
async def search(session: AsyncSession, kb_id: str, query: str, top_k: int | None = None) -> list[dict]:
async def search(
session: AsyncSession,
kb_id: str,
query: str,
top_k: int | None = None,
score_threshold: float = 0.0,
) -> list[dict]:
kb = await session.get(KnowledgeBase, kb_id)
if not kb:
return []
@@ -217,13 +223,20 @@ async def search(session: AsyncSession, kb_id: str, query: str, top_k: int | Non
return []
query_embedding = (await _embed(session, kb, [query]))[0]
distance = KnowledgeChunk.embedding.cosine_distance(query_embedding)
rows = (await session.execute(
statement = (
select(KnowledgeChunk, KnowledgeDocument.name, distance.label("distance"))
.join(KnowledgeDocument, KnowledgeDocument.id == KnowledgeChunk.document_id)
.where(KnowledgeChunk.knowledge_base_id == kb_id, KnowledgeDocument.status == "ready")
.where(
KnowledgeChunk.knowledge_base_id == kb_id,
KnowledgeDocument.status == "ready",
distance <= 1.0 - score_threshold,
)
.order_by(distance)
.limit(top_k or settings.KNOWLEDGE_TOP_K)
)).all()
)
effective_top_k = settings.KNOWLEDGE_TOP_K if top_k is None else top_k
if effective_top_k != -1:
statement = statement.limit(effective_top_k)
rows = (await session.execute(statement)).all()
return [
{"content": chunk.content, "document": name, "score": round(max(0.0, 1.0 - float(dist)), 4)}
for chunk, name, dist in rows