Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 63 additions & 45 deletions src/components/Chat/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -312,25 +312,26 @@ export const Chat = memo(
body: JSON.stringify({
projectName: courseName,
}),
});
})

if (!response.ok) {
throw new Error('Failed to fetch LLM providers');
throw new Error('Failed to fetch LLM providers')
}

const data = await response.json();
llmProviders = data;
const data = await response.json()
llmProviders = data

if (!llmProviders) {
throw new Error('No LLM providers returned from API');
throw new Error('No LLM providers returned from API')
}
} catch (error) {
console.error('Error fetching LLM providers:', error);
console.error('Error fetching LLM providers:', error)
errorToast({
title: 'Website Error - Please refresh the page',
message: 'Failed to fetch LLM providers. Please refresh the page and try again.',
});
return;
message:
'Failed to fetch LLM providers. Please refresh the page and try again.',
})
return
}
}

Expand Down Expand Up @@ -367,8 +368,8 @@ export const Chat = memo(
message.contexts = []
message.content = Array.isArray(message.content)
? message.content.filter(
(content) => content.type !== 'tool_image_url',
)
(content) => content.type !== 'tool_image_url',
)
: message.content

const updatedMessages = [...(selectedConversation.messages || [])]
Expand Down Expand Up @@ -571,12 +572,12 @@ export const Chat = memo(
.map((msg) => {
const contentText = Array.isArray(msg.content)
? msg.content
.filter(
(content) =>
content.type === 'text' && content.text,
)
.map((content) => content.text!)
.join(' ')
.filter(
(content) =>
content.type === 'text' && content.text,
)
.map((content) => content.text!)
.join(' ')
: typeof msg.content === 'string'
? msg.content
: ''
Expand All @@ -591,12 +592,12 @@ export const Chat = memo(
.map((msg) => {
const contentText = Array.isArray(msg.content)
? msg.content
.filter(
(content) =>
content.type === 'text' && content.text,
)
.map((content) => content.text!)
.join(' ')
.filter(
(content) =>
content.type === 'text' && content.text,
)
.map((content) => content.text!)
.join(' ')
: typeof msg.content === 'string'
? msg.content
: ''
Expand Down Expand Up @@ -628,13 +629,13 @@ export const Chat = memo(
? msg.content.trim()
: Array.isArray(msg.content)
? msg.content
.map((c) => c.text)
.join(' ')
.trim()
.map((c) => c.text)
.join(' ')
.trim()
: '',
})),
},
key: getOpenAIKey(courseMetadata, apiKey),
key: getOpenAIKey(llmProviders, courseMetadata, apiKey),
course_name: courseName,
stream: false,
courseMetadata: courseMetadata,
Expand Down Expand Up @@ -752,7 +753,7 @@ export const Chat = memo(
// Check if the response is NO_REWRITE_REQUIRED or if we couldn't extract a valid query
if (
rewrittenQuery.trim().toUpperCase() ===
'NO_REWRITE_REQUIRED' ||
'NO_REWRITE_REQUIRED' ||
!extractedQuery
) {
console.log(
Expand Down Expand Up @@ -812,7 +813,7 @@ export const Chat = memo(
imageUrls,
imgDesc,
updatedConversation,
getOpenAIKey(courseMetadata, apiKey),
getOpenAIKey(llmProviders, courseMetadata, apiKey),
)
homeDispatch({ field: 'isRouting', value: false })
if (uiucToolsToRun.length > 0) {
Expand All @@ -838,7 +839,7 @@ export const Chat = memo(

const finalChatBody: ChatBody = {
conversation: updatedConversation,
key: getOpenAIKey(courseMetadata, apiKey),
key: getOpenAIKey(llmProviders, courseMetadata, apiKey),
course_name: courseName,
stream: true,
courseMetadata: courseMetadata,
Expand Down Expand Up @@ -913,10 +914,18 @@ export const Chat = memo(
// Check if response is ok before proceeding
if (!response.ok) {
const errorData = await response.json()
console.log('Chat.txs --- errorData from /api/allNewRoutingChat', errorData)
console.log(
'Chat.txs --- errorData from /api/allNewRoutingChat',
errorData,
)
// Read our custom error object. But normal errors are captured too via errorData.error.
const customError = new Error(errorData.message || errorData.error || 'The LLM might be overloaded or misconfigured. Please check your API key, or use a different LLM.')
; (customError as any).title = errorData.title || 'LLM Didn\'t Respond'
const customError = new Error(
errorData.message ||
errorData.error ||
'The LLM might be overloaded or misconfigured. Please check your API key, or use a different LLM.',
)
;(customError as any).title =
errorData.title || "LLM Didn't Respond"
throw customError
}
} catch (error) {
Expand All @@ -926,7 +935,10 @@ export const Chat = memo(

errorToast({
title: (error as any).title || 'Error',
message: error instanceof Error ? error.message : 'An unexpected error occurred',
message:
error instanceof Error
? error.message
: 'An unexpected error occurred',
})
return
}
Expand All @@ -937,7 +949,10 @@ export const Chat = memo(

errorToast({
title: (error as any).title || 'Error',
message: error instanceof Error ? error.message : 'An unexpected error occurred',
message:
error instanceof Error
? error.message
: 'An unexpected error occurred',
})
return
}
Expand All @@ -951,12 +966,15 @@ export const Chat = memo(
const errorData = await response.json()
errorToast({
title: errorData.title || 'Error',
message: errorData.message || 'There was an unexpected error calling the LLM. Try using a different model.',
message:
errorData.message ||
'There was an unexpected error calling the LLM. Try using a different model.',
})
} catch (error) {
errorToast({
title: 'Error',
message: 'There was an unexpected error calling the LLM. Try using a different model.',
message:
'There was an unexpected error calling the LLM. Try using a different model.',
})
}
return
Expand Down Expand Up @@ -1574,13 +1592,13 @@ export const Chat = memo(

const statements =
courseMetadata?.example_questions &&
courseMetadata.example_questions.length > 0
courseMetadata.example_questions.length > 0
? courseMetadata.example_questions
: [
'Make a bullet point list of key takeaways from this project.',
'What are the best practices for [Activity or Process] in [Context or Field]?',
'Can you explain the concept of [Specific Concept] in simple terms?',
]
'Make a bullet point list of key takeaways from this project.',
'What are the best practices for [Activity or Process] in [Context or Field]?',
'Can you explain the concept of [Specific Concept] in simple terms?',
]

// Add this function to create dividers with statements
const renderIntroductoryStatements = () => {
Expand Down Expand Up @@ -1895,8 +1913,8 @@ export const Chat = memo(
transition={{ duration: 0.1 }}
>
{selectedConversation &&
selectedConversation.messages &&
selectedConversation.messages?.length === 0 ? (
selectedConversation.messages &&
selectedConversation.messages?.length === 0 ? (
<>
<div className="mt-16">
{renderIntroductoryStatements()}
Expand All @@ -1914,7 +1932,7 @@ export const Chat = memo(
handleSend(
editedMessage,
selectedConversation?.messages?.length -
index,
index,
null,
tools,
enabledDocumentGroups,
Expand Down
19 changes: 12 additions & 7 deletions src/utils/streamProcessing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
type BedrockProvider,
type GeminiProvider,
type SambaNovaProvider,
ProviderNames,
} from '~/utils/modelProviders/LLMProvider'
import fetchMQRContexts from '~/pages/api/getContextsMQR'
import fetchContexts from '~/pages/api/getContexts'
Expand All @@ -46,7 +47,6 @@ import { runGeminiChat } from '~/app/api/chat/gemini/route'
import { runBedrockChat } from '~/app/api/chat/bedrock/route'
import { runSambaNovaChat } from '~/app/api/chat/sambanova/route'


/**
* Enum representing the possible states of the state machine used in processing text chunks.
*/
Expand Down Expand Up @@ -700,12 +700,12 @@ export async function handleImageContent(
)

if (imgDescIndex !== -1) {
; (message.content as Content[])[imgDescIndex] = {
;(message.content as Content[])[imgDescIndex] = {
type: 'text',
text: `Image description: ${imgDesc}`,
}
} else {
; (message.content as Content[]).push({
;(message.content as Content[]).push({
type: 'text',
text: `Image description: ${imgDesc}`,
})
Expand All @@ -719,13 +719,17 @@ export async function handleImageContent(
}

export const getOpenAIKey = (
llmProviders: AllLLMProviders,
courseMetadata: CourseMetadata,
userApiKey: string,
) => {
const key =
courseMetadata?.openai_api_key && courseMetadata?.openai_api_key != ''
? courseMetadata.openai_api_key
llmProviders[ProviderNames.OpenAI]?.apiKey &&
llmProviders[ProviderNames.OpenAI]?.apiKey != ''
? llmProviders[ProviderNames.OpenAI]?.apiKey
: userApiKey
// console.log('OpenAI key found for getOpenAIKey:', key)
// console.log('llmProviders:', llmProviders)
return key
}

Expand Down Expand Up @@ -779,10 +783,11 @@ export const routeModelRequest = async (
NOTE: WebLLM is handled separately, because it MUST be called from the Client browser itself.
*/

console.debug('In routeModelRequest: ', chatBody, baseUrl)
// console.debug('In routeModelRequest: ', chatBody, baseUrl)
// console.debug('In routeModelRequest: ', baseUrl)

const selectedConversation = chatBody.conversation!
console.debug('Selected conversation:', selectedConversation)
// console.debug('Selected conversation:', selectedConversation)
if (!selectedConversation.model || !selectedConversation.model.id) {
console.debug('Invalid conversation:', selectedConversation)
throw new Error('Conversation model is undefined or missing "id" property.')
Expand Down