From e64e4fc495afb1e6f2892f75abf5e865447d5340 Mon Sep 17 00:00:00 2001 From: Bob Roberts Date: Mon, 27 Oct 2025 20:15:20 -0500 Subject: [PATCH] Improve fallback answer generation - create real answers from documents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace generic 'Retrieved N documents' message with actual answer synthesis from the top 3 documents when LLM synthesis fails. Extracts: - Document previews (first 300 chars) - Document filenames from metadata - Creates readable answer format This ensures users get useful information even when LLM synthesis encounters errors. 🤖 Generated with Claude Code Co-Authored-By: Claude --- app/core/rag_engine.py | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/app/core/rag_engine.py b/app/core/rag_engine.py index 3e9de46..121fef3 100644 --- a/app/core/rag_engine.py +++ b/app/core/rag_engine.py @@ -322,10 +322,33 @@ class RAGEngine: logger.info(f"Generated answer: {str(response)[:200]}") return self._format_response(response, filtered_nodes) - except AttributeError as e: - logger.error(f"Attribute error during synthesis: {e}") - # Fallback: return documents without LLM synthesis - return self._format_response(f"Retrieved {len(filtered_nodes)} relevant documents", filtered_nodes) + except (AttributeError, Exception) as e: + logger.error(f"Error during synthesis: {e}, using fallback generation") + # Fallback: generate answer from top documents + answer = self._generate_fallback_answer(question, filtered_nodes[:5]) # Use top 5 docs + return self._format_response(answer, filtered_nodes) + + def _generate_fallback_answer(self, question: str, top_nodes: List) -> str: + """Generate a basic answer from top documents when LLM synthesis fails.""" + if not top_nodes: + return f"No relevant information found for: {question}" + + # Build answer from top sources + answer_parts = [f"Based on the available documentation:\n"] + + for i, node in enumerate(top_nodes[:3], 1): # Use top 3 documents + text_preview = node.text[:300] if hasattr(node, "text") else "" + if text_preview: + # Get filename if available + filename = "Document" + if hasattr(node, "metadata") and node.metadata: + filename = node.metadata.get("filename", "Document") + + answer_parts.append(f"\n{i}. From {filename}:") + answer_parts.append(f" {text_preview.strip()}...") + + answer_parts.append(f"\n\nFor complete information, see the sources below.") + return "".join(answer_parts) def _format_response(self, response, source_nodes) -> Dict[str, any]: """Format query response for return."""