@@ -223,7 +223,7 @@ def consolidate(self, response: WebSearchResponse) -> WebSearchResponse:
223223
224224 return response
225225
226- def _get_template_for_provider (self , provider : str ) -> str :
226+ def _get_template_for_provider (self , provider : str ) -> str | None :
227227 """
228228 Get the template for a specific provider.
229229
@@ -234,10 +234,7 @@ def _get_template_for_provider(self, provider: str) -> str:
234234 provider: Provider name (e.g., "serper", "jina")
235235
236236 Returns:
237- Template string for this provider
238-
239- Raises:
240- ValueError: If no template exists for this provider
237+ Template string for this provider, or None if no template exists
241238 """
242239 # 1. Custom template takes highest priority
243240 if self .custom_template :
@@ -250,14 +247,14 @@ def _get_template_for_provider(self, provider: str) -> str:
250247 _logger .debug (f"Using provider-specific template: { template_key } " )
251248 return PROVIDER_TEMPLATES [template_key ]
252249
253- # 3. No template exists for this provider - fail explicitly
250+ # 3. No template exists for this provider - return None for auto-fallback
254251 available = list (PROVIDER_TEMPLATES .keys ())
255- _logger .error (f"No template for provider '{ provider } '. Available: { available } " )
256- raise ValueError (
257- f"No template consolidation available for provider '{ provider } '. "
252+ _logger .warning (
253+ f"No template available for provider '{ provider } '. "
258254 f"Template consolidation only works with: { available } . "
259- f"Use consolidation='llm' or provide a custom_template for other providers ."
255+ f"Auto-falling back to simple result formatting ."
260256 )
257+ return None
261258
262259 def _build_provider_context (self , response : WebSearchResponse ) -> dict [str , Any ]:
263260 """
@@ -320,11 +317,17 @@ def _build_provider_context(self, response: WebSearchResponse) -> dict[str, Any]
320317 return context
321318
322319 def _consolidate_with_template (self , response : WebSearchResponse ) -> str :
323- """Render results using Jinja2 template"""
320+ """Render results using Jinja2 template or fallback to simple formatting """
324321 _logger .debug (f"Building template context for { response .provider } " )
325322
326323 # Get template (auto-detect provider-specific if not explicitly set)
327324 template_str = self ._get_template_for_provider (response .provider )
325+
326+ # Fallback: if no template available, use simple result formatting
327+ if template_str is None :
328+ _logger .info (f"Using fallback simple formatting for { response .provider } " )
329+ return self ._format_simple_results (response )
330+
328331 template = self .jinja_env .from_string (template_str )
329332
330333 # Build context with provider-specific fields
@@ -394,5 +397,31 @@ def _build_prompts(self, response: WebSearchResponse) -> tuple[str, str]:
394397
395398 return system_prompt , user_prompt
396399
400+ def _format_simple_results (self , response : WebSearchResponse ) -> str :
401+ """
402+ Format search results using a simple, provider-agnostic format.
403+
404+ This is used as a fallback when no provider-specific template is available.
405+ """
406+ lines = [f"### Search Results for \" { response .query } \" " , "" ]
407+
408+ for i , result in enumerate (response .search_results [: self .max_results ], 1 ):
409+ lines .append (f"**[{ i } ] { result .title } **" )
410+ if result .snippet :
411+ lines .append (f"{ result .snippet } " )
412+ if result .source :
413+ lines .append (f"*Source: { result .source } *" )
414+ lines .append (f"🔗 [{ result .url } ]({ result .url } )" )
415+ lines .append ("" )
416+
417+ if response .search_results :
418+ lines .append (
419+ f"---\n *{ len (response .search_results )} results via { response .provider } *"
420+ )
421+ else :
422+ lines .append ("*No results found.*" )
423+
424+ return "\n " .join (lines )
425+
397426
398427__all__ = ["AnswerConsolidator" , "CONSOLIDATION_TYPES" , "PROVIDER_TEMPLATES" ]
0 commit comments