Skip to content

Commit

Permalink
feat(nx-dev): fixed error handling
Browse files Browse the repository at this point in the history
]
  • Loading branch information
mandarini committed Aug 28, 2023
1 parent cccdbcb commit cea5f33
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 58 deletions.
7 changes: 3 additions & 4 deletions nx-dev/data-access-ai/src/lib/data-access-ai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export async function queryAi(
);

if (!responseObj.ok) {
throw new Error(responseObj.statusText);
throw await responseObj.json();
}

const response: {
Expand All @@ -43,9 +43,8 @@ export async function queryAi(
chatFullHistory = response.chatHistory;

return response;
} catch (e) {
// TODO(katerina): Fix this to show the actual error
console.error('Error in fetch', e);
} catch (e: any) {
console.error('Error: ', e?.['message'] || e);
throw e;
}
}
Expand Down
2 changes: 1 addition & 1 deletion nx-dev/feature-ai/src/lib/error-message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
} from '@heroicons/react/24/outline';

export function ErrorMessage({ error }: { error: any }): JSX.Element {
if (error.data.no_results) {
if (error?.data?.no_results) {
return (
<div className="rounded-md bg-yellow-50 p-4">
<div className="flex">
Expand Down
78 changes: 46 additions & 32 deletions nx-dev/nx-dev/pages/api/query-ai-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@

import { NextRequest } from 'next/server';
import {
ApplicationError,
CustomError,
DEFAULT_MATCH_COUNT,
DEFAULT_MATCH_THRESHOLD,
MIN_CONTENT_LENGTH,
PROMPT,
PageSection,
UserError,
checkEnvVariables,
getListOfSources,
getMessageFromResponse,
Expand All @@ -32,17 +31,19 @@ export const config = {
};

export default async function handler(request: NextRequest) {
checkEnvVariables(openAiKey, supabaseUrl, supabaseServiceKey);
const { query, aiResponse, chatFullHistory } = await request.json();
try {
checkEnvVariables(openAiKey, supabaseUrl, supabaseServiceKey);
const { query, aiResponse, chatFullHistory } = await request.json();

const supabaseClient: SupabaseClient<any, 'public', any> = createClient(
supabaseUrl as string,
supabaseServiceKey as string
);
const supabaseClient: SupabaseClient<any, 'public', any> = createClient(
supabaseUrl as string,
supabaseServiceKey as string
);

try {
if (!query) {
throw new UserError('Missing query in request data');
throw new CustomError('user_error', 'Missing query in request data', {
missing_query: true,
});
}

// Moderate the content to comply with OpenAI T&C
Expand Down Expand Up @@ -76,9 +77,13 @@ export default async function handler(request: NextRequest) {
);

if (!embeddingResponseObj.ok) {
throw new ApplicationError('Failed to create embedding for question', {
data: embeddingResponseObj.status,
});
throw new CustomError(
'application_error',
'Failed to create embedding for question',
{
data: embeddingResponseObj.status,
}
);
}

const embeddingResponse = await embeddingResponseObj.json();
Expand All @@ -97,13 +102,19 @@ export default async function handler(request: NextRequest) {
);

if (matchError) {
throw new ApplicationError('Failed to match page sections', matchError);
throw new CustomError(
'application_error',
'Failed to match page sections',
matchError
);
}

// Note: this is experimental. I think it should work
// mainly because we're testing previous response + query.
if (!pageSections || pageSections.length === 0) {
throw new UserError('No results found.', { no_results: true });
throw new CustomError('user_error', 'No results found.', {
no_results: true,
});
}

const tokenizer = new GPT3Tokenizer({ type: 'gpt3' });
Expand Down Expand Up @@ -143,9 +154,13 @@ export default async function handler(request: NextRequest) {
);

if (!responseObj.ok) {
throw new ApplicationError('Failed to generate completion', {
data: responseObj.status,
});
throw new CustomError(
'application_error',
'Failed to generate completion',
{
data: responseObj.status,
}
);
}

const response = await responseObj.json();
Expand Down Expand Up @@ -175,19 +190,18 @@ export default async function handler(request: NextRequest) {
},
});
} catch (err: unknown) {
if (err instanceof UserError) {
console.error(err.message);
} else if (err instanceof ApplicationError) {
// Print out application errors with their additional data
console.error(`${err.message}: ${JSON.stringify(err.data)}`);
} else {
// Print out unexpected errors as is to help with debugging
console.error(err);
}

// TODO: include more response info in debug environments
// OR RETURN RESPONSE WITH DIFFERENT ERROR STATUS
console.error(err);
throw err;
console.error('Error: ', err);
return new Response(
JSON.stringify({
...JSON.parse(JSON.stringify(err)),
message: err?.['message'],
}),
{
status: 500,
headers: {
'content-type': 'application/json',
},
}
);
}
}
4 changes: 2 additions & 2 deletions nx-dev/util-ai/src/lib/moderation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { openAiAPICall } from './openai-call';
import { UserError } from './utils';
import { CustomError } from './utils';

export async function moderateContent(
sanitizedQuery: string,
Expand All @@ -15,7 +15,7 @@ export async function moderateContent(
const [results] = moderationResponse.results;

if (results.flagged) {
throw new UserError('Flagged content', {
throw new CustomError('user_error', 'Flagged content', {
flagged: true,
categories: results.categories,
});
Expand Down
46 changes: 27 additions & 19 deletions nx-dev/util-ai/src/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,48 @@
import {
ChatCompletionRequestMessageRoleEnum,
CreateChatCompletionResponse,
} from 'openai';
import { ChatCompletionRequestMessageRoleEnum } from 'openai';

export function checkEnvVariables(
openAiKey?: string,
supabaseUrl?: string,
supabaseServiceKey?: string
) {
if (!openAiKey) {
throw new ApplicationError('Missing environment variable NX_OPENAI_KEY');
throw new CustomError(
'application_error',
'Missing environment variable NX_OPENAI_KEY',
{
missing_key: true,
}
);
}

if (!supabaseUrl) {
throw new ApplicationError(
'Missing environment variable NX_NEXT_PUBLIC_SUPABASE_URL'
throw new CustomError(
'application_error',
'Missing environment variable NX_NEXT_PUBLIC_SUPABASE_URL',
{ missing_key: true }
);
}
if (!supabaseServiceKey) {
throw new ApplicationError(
'Missing environment variable NX_SUPABASE_SERVICE_ROLE_KEY'
throw new CustomError(
'application_error',
'Missing environment variable NX_SUPABASE_SERVICE_ROLE_KEY',
{ missing_key: true }
);
}
}

export class ApplicationError extends Error {
public type: string = 'application_error';
constructor(message: string, public data: Record<string, any> = {}) {
super(message);
}
}
export class CustomError extends Error {
public type: string;
public data: Record<string, any>;

export class UserError extends ApplicationError {
public override type: string = 'user_error';
constructor(message: string, data: Record<string, any> = {}) {
super(message, data);
constructor(
type: string = 'application_error',
message: string,
data: Record<string, any> = {}
) {
super(message);
this.type = type;
this.data = data;
}
}

Expand Down

0 comments on commit cea5f33

Please sign in to comment.