(params: SearchParams)
| 452 | } |
| 453 | |
| 454 | export async function handleVectorOnlySearch(params: SearchParams): Promise<SearchResult[]> { |
| 455 | const { knowledgeBaseIds, topK, queryVector, distanceThreshold } = params |
| 456 | |
| 457 | if (!queryVector || !distanceThreshold) { |
| 458 | throw new Error('Query vector and distance threshold are required for vector-only search') |
| 459 | } |
| 460 | |
| 461 | const strategy = getQueryStrategy(knowledgeBaseIds.length, topK) |
| 462 | |
| 463 | const distanceExpr = sql<number>`${embedding.embedding} <=> ${queryVector}::vector`.as('distance') |
| 464 | |
| 465 | if (strategy.useParallel) { |
| 466 | // Parallel approach for many KBs |
| 467 | const parallelLimit = Math.ceil(topK / knowledgeBaseIds.length) + 5 |
| 468 | |
| 469 | const queryPromises = knowledgeBaseIds.map(async (kbId) => { |
| 470 | return await db |
| 471 | .select(getSearchResultFields(distanceExpr)) |
| 472 | .from(embedding) |
| 473 | .innerJoin(document, eq(embedding.documentId, document.id)) |
| 474 | .where( |
| 475 | and( |
| 476 | eq(embedding.knowledgeBaseId, kbId), |
| 477 | eq(embedding.enabled, true), |
| 478 | eq(document.enabled, true), |
| 479 | eq(document.processingStatus, 'completed'), |
| 480 | eq(document.userExcluded, false), |
| 481 | isNull(document.archivedAt), |
| 482 | isNull(document.deletedAt), |
| 483 | sql`${embedding.embedding} <=> ${queryVector}::vector < ${distanceThreshold}` |
| 484 | ) |
| 485 | ) |
| 486 | .orderBy(sql`${embedding.embedding} <=> ${queryVector}::vector`) |
| 487 | .limit(parallelLimit) |
| 488 | }) |
| 489 | |
| 490 | const parallelResults = await Promise.all(queryPromises) |
| 491 | const allResults = parallelResults.flat() |
| 492 | return allResults.sort((a, b) => a.distance - b.distance).slice(0, topK) |
| 493 | } |
| 494 | // Single query for fewer KBs |
| 495 | return await db |
| 496 | .select(getSearchResultFields(distanceExpr)) |
| 497 | .from(embedding) |
| 498 | .innerJoin(document, eq(embedding.documentId, document.id)) |
| 499 | .where( |
| 500 | and( |
| 501 | inArray(embedding.knowledgeBaseId, knowledgeBaseIds), |
| 502 | eq(embedding.enabled, true), |
| 503 | eq(document.enabled, true), |
| 504 | eq(document.processingStatus, 'completed'), |
| 505 | eq(document.userExcluded, false), |
| 506 | isNull(document.archivedAt), |
| 507 | isNull(document.deletedAt), |
| 508 | sql`${embedding.embedding} <=> ${queryVector}::vector < ${distanceThreshold}` |
| 509 | ) |
| 510 | ) |
| 511 | .orderBy(sql`${embedding.embedding} <=> ${queryVector}::vector`) |
no test coverage detected