Skip to content

Commit

Permalink
[feature] Surface detailed error for deleted conversations (#535)
Browse files Browse the repository at this point in the history
Co-authored-by: Ian Seabock (Centific Technologies Inc) <[email protected]>
  • Loading branch information
iseabock and Ian Seabock (Centific Technologies Inc) committed Jan 29, 2024
1 parent 654953b commit 649129c
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 42 deletions.
14 changes: 12 additions & 2 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ def assets(path):
)
except Exception as e:
logging.exception("Exception in CosmosDB initialization", e)
cosmodb_error = str(e)
cosmos_conversation_client = None


Expand Down Expand Up @@ -640,12 +641,14 @@ def add_conversation():
## then write it to the conversation history in cosmos
messages = request.json["messages"]
if len(messages) > 0 and messages[-1]['role'] == "user":
cosmos_conversation_client.create_message(
createdMessageValue = cosmos_conversation_client.create_message(
uuid=str(uuid.uuid4()),
conversation_id=conversation_id,
user_id=user_id,
input_message=messages[-1]
)
if createdMessageValue == "Conversation not found":
raise Exception("Conversation not found for the given conversation ID: " + conversation_id + ".")
else:
raise Exception("No user message found")

Expand Down Expand Up @@ -875,7 +878,14 @@ def ensure_cosmos():
return jsonify({"error": "CosmosDB is not configured"}), 404

if not cosmos_conversation_client or not cosmos_conversation_client.ensure():
return jsonify({"error": "CosmosDB is not working"}), 500
if cosmodb_error == "Invalid credentials":
return jsonify({"error": cosmodb_error}), 401
elif cosmodb_error == "Invalid CosmosDB database name":
return jsonify({"error": f"{cosmodb_error} {AZURE_COSMOSDB_DATABASE} for account {AZURE_COSMOSDB_ACCOUNT}"}), 422
elif cosmodb_error == "Invalid CosmosDB container name":
return jsonify({"error": f"{cosmodb_error}: {AZURE_COSMOSDB_CONVERSATIONS_CONTAINER}"}), 422
else:
return jsonify({"error": "CosmosDB is not working"}), 500

return jsonify({"message": "CosmosDB is configured and working"}), 200

Expand Down
27 changes: 23 additions & 4 deletions backend/history/cosmosdbservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from datetime import datetime
from flask import Flask, request
from azure.identity import DefaultAzureCredential
from azure.cosmos import CosmosClient, PartitionKey
from azure.cosmos import CosmosClient, exceptions

class CosmosConversationClient():

Expand All @@ -12,10 +12,27 @@ def __init__(self, cosmosdb_endpoint: str, credential: any, database_name: str,
self.credential = credential
self.database_name = database_name
self.container_name = container_name
self.cosmosdb_client = CosmosClient(self.cosmosdb_endpoint, credential=credential)
self.database_client = self.cosmosdb_client.get_database_client(database_name)
self.container_client = self.database_client.get_container_client(container_name)
self.enable_message_feedback = enable_message_feedback
try:
self.cosmosdb_client = CosmosClient(self.cosmosdb_endpoint, credential=credential)
except exceptions.CosmosHttpResponseError as e:
if e.status_code == 401:
raise ValueError("Invalid credentials") from e
else:
print("An error occurred:", e)

try:
self.database_client = self.cosmosdb_client.get_database_client(database_name)
self.database_client.read()
except exceptions.CosmosResourceNotFoundError:
raise ValueError("Invalid CosmosDB database name")

try:
self.container_client = self.database_client.get_container_client(container_name)
self.container_client.read()
except exceptions.CosmosResourceNotFoundError:
raise ValueError("Invalid CosmosDB container name")


def ensure(self):
try:
Expand Down Expand Up @@ -131,6 +148,8 @@ def create_message(self, uuid, conversation_id, user_id, input_message: dict):
if resp:
## update the parent conversations's updatedAt field with the current message's createdAt datetime value
conversation = self.get_conversation(user_id, conversation_id)
if not conversation:
return "Conversation not found"
conversation['updatedAt'] = message['createdAt']
self.upsert_conversation(conversation)
return resp
Expand Down
2 changes: 1 addition & 1 deletion frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/x-icon" href="/favicon.ico?v=2" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Azure AI</title>
<title>Contoso</title>
</head>
<body>
<div id="root"></div>
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,10 @@ export const historyEnsure = async (): Promise<CosmosDBHealth> => {
}else{
if(res.status === 500){
formattedResponse = CosmosDBStatus.NotWorking
}else if(res.status === 401){
formattedResponse = CosmosDBStatus.InvalidCredentials
}else if(res.status === 422){
formattedResponse = respJson.error
}else{
formattedResponse = CosmosDBStatus.NotConfigured
}
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/api/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ export type UserInfo = {
export enum CosmosDBStatus {
NotConfigured = "CosmosDB is not configured",
NotWorking = "CosmosDB is not working",
InvalidCredentials = "CosmosDB has invalid credentials",
InvalidDatabase = "Invalid CosmosDB database name",
InvalidContainer = "Invalid CosmosDB container name",
Working = "CosmosDB is configured and working",
}

Expand Down
21 changes: 18 additions & 3 deletions frontend/src/pages/chat/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,12 @@ const Chat = () => {
const [ASSISTANT, TOOL, ERROR] = ["assistant", "tool", "error"]

useEffect(() => {
if (appStateContext?.state.isCosmosDBAvailable?.status === CosmosDBStatus.NotWorking && appStateContext.state.chatHistoryLoadingState === ChatHistoryLoadingState.Fail && hideErrorDialog) {
if (appStateContext?.state.isCosmosDBAvailable?.status === CosmosDBStatus.NotWorking
|| appStateContext?.state.isCosmosDBAvailable?.status === CosmosDBStatus.InvalidCredentials
|| appStateContext?.state.isCosmosDBAvailable?.status.includes(CosmosDBStatus.InvalidDatabase)
|| appStateContext?.state.isCosmosDBAvailable?.status.includes(CosmosDBStatus.InvalidContainer)
&& appStateContext.state.chatHistoryLoadingState === ChatHistoryLoadingState.Fail
&& hideErrorDialog) {
let subtitle = `${appStateContext.state.isCosmosDBAvailable.status}. Please contact the site administrator.`
setErrorMsg({
title: "Chat history is not enabled",
Expand Down Expand Up @@ -281,10 +286,12 @@ const Chat = () => {
try {
const response = conversationId ? await historyGenerate(request, abortController.signal, conversationId) : await historyGenerate(request, abortController.signal);
if (!response?.ok) {
const responseJson = await response.json();
var errorResponseMessage = responseJson.error === undefined ? "Please try again. If the problem persists, please contact the site administrator." : responseJson.error;
let errorChatMsg: ChatMessage = {
id: uuid(),
role: ERROR,
content: "There was an error generating a response. Chat history can't be saved at this time. If the problem persists, please contact the site administrator.",
content: `There was an error generating a response. Chat history can't be saved at this time. ${errorResponseMessage}`,
date: new Date().toISOString()
}
let resultConversation;
Expand Down Expand Up @@ -376,7 +383,7 @@ const Chat = () => {

} catch (e) {
if (!abortController.signal.aborted) {
let errorMessage = "An error occurred. Please try again. If the problem persists, please contact the site administrator.";
let errorMessage = `An error occurred. ${errorResponseMessage}`;
if (result.error?.message) {
errorMessage = result.error.message;
}
Expand All @@ -403,6 +410,14 @@ const Chat = () => {
} else {
if (!result.history_metadata) {
console.error("Error retrieving data.", result);
console.log("errorMessage", errorMessage)
let errorChatMsg: ChatMessage = {
id: uuid(),
role: ERROR,
content: errorMessage,
date: new Date().toISOString()
}
setMessages([...messages, userMessage, errorChatMsg])
setIsLoading(false);
setShowLoadingMessage(false);
abortFuncs.current = abortFuncs.current.filter(a => a !== abortController);
Expand Down
60 changes: 30 additions & 30 deletions static/assets/index-c8bc2c87.js → static/assets/index-18a991e4.js

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<link rel="icon" type="image/x-icon" href="/favicon.ico?v=2" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Contoso</title>
<script type="module" crossorigin src="/assets/index-c8bc2c87.js"></script>
<script type="module" crossorigin src="/assets/index-18a991e4.js"></script>
<link rel="stylesheet" href="/assets/index-5e49c158.css">
</head>
<body>
Expand Down

0 comments on commit 649129c

Please sign in to comment.