Skip to content

Commit 8058ae5

Browse files
committed
handle errors better
1 parent 3a7035d commit 8058ae5

File tree

4 files changed

+66
-26
lines changed

4 files changed

+66
-26
lines changed

src/{{ project_name_snake }}/qa_workflows.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,12 @@ class QueryConversationHistoryEvent(HumanResponseEvent):
172172
pass
173173

174174

175+
class ErrorEvent(Event):
176+
"""Event emitted when an error occurs"""
177+
178+
error: str
179+
180+
175181
class ChatWorkflowState(BaseModel):
176182
index_name: str | None = None
177183
conversation_history: list[ConversationMessage] = Field(default_factory=list)
@@ -219,7 +225,7 @@ class ChatWorkflow(Workflow):
219225
@step
220226
async def initialize_chat(
221227
self, ev: ChatEvent, ctx: Context[ChatWorkflowState]
222-
) -> InputRequiredEvent | StopEvent:
228+
) -> InputRequiredEvent | StopEvent | None:
223229
"""Initialize the chat session and request first input"""
224230
try:
225231
logger.info(f"Initializing chat {ev.index_name}")
@@ -236,17 +242,14 @@ async def initialize_chat(
236242
if ev.conversation_history:
237243
async with ctx.store.edit_state() as state:
238244
state.conversation_history.extend(ev.conversation_history)
239-
# Request first user input
240-
return InputRequiredEvent()
241245

242246
except Exception as e:
243247
logger.error(f"Error initializing chat: {str(e)}", exc_info=True)
244-
return StopEvent(
245-
result={
246-
"success": False,
247-
"error": f"Failed to initialize chat: {str(e)}",
248-
}
248+
ctx.write_event_to_stream(
249+
ErrorEvent(error=f"Failed to initialize chat: {str(e)}")
249250
)
251+
return InputRequiredEvent()
252+
250253

251254
@step
252255
async def get_conversation_history(
@@ -260,7 +263,7 @@ async def get_conversation_history(
260263
@step
261264
async def process_user_response(
262265
self, ev: HumanResponseEvent, ctx: Context[ChatWorkflowState]
263-
) -> InputRequiredEvent | HumanResponseEvent | StopEvent | None:
266+
) -> InputRequiredEvent | HumanResponseEvent | None:
264267
"""Process user input and generate response"""
265268
try:
266269
logger.info(f"Processing user response {ev.response}")
@@ -326,13 +329,11 @@ async def process_user_response(
326329
assistant_response,
327330
]
328331
)
329-
return InputRequiredEvent()
330332

331333
except Exception as e:
332334
logger.error(f"Error processing query: {str(e)}", exc_info=True)
333-
return StopEvent(
334-
result={"success": False, "error": f"Error processing query: {str(e)}"}
335-
)
335+
ctx.write_event_to_stream(ErrorEvent(error=str(e)))
336+
return InputRequiredEvent()
336337

337338

338339
upload = DocumentUploadWorkflow(timeout=None)

test-proj/src/test_proj/qa_workflows.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,12 @@ class QueryConversationHistoryEvent(HumanResponseEvent):
172172
pass
173173

174174

175+
class ErrorEvent(Event):
176+
"""Event emitted when an error occurs"""
177+
178+
error: str
179+
180+
175181
class ChatWorkflowState(BaseModel):
176182
index_name: str | None = None
177183
conversation_history: list[ConversationMessage] = Field(default_factory=list)
@@ -219,7 +225,7 @@ class ChatWorkflow(Workflow):
219225
@step
220226
async def initialize_chat(
221227
self, ev: ChatEvent, ctx: Context[ChatWorkflowState]
222-
) -> InputRequiredEvent | StopEvent:
228+
) -> InputRequiredEvent | StopEvent | None:
223229
"""Initialize the chat session and request first input"""
224230
try:
225231
logger.info(f"Initializing chat {ev.index_name}")
@@ -236,17 +242,14 @@ async def initialize_chat(
236242
if ev.conversation_history:
237243
async with ctx.store.edit_state() as state:
238244
state.conversation_history.extend(ev.conversation_history)
239-
# Request first user input
240-
return InputRequiredEvent()
241245

242246
except Exception as e:
243247
logger.error(f"Error initializing chat: {str(e)}", exc_info=True)
244-
return StopEvent(
245-
result={
246-
"success": False,
247-
"error": f"Failed to initialize chat: {str(e)}",
248-
}
248+
ctx.write_event_to_stream(
249+
ErrorEvent(error=f"Failed to initialize chat: {str(e)}")
249250
)
251+
return InputRequiredEvent()
252+
250253

251254
@step
252255
async def get_conversation_history(
@@ -260,7 +263,7 @@ async def get_conversation_history(
260263
@step
261264
async def process_user_response(
262265
self, ev: HumanResponseEvent, ctx: Context[ChatWorkflowState]
263-
) -> InputRequiredEvent | HumanResponseEvent | StopEvent | None:
266+
) -> InputRequiredEvent | HumanResponseEvent | None:
264267
"""Process user input and generate response"""
265268
try:
266269
logger.info(f"Processing user response {ev.response}")
@@ -326,13 +329,11 @@ async def process_user_response(
326329
assistant_response,
327330
]
328331
)
329-
return InputRequiredEvent()
330332

331333
except Exception as e:
332334
logger.error(f"Error processing query: {str(e)}", exc_info=True)
333-
return StopEvent(
334-
result={"success": False, "error": f"Error processing query: {str(e)}"}
335-
)
335+
ctx.write_event_to_stream(ErrorEvent(error=str(e)))
336+
return InputRequiredEvent()
336337

337338

338339
upload = DocumentUploadWorkflow(timeout=None)

test-proj/ui/src/libs/useChatbot.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ export function useChatbot({
166166
interface AppendChatMessageData {
167167
message: ChatMessage;
168168
}
169+
interface ErrorEventData {
170+
error: string;
171+
}
169172
interface ChatMessage {
170173
role: "user" | "assistant";
171174
text: string;
@@ -239,6 +242,22 @@ function toMessages(events: WorkflowEvent[]): Message[] {
239242
timestamp: new Date(content.message.timestamp),
240243
isPartial: false,
241244
});
245+
} else if (type.endsWith(".ErrorEvent")) {
246+
if (
247+
lastMessage &&
248+
lastMessage.isPartial &&
249+
lastMessage.role === "assistant"
250+
) {
251+
messages.pop();
252+
}
253+
const content = ev.data as unknown as ErrorEventData;
254+
messages.push({
255+
role: "assistant",
256+
content: content.error,
257+
timestamp: new Date(),
258+
isPartial: false,
259+
error: true,
260+
});
242261
}
243262
}
244263
return messages;

ui/src/libs/useChatbot.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ export function useChatbot({
166166
interface AppendChatMessageData {
167167
message: ChatMessage;
168168
}
169+
interface ErrorEventData {
170+
error: string;
171+
}
169172
interface ChatMessage {
170173
role: "user" | "assistant";
171174
text: string;
@@ -239,6 +242,22 @@ function toMessages(events: WorkflowEvent[]): Message[] {
239242
timestamp: new Date(content.message.timestamp),
240243
isPartial: false,
241244
});
245+
} else if (type.endsWith(".ErrorEvent")) {
246+
if (
247+
lastMessage &&
248+
lastMessage.isPartial &&
249+
lastMessage.role === "assistant"
250+
) {
251+
messages.pop();
252+
}
253+
const content = ev.data as unknown as ErrorEventData;
254+
messages.push({
255+
role: "assistant",
256+
content: content.error,
257+
timestamp: new Date(),
258+
isPartial: false,
259+
error: true,
260+
});
242261
}
243262
}
244263
return messages;

0 commit comments

Comments
 (0)