| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- import { parseJsonResponse } from '@/lib/generation/json-repair';
- import { PROMPT_IDS, buildPrompt } from '@/lib/generation/prompts';
- import type { AICallFn } from '@/lib/generation/pipeline-types';
- import { createLogger } from '@/lib/logger';
- const log = createLogger('SearchQueryBuilder');
- const TAVILY_SOFT_MAX_QUERY_LENGTH = 350;
- export const SEARCH_QUERY_REWRITE_EXCERPT_LENGTH = 7000;
- interface SearchQueryRewriteResponse {
- query: string;
- }
- export interface SearchQueryBuildResult {
- query: string;
- rewriteAttempted: boolean;
- rawRequirementLength: number;
- finalQueryLength: number;
- hasPdfContext: boolean;
- }
- function normalizeSearchRequirement(requirement: string): string {
- return requirement.replace(/\s+/g, ' ').trim();
- }
- function normalizePdfExcerpt(pdfText?: string): string {
- if (!pdfText) {
- return '';
- }
- return pdfText.replace(/\s+/g, ' ').trim().slice(0, SEARCH_QUERY_REWRITE_EXCERPT_LENGTH);
- }
- function shouldRewriteSearchQuery(
- normalizedRequirement: string,
- normalizedPdfExcerpt: string,
- ): boolean {
- return normalizedRequirement.length > 400 || Boolean(normalizedPdfExcerpt);
- }
- export async function buildSearchQuery(
- requirement: string,
- pdfText: string | undefined,
- aiCall?: AICallFn,
- ): Promise<SearchQueryBuildResult> {
- const normalizedRequirement = normalizeSearchRequirement(requirement);
- const pdfExcerpt = normalizePdfExcerpt(pdfText);
- const hasPdfContext = Boolean(pdfExcerpt);
- const rewriteAttempted = shouldRewriteSearchQuery(normalizedRequirement, pdfExcerpt);
- const fallback = {
- query: normalizedRequirement,
- rewriteAttempted,
- rawRequirementLength: normalizedRequirement.length,
- finalQueryLength: normalizedRequirement.length,
- hasPdfContext,
- } satisfies SearchQueryBuildResult;
- if (!normalizedRequirement || !rewriteAttempted) {
- return fallback;
- }
- if (!aiCall) {
- log.warn('Query rewrite AI call unavailable, falling back to raw requirement');
- return fallback;
- }
- const prompts = buildPrompt(PROMPT_IDS.WEB_SEARCH_QUERY_REWRITE, {
- requirement: normalizedRequirement,
- pdfExcerpt: pdfExcerpt || 'None',
- });
- if (!prompts) {
- log.warn('Query rewrite prompt not found, falling back to raw requirement');
- return fallback;
- }
- try {
- const response = await aiCall(prompts.system, prompts.user);
- const parsed = parseJsonResponse<SearchQueryRewriteResponse>(response);
- const rewrittenQuery = normalizeSearchRequirement(parsed?.query || '').slice(
- 0,
- TAVILY_SOFT_MAX_QUERY_LENGTH,
- );
- if (!rewrittenQuery) {
- log.warn('Query rewrite returned empty output, falling back to raw requirement');
- return fallback;
- }
- return {
- ...fallback,
- query: rewrittenQuery,
- finalQueryLength: rewrittenQuery.length,
- };
- } catch (error) {
- log.warn('Query rewrite failed, falling back to raw requirement:', error);
- return fallback;
- }
- }
|