@@ -15,7 +15,8 @@ public class CompareToolHandler : BaseToolHandler
1515 public CompareToolHandler (
1616 ILogger < CompareToolHandler > logger ,
1717 IOptions < NLWebOptions > options ,
18- IQueryProcessor queryProcessor , IResultGenerator resultGenerator )
18+ IQueryProcessor queryProcessor ,
19+ IResultGenerator resultGenerator )
1920 : base ( logger , options , queryProcessor , resultGenerator )
2021 {
2122 }
@@ -41,22 +42,25 @@ public override async Task<NLWebResponse> ExecuteAsync(NLWebRequest request, Can
4142
4243 Logger . LogDebug ( "Comparing '{Item1}' vs '{Item2}'" , comparisonItems . Item1 , comparisonItems . Item2 ) ;
4344
44- // Gather information about both items
45- var item1Results = await GatherItemInformation ( comparisonItems . Item1 , request , cancellationToken ) ;
46- var item2Results = await GatherItemInformation ( comparisonItems . Item2 , request , cancellationToken ) ;
45+ // Create comparison query
46+ var comparisonQuery = $ "{ comparisonItems . Item1 } vs { comparisonItems . Item2 } comparison differences";
47+
48+ // Generate comparison results
49+ var searchResults = await ResultGenerator . GenerateListAsync ( comparisonQuery , request . Site , cancellationToken ) ;
50+ var resultsList = searchResults . ToList ( ) ;
4751
4852 // Create structured comparison results
49- var comparisonResponse = CreateComparisonResponse (
50- request , comparisonItems . Item1 , comparisonItems . Item2 ,
51- item1Results , item2Results ) ;
53+ var comparisonResults = CreateComparisonResults ( resultsList , comparisonItems . Item1 , comparisonItems . Item2 ) ;
5254
5355 stopwatch . Stop ( ) ;
54- comparisonResponse . ProcessingTimeMs = stopwatch . ElapsedMilliseconds ;
55- comparisonResponse . Message = $ "Comparison completed between '{ comparisonItems . Item1 } ' and '{ comparisonItems . Item2 } '";
56+
57+ var response = CreateSuccessResponse ( request , comparisonResults , stopwatch . ElapsedMilliseconds ) ;
58+ response . ProcessedQuery = comparisonQuery ;
59+ response . Summary = $ "Comparison completed between '{ comparisonItems . Item1 } ' and '{ comparisonItems . Item2 } '";
5660
5761 Logger . LogDebug ( "Compare tool completed in {ElapsedMs}ms" , stopwatch . ElapsedMilliseconds ) ;
5862
59- return comparisonResponse ;
63+ return response ;
6064 }
6165 catch ( Exception ex )
6266 {
@@ -119,19 +123,15 @@ public override int GetPriority(NLWebRequest request)
119123 @"(.+?)\s+(?:vs|versus)\s+(.+)" ,
120124 // "difference between A and B"
121125 @"difference\s+between\s+(.+?)\s+and\s+(.+)" ,
122- // "A or B" (when asking which is better)
123- @"(.+?)\s+or\s+(.+?)(?:\s+which|$)" ,
124- // "A and B comparison"
125- @"(.+?)\s+and\s+(.+?)\s+comparison" ,
126126 } ;
127127
128128 foreach ( var pattern in patterns )
129129 {
130130 var match = Regex . Match ( queryLower , pattern , RegexOptions . IgnoreCase ) ;
131131 if ( match . Success && match . Groups . Count > 2 )
132132 {
133- var item1 = CleanComparisonItem ( match . Groups [ 1 ] . Value ) ;
134- var item2 = CleanComparisonItem ( match . Groups [ 2 ] . Value ) ;
133+ var item1 = match . Groups [ 1 ] . Value . Trim ( ) ;
134+ var item2 = match . Groups [ 2 ] . Value . Trim ( ) ;
135135
136136 if ( ! string . IsNullOrWhiteSpace ( item1 ) && ! string . IsNullOrWhiteSpace ( item2 ) )
137137 {
@@ -144,226 +144,48 @@ public override int GetPriority(NLWebRequest request)
144144 }
145145
146146 /// <summary>
147- /// Cleans up extracted comparison items by removing noise words.
148- /// </summary>
149- private string CleanComparisonItem ( string item )
150- {
151- if ( string . IsNullOrWhiteSpace ( item ) )
152- return string . Empty ;
153-
154- var cleaned = item . Trim ( ) ;
155-
156- // Remove common noise words from the beginning
157- var prefixNoise = new [ ] { "the" , "a" , "an" , "which" , "what" , "how" } ;
158- foreach ( var noise in prefixNoise )
159- {
160- if ( cleaned . StartsWith ( noise + " " , StringComparison . OrdinalIgnoreCase ) )
161- {
162- cleaned = cleaned . Substring ( noise . Length + 1 ) . Trim ( ) ;
163- }
164- }
165-
166- // Remove common noise words from the end
167- var suffixNoise = new [ ] { "better" , "worse" , "best" , "good" , "bad" } ;
168- foreach ( var noise in suffixNoise )
169- {
170- if ( cleaned . EndsWith ( " " + noise , StringComparison . OrdinalIgnoreCase ) )
171- {
172- cleaned = cleaned . Substring ( 0 , cleaned . Length - noise . Length - 1 ) . Trim ( ) ;
173- }
174- }
175-
176- return cleaned ;
177- }
178-
179- /// <summary>
180- /// Gathers information about a specific item for comparison.
181- /// </summary>
182- private async Task < IList < NLWebResult > > GatherItemInformation ( string item , NLWebRequest originalRequest , CancellationToken cancellationToken )
183- {
184- // Create a focused query for this specific item
185- var itemQuery = $ "{ item } features overview specifications";
186-
187- var itemRequest = new NLWebRequest
188- {
189- QueryId = originalRequest . QueryId ,
190- Query = itemQuery ,
191- Mode = originalRequest . Mode ,
192- Site = originalRequest . Site ,
193- MaxResults = 5 , // Limit results per item
194- TimeoutSeconds = originalRequest . TimeoutSeconds ,
195- DecontextualizedQuery = originalRequest . DecontextualizedQuery ,
196- Context = originalRequest . Context
197- } ;
198-
199- try
200- {
201- var response = await QueryProcessor . ProcessQueryAsync ( itemRequest , cancellationToken ) ;
202- return response . Success ? response . Results : new List < NLWebResult > ( ) ;
203- }
204- catch ( Exception ex )
205- {
206- Logger . LogWarning ( ex , "Failed to gather information for item '{Item}'" , item ) ;
207- return new List < NLWebResult > ( ) ;
208- }
209- }
210-
211- /// <summary>
212- /// Creates a structured comparison response from the gathered information.
147+ /// Creates structured comparison results.
213148 /// </summary>
214- private NLWebResponse CreateComparisonResponse (
215- NLWebRequest request ,
216- string item1 ,
217- string item2 ,
218- IList < NLWebResult > item1Results ,
219- IList < NLWebResult > item2Results )
149+ private IList < NLWebResult > CreateComparisonResults ( IList < NLWebResult > results , string item1 , string item2 )
220150 {
221151 var comparisonResults = new List < NLWebResult > ( ) ;
222152
223153 // Create summary comparison result
224- var summaryResult = CreateComparisonSummary ( item1 , item2 , item1Results , item2Results ) ;
225- comparisonResults . Add ( summaryResult ) ;
226-
227- // Add detailed results for item 1
228- var item1Section = CreateItemSection ( item1 , item1Results , "A" ) ;
229- comparisonResults . AddRange ( item1Section ) ;
230-
231- // Add detailed results for item 2
232- var item2Section = CreateItemSection ( item2 , item2Results , "B" ) ;
233- comparisonResults . AddRange ( item2Section ) ;
234-
235- // Add side-by-side comparison if we have good data
236- if ( item1Results . Any ( ) && item2Results . Any ( ) )
237- {
238- var sideBySideResult = CreateSideBySideComparison ( item1 , item2 , item1Results , item2Results ) ;
239- comparisonResults . Add ( sideBySideResult ) ;
154+ comparisonResults . Add ( CreateToolResult (
155+ $ "Comparison: { item1 } vs { item2 } ",
156+ $ "Side-by-side comparison analysis of { item1 } and { item2 } ",
157+ "" ,
158+ "Compare" ,
159+ 1.0
160+ ) ) ;
161+
162+ // Add relevant comparison results
163+ var relevantResults = results
164+ . Where ( r => IsRelevantForComparison ( r , item1 , item2 ) )
165+ . Take ( 8 )
166+ . ToList ( ) ;
167+
168+ foreach ( var result in relevantResults )
169+ {
170+ comparisonResults . Add ( CreateToolResult (
171+ $ "[Compare] { result . Name } ",
172+ result . Description ,
173+ result . Url ,
174+ result . Site ?? "Compare" ,
175+ result . Score
176+ ) ) ;
240177 }
241178
242- return CreateSuccessResponse ( request , comparisonResults , 0 ) ;
179+ return comparisonResults ;
243180 }
244181
245182 /// <summary>
246- /// Creates a high-level comparison summary .
183+ /// Checks if a result is relevant for comparison .
247184 /// </summary>
248- private NLWebResult CreateComparisonSummary ( string item1 , string item2 , IList < NLWebResult > item1Results , IList < NLWebResult > item2Results )
185+ private bool IsRelevantForComparison ( NLWebResult result , string item1 , string item2 )
249186 {
250- var summary = $ "Comparison between { item1 } and { item2 } :\n \n ";
251-
252- if ( item1Results . Any ( ) )
253- {
254- summary += $ "**{ item1 } **: { GetBestSummary ( item1Results ) } \n \n ";
255- }
256-
257- if ( item2Results . Any ( ) )
258- {
259- summary += $ "**{ item2 } **: { GetBestSummary ( item2Results ) } \n \n ";
260- }
261-
262- if ( ! item1Results . Any ( ) && ! item2Results . Any ( ) )
263- {
264- summary += "Limited information available for detailed comparison." ;
265- }
266-
267- return new NLWebResult
268- {
269- Title = $ "Comparison: { item1 } vs { item2 } ",
270- Summary = summary ,
271- Url = string . Empty ,
272- Site = "Compare" ,
273- Content = "Structured comparison analysis" ,
274- Timestamp = DateTime . UtcNow
275- } ;
276- }
277-
278- /// <summary>
279- /// Creates a section of results for a specific item.
280- /// </summary>
281- private IList < NLWebResult > CreateItemSection ( string item , IList < NLWebResult > results , string section )
282- {
283- var sectionResults = new List < NLWebResult > ( ) ;
284-
285- // Add section header
286- sectionResults . Add ( new NLWebResult
287- {
288- Title = $ "Option { section } : { item } ",
289- Summary = $ "Information about { item } ",
290- Url = string . Empty ,
291- Site = "Compare" ,
292- Content = string . Empty ,
293- Timestamp = DateTime . UtcNow
294- } ) ;
295-
296- // Add the best results for this item
297- var bestResults = results . Take ( 3 ) . ToList ( ) ;
298- foreach ( var result in bestResults )
299- {
300- if ( result is NLWebResult webResult )
301- {
302- var enhancedResult = new NLWebResult
303- {
304- Title = $ "{ item } : { webResult . Name } ",
305- Summary = webResult . Description ,
306- Url = webResult . Url ,
307- Site = webResult . Site ?? "Compare" ,
308- } ;
309- sectionResults . Add ( enhancedResult ) ;
310- }
311- }
312-
313- return sectionResults ;
314- }
315-
316- /// <summary>
317- /// Creates a side-by-side comparison result.
318- /// </summary>
319- private NLWebResult CreateSideBySideComparison ( string item1 , string item2 , IList < NLWebResult > item1Results , IList < NLWebResult > item2Results )
320- {
321- var comparison = $ "**Side-by-Side Comparison**\n \n ";
322- comparison += $ "| Aspect | { item1 } | { item2 } |\n ";
323- comparison += "|--------|---------|----------|\n " ;
324-
325- // Extract key aspects from both sets of results
326- var item1Summary = GetBestSummary ( item1Results ) ;
327- var item2Summary = GetBestSummary ( item2Results ) ;
328-
329- comparison += $ "| Overview | { TruncateForTable ( item1Summary ) } | { TruncateForTable ( item2Summary ) } |\n ";
330-
331- return new NLWebResult
332- {
333- Title = $ "Side-by-Side: { item1 } vs { item2 } ",
334- Summary = comparison ,
335- Url = string . Empty ,
336- Site = "Compare" ,
337- Content = "Detailed side-by-side comparison table" ,
338- Timestamp = DateTime . UtcNow
339- } ;
340- }
341-
342- /// <summary>
343- /// Gets the best summary from a collection of results.
344- /// </summary>
345- private string GetBestSummary ( IList < NLWebResult > results )
346- {
347- var bestResult = results
348- . Where ( r => ! string . IsNullOrWhiteSpace ( r . Description ) )
349- . OrderByDescending ( r => r . Description ? . Length ?? 0 )
350- . FirstOrDefault ( ) ;
351-
352- return bestResult ? . Description ?? "No detailed information available" ;
353- }
354-
355- /// <summary>
356- /// Truncates text for table display.
357- /// </summary>
358- private string TruncateForTable ( string text )
359- {
360- if ( string . IsNullOrWhiteSpace ( text ) )
361- return "N/A" ;
362-
363- const int maxLength = 100 ;
364- if ( text . Length <= maxLength )
365- return text ;
366-
367- return text . Substring ( 0 , maxLength - 3 ) + "..." ;
187+ var text = $ "{ result . Name } { result . Description } ". ToLowerInvariant ( ) ;
188+ return text . Contains ( item1 . ToLowerInvariant ( ) ) || text . Contains ( item2 . ToLowerInvariant ( ) ) ||
189+ text . Contains ( "compare" ) || text . Contains ( "difference" ) || text . Contains ( "versus" ) ;
368190 }
369191}
0 commit comments