Spaces:
Sleeping
Sleeping
Srini P commited on
Commit ·
3d20163
1
Parent(s): 3dd864d
Fix: Graceful error handling - never show blank responses on errors
Browse files
app/backend/main.py
CHANGED
|
@@ -172,8 +172,18 @@ async def chat(request: ChatRequest):
|
|
| 172 |
except HTTPException:
|
| 173 |
raise
|
| 174 |
except Exception as e:
|
| 175 |
-
logger.error(f"Error processing chat request: {str(e)}")
|
| 176 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 177 |
|
| 178 |
|
| 179 |
# ====================
|
|
|
|
| 172 |
except HTTPException:
|
| 173 |
raise
|
| 174 |
except Exception as e:
|
| 175 |
+
logger.error(f"Error processing chat request: {str(e)}", exc_info=True)
|
| 176 |
+
# Return a proper ChatResponse with error info instead of a 500,
|
| 177 |
+
# so the frontend always has something to display.
|
| 178 |
+
return ChatResponse(
|
| 179 |
+
answer="I'm sorry, I encountered an unexpected error while processing your question. Please try again in a moment.",
|
| 180 |
+
sources=[],
|
| 181 |
+
route="error",
|
| 182 |
+
user_role=request.user_role,
|
| 183 |
+
accessible_collections=[],
|
| 184 |
+
guardrail_flags=["server_error"],
|
| 185 |
+
guardrail_warnings=[f"Internal error: {str(e)}"],
|
| 186 |
+
)
|
| 187 |
|
| 188 |
|
| 189 |
# ====================
|
app/backend/pipeline/rag_pipeline.py
CHANGED
|
@@ -58,6 +58,27 @@ class RAGPipeline:
|
|
| 58 |
Returns:
|
| 59 |
RAGResponse with answer, sources, and metadata
|
| 60 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
metadata = QueryMetadata(
|
| 62 |
user_role=user_role,
|
| 63 |
user_department=self._get_department(user_role),
|
|
@@ -187,9 +208,9 @@ class RAGPipeline:
|
|
| 187 |
# Generate answer
|
| 188 |
answer = self._generate_answer(query_text, context, user_role)
|
| 189 |
|
| 190 |
-
if not answer:
|
| 191 |
return RAGResponse(
|
| 192 |
-
answer="I
|
| 193 |
sources=[],
|
| 194 |
route=route_name,
|
| 195 |
user_role=user_role,
|
|
|
|
| 58 |
Returns:
|
| 59 |
RAGResponse with answer, sources, and metadata
|
| 60 |
"""
|
| 61 |
+
try:
|
| 62 |
+
return self._process_query(user_role, query_text, user_id)
|
| 63 |
+
except Exception as e:
|
| 64 |
+
logger.error(f"Unexpected error in RAG pipeline: {str(e)}", exc_info=True)
|
| 65 |
+
return RAGResponse(
|
| 66 |
+
answer="I'm sorry, I encountered an unexpected error while processing your question. Please try again in a moment.",
|
| 67 |
+
sources=[],
|
| 68 |
+
route="error",
|
| 69 |
+
user_role=user_role,
|
| 70 |
+
accessible_collections=[],
|
| 71 |
+
guardrail_flags=["pipeline_error"],
|
| 72 |
+
guardrail_warnings=[f"Internal error: {str(e)}"],
|
| 73 |
+
)
|
| 74 |
+
|
| 75 |
+
def _process_query(
|
| 76 |
+
self,
|
| 77 |
+
user_role: str,
|
| 78 |
+
query_text: str,
|
| 79 |
+
user_id: Optional[str] = None,
|
| 80 |
+
) -> RAGResponse:
|
| 81 |
+
"""Internal query processing. Separated so answer_query can wrap with try/except."""
|
| 82 |
metadata = QueryMetadata(
|
| 83 |
user_role=user_role,
|
| 84 |
user_department=self._get_department(user_role),
|
|
|
|
| 208 |
# Generate answer
|
| 209 |
answer = self._generate_answer(query_text, context, user_role)
|
| 210 |
|
| 211 |
+
if not answer or not answer.strip():
|
| 212 |
return RAGResponse(
|
| 213 |
+
answer="I wasn't able to generate a response for your question. Please try rephrasing or ask a different question.",
|
| 214 |
sources=[],
|
| 215 |
route=route_name,
|
| 216 |
user_role=user_role,
|
app/frontend-nextjs/components/ChatInterface.tsx
CHANGED
|
@@ -61,21 +61,35 @@ export default function ChatInterface({ user, onLogout, onAdminPanel }: ChatInte
|
|
| 61 |
user_id: user.username,
|
| 62 |
});
|
| 63 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
const assistantMessage: ChatMessageType = {
|
| 65 |
id: (Date.now() + 1).toString(),
|
| 66 |
type: 'assistant',
|
| 67 |
-
content:
|
| 68 |
timestamp: new Date(),
|
| 69 |
-
response,
|
| 70 |
};
|
| 71 |
|
| 72 |
setMessages((prev) => [...prev, assistantMessage]);
|
| 73 |
-
} catch (error) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
const errorMessage: ChatMessageType = {
|
| 75 |
id: (Date.now() + 1).toString(),
|
| 76 |
type: 'assistant',
|
| 77 |
-
content:
|
| 78 |
-
'Sorry, I encountered an error processing your query. Please ensure the backend is running on http://localhost:8000',
|
| 79 |
timestamp: new Date(),
|
| 80 |
};
|
| 81 |
setMessages((prev) => [...prev, errorMessage]);
|
|
|
|
| 61 |
user_id: user.username,
|
| 62 |
});
|
| 63 |
|
| 64 |
+
// Guard against empty/blank responses from the backend
|
| 65 |
+
const answerText = response.answer?.trim()
|
| 66 |
+
? response.answer
|
| 67 |
+
: "I wasn't able to generate a response for your question. Please try rephrasing or ask a different question.";
|
| 68 |
+
|
| 69 |
const assistantMessage: ChatMessageType = {
|
| 70 |
id: (Date.now() + 1).toString(),
|
| 71 |
type: 'assistant',
|
| 72 |
+
content: answerText,
|
| 73 |
timestamp: new Date(),
|
| 74 |
+
response: { ...response, answer: answerText },
|
| 75 |
};
|
| 76 |
|
| 77 |
setMessages((prev) => [...prev, assistantMessage]);
|
| 78 |
+
} catch (error: unknown) {
|
| 79 |
+
// Extract a helpful message from the error if possible
|
| 80 |
+
let errorText = 'Sorry, I encountered an error processing your query. Please try again in a moment.';
|
| 81 |
+
if (error && typeof error === 'object' && 'response' in error) {
|
| 82 |
+
const axiosError = error as { response?: { data?: { error?: string; detail?: string } } };
|
| 83 |
+
const serverMsg = axiosError.response?.data?.detail || axiosError.response?.data?.error;
|
| 84 |
+
if (serverMsg) {
|
| 85 |
+
errorText = `Sorry, something went wrong: ${serverMsg}`;
|
| 86 |
+
}
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
const errorMessage: ChatMessageType = {
|
| 90 |
id: (Date.now() + 1).toString(),
|
| 91 |
type: 'assistant',
|
| 92 |
+
content: errorText,
|
|
|
|
| 93 |
timestamp: new Date(),
|
| 94 |
};
|
| 95 |
setMessages((prev) => [...prev, errorMessage]);
|