(params: SearchParams)
| 395 | } |
| 396 | |
| 397 | export async function handleTagOnlySearch(params: SearchParams): Promise<SearchResult[]> { |
| 398 | const { knowledgeBaseIds, topK, structuredFilters } = params |
| 399 | |
| 400 | if (!structuredFilters || structuredFilters.length === 0) { |
| 401 | throw new Error('Tag filters are required for tag-only search') |
| 402 | } |
| 403 | |
| 404 | const strategy = getQueryStrategy(knowledgeBaseIds.length, topK) |
| 405 | const tagFilterConditions = getStructuredTagFilters(structuredFilters, embedding) |
| 406 | |
| 407 | if (strategy.useParallel) { |
| 408 | // Parallel approach for many KBs |
| 409 | const parallelLimit = Math.ceil(topK / knowledgeBaseIds.length) + 5 |
| 410 | |
| 411 | const queryPromises = knowledgeBaseIds.map(async (kbId) => { |
| 412 | return await db |
| 413 | .select(getSearchResultFields(sql<number>`0`.as('distance'))) |
| 414 | .from(embedding) |
| 415 | .innerJoin(document, eq(embedding.documentId, document.id)) |
| 416 | .where( |
| 417 | and( |
| 418 | eq(embedding.knowledgeBaseId, kbId), |
| 419 | eq(embedding.enabled, true), |
| 420 | eq(document.enabled, true), |
| 421 | eq(document.processingStatus, 'completed'), |
| 422 | eq(document.userExcluded, false), |
| 423 | isNull(document.archivedAt), |
| 424 | isNull(document.deletedAt), |
| 425 | ...tagFilterConditions |
| 426 | ) |
| 427 | ) |
| 428 | .limit(parallelLimit) |
| 429 | }) |
| 430 | |
| 431 | const parallelResults = await Promise.all(queryPromises) |
| 432 | return parallelResults.flat().slice(0, topK) |
| 433 | } |
| 434 | // Single query for fewer KBs |
| 435 | return await db |
| 436 | .select(getSearchResultFields(sql<number>`0`.as('distance'))) |
| 437 | .from(embedding) |
| 438 | .innerJoin(document, eq(embedding.documentId, document.id)) |
| 439 | .where( |
| 440 | and( |
| 441 | inArray(embedding.knowledgeBaseId, knowledgeBaseIds), |
| 442 | eq(embedding.enabled, true), |
| 443 | eq(document.enabled, true), |
| 444 | eq(document.processingStatus, 'completed'), |
| 445 | eq(document.userExcluded, false), |
| 446 | isNull(document.archivedAt), |
| 447 | isNull(document.deletedAt), |
| 448 | ...tagFilterConditions |
| 449 | ) |
| 450 | ) |
| 451 | .limit(topK) |
| 452 | } |
| 453 | |
| 454 | export async function handleVectorOnlySearch(params: SearchParams): Promise<SearchResult[]> { |
no test coverage detected