mirror of
https://github.com/enricoros/big-AGI.git
synced 2026-05-10 21:50:14 -07:00
Smaller moves
This commit is contained in:
@@ -10,7 +10,7 @@ import TelegramIcon from '@mui/icons-material/Telegram';
|
||||
|
||||
import { useComposerStore } from '../utilities/store';
|
||||
import { useSpeechRecognition } from '../utilities/speechRecognition';
|
||||
import { NoSSR } from './NoSSR';
|
||||
import { NoSSR } from './util/NoSSR';
|
||||
|
||||
|
||||
/// Text template helpers
|
||||
|
||||
@@ -22,7 +22,7 @@ import StopOutlinedIcon from '@mui/icons-material/StopOutlined';
|
||||
import { Alert, Avatar, Box, Button, IconButton, ListDivider, ListItem, ListItemDecorator, Menu, MenuItem, Stack, Textarea, Tooltip, Typography, useTheme } from '@mui/joy';
|
||||
import { SxProps, Theme } from '@mui/joy/styles/types';
|
||||
|
||||
import { Link } from './Link';
|
||||
import { Link } from './util/Link';
|
||||
|
||||
|
||||
// One message in the chat
|
||||
@@ -154,7 +154,7 @@ function RunnableCode({ codeBlock, theme }: { codeBlock: CodeMessageBlock, theme
|
||||
);
|
||||
}
|
||||
|
||||
function ChatMessageCodeBlock({ codeBlock, theme, sx }: { codeBlock: CodeMessageBlock, theme: Theme, sx?: SxProps }) {
|
||||
function CodeBlock({ codeBlock, theme, sx }: { codeBlock: CodeMessageBlock, theme: Theme, sx?: SxProps }) {
|
||||
const [showSandpack, setShowSandpack] = React.useState(false);
|
||||
|
||||
const handleCopyToClipboard = () =>
|
||||
@@ -183,15 +183,47 @@ function ChatMessageCodeBlock({ codeBlock, theme, sx }: { codeBlock: CodeMessage
|
||||
</Box>;
|
||||
}
|
||||
|
||||
function prettyModel(model: string): string {
|
||||
function prettyBaseModel(model: string): string {
|
||||
if (model.startsWith('gpt-4')) return 'gpt-4';
|
||||
if (model.startsWith('gpt-3.5-turbo')) return '3.5-turbo';
|
||||
return model;
|
||||
}
|
||||
|
||||
function explainErrorInMessage(message: UiMessage) {
|
||||
let errorMessage: JSX.Element | null = null;
|
||||
const isAssistantError = message.role === 'assistant' && (message.text.startsWith('Error: ') || message.text.startsWith('OpenAI API error: '));
|
||||
if (isAssistantError) {
|
||||
if (message.text.startsWith('OpenAI API error: 429 Too Many Requests')) {
|
||||
// TODO: retry at the api/chat level a few times instead of showing this error
|
||||
errorMessage = <>
|
||||
The model appears to be occupied at the moment. Kindly select <b>GPT-3.5 Turbo</b> via settings icon,
|
||||
or give it another go by selecting <b>Run again</b> from the message menu.
|
||||
</>;
|
||||
} else if (message.text.includes('"model_not_found"')) {
|
||||
// note that "model_not_found" is different than "The model `gpt-xyz` does not exist" message
|
||||
errorMessage = <>
|
||||
Your API key appears to be unauthorized for {message.model || 'this model'}. You can change to <b>GPT-3.5 Turbo</b> via the settings
|
||||
icon and simultaneously <Link noLinkStyle href='https://openai.com/waitlist/gpt-4-api' target='_blank'>request
|
||||
access</Link> to the desired model.
|
||||
</>;
|
||||
} else if (message.text.includes('"context_length_exceeded"')) {
|
||||
// TODO: propose to summarize or split the input?
|
||||
const pattern: RegExp = /maximum context length is (\d+) tokens.+resulted in (\d+) tokens/;
|
||||
const match = pattern.exec(message.text);
|
||||
const usedText = match ? ` (${match[2]} tokens, max ${match[1]})` : '';
|
||||
errorMessage = <>
|
||||
This thread <b>surpasses the maximum size</b> allowed for {message.model || 'this model'}{usedText}.
|
||||
Please consider removing some earlier messages from the conversation, start a new conversation,
|
||||
choose a model with larger context, or submit a shorter new message.
|
||||
</>;
|
||||
}
|
||||
}
|
||||
return { errorMessage, isAssistantError };
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ChatMessage component is a customizable chat message UI component that supports
|
||||
* The Message component is a customizable chat message UI component that supports
|
||||
* different roles (user, assistant, and system), text editing, syntax highlighting,
|
||||
* and code execution using Sandpack for TypeScript, JavaScript, and HTML code blocks.
|
||||
* The component also provides options for copying code to clipboard and expanding
|
||||
@@ -201,7 +233,7 @@ function prettyModel(model: string): string {
|
||||
* @param {Function} props.onDelete - The function to call when the delete button is clicked.
|
||||
* @param {Function} props.onEdit - The function to call when the edit button is clicked and the edited text is submitted.
|
||||
*/
|
||||
export function ChatMessage(props: { uiMessage: UiMessage, onDelete: () => void, onEdit: (text: string) => void, onRunAgain: () => void }) {
|
||||
export function Message(props: { uiMessage: UiMessage, onDelete: () => void, onEdit: (text: string) => void, onRunAgain: () => void }) {
|
||||
const theme = useTheme();
|
||||
const message = props.uiMessage;
|
||||
|
||||
@@ -253,34 +285,7 @@ export function ChatMessage(props: { uiMessage: UiMessage, onDelete: () => void,
|
||||
|
||||
|
||||
// soft error handling
|
||||
let errorMessage: JSX.Element | null = null;
|
||||
const isAssistantError = message.role === 'assistant' && (message.text.startsWith('Error: ') || message.text.startsWith('OpenAI API error: '));
|
||||
if (isAssistantError) {
|
||||
if (message.text.startsWith('OpenAI API error: 429 Too Many Requests')) {
|
||||
// TODO: retry at the api/chat level a few times instead of showing this error
|
||||
errorMessage = <>
|
||||
The model appears to be occupied at the moment. Kindly select <b>GPT-3.5 Turbo</b> via settings icon,
|
||||
or give it another go by selecting <b>Run again</b> from the message menu.
|
||||
</>;
|
||||
} else if (message.text.includes('"model_not_found"')) {
|
||||
// note that "model_not_found" is different than "The model `gpt-xyz` does not exist" message
|
||||
errorMessage = <>
|
||||
Your API key appears to be unauthorized for {message.model || 'this model'}. You can change to <b>GPT-3.5 Turbo</b> via the settings
|
||||
icon and simultaneously <Link noLinkStyle href='https://openai.com/waitlist/gpt-4-api' target='_blank'>request
|
||||
access</Link> to the desired model.
|
||||
</>;
|
||||
} else if (message.text.includes('"context_length_exceeded"')) {
|
||||
// TODO: propose to summarize or split the input?
|
||||
const pattern: RegExp = /maximum context length is (\d+) tokens.+resulted in (\d+) tokens/;
|
||||
const match = pattern.exec(message.text);
|
||||
const usedText = match ? ` (${match[2]} tokens, max ${match[1]})` : '';
|
||||
errorMessage = <>
|
||||
This thread <b>surpasses the maximum size</b> allowed for {message.model || 'this model'}{usedText}.
|
||||
Please consider removing some earlier messages from the conversation, start a new conversation,
|
||||
choose a model with larger context, or submit a shorter new message.
|
||||
</>;
|
||||
}
|
||||
}
|
||||
const { isAssistantError, errorMessage } = explainErrorInMessage(message);
|
||||
|
||||
|
||||
// theming
|
||||
@@ -342,10 +347,12 @@ export function ChatMessage(props: { uiMessage: UiMessage, onDelete: () => void,
|
||||
: <SportsMartialArtsOutlinedIcon sx={{ width: 40, height: 40 }} />
|
||||
)}
|
||||
|
||||
{message.role === 'system' && (<Typography level='body2' color='neutral'>system</Typography>)}
|
||||
{message.role === 'system' && (
|
||||
<Typography level='body2' color='neutral'>system</Typography>
|
||||
)}
|
||||
{message.role === 'assistant' && (
|
||||
<Tooltip title={message.model} variant='solid'>
|
||||
<Typography level='body2' color='neutral'>{prettyModel(message.model)}</Typography>
|
||||
<Typography level='body2' color='neutral'>{prettyBaseModel(message.model)}</Typography>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
@@ -388,7 +395,7 @@ export function ChatMessage(props: { uiMessage: UiMessage, onDelete: () => void,
|
||||
<Box sx={{ ...chatFontCss, flexGrow: 0, whiteSpace: 'break-spaces' }}>
|
||||
{parseAndHighlightCodeBlocks(collapsedText).map((part, index) =>
|
||||
part.type === 'code' ? (
|
||||
<ChatMessageCodeBlock key={index} codeBlock={part} theme={theme} sx={chatFontCss} />
|
||||
<CodeBlock key={index} codeBlock={part} theme={theme} sx={chatFontCss} />
|
||||
) : (
|
||||
<Typography key={index} level='body1' component='span'
|
||||
sx={{ ...chatFontCss, mx: 1.5, background: textBackground }}>
|
||||
@@ -4,8 +4,8 @@ import { shallow } from 'zustand/shallow';
|
||||
import { Box, Button, Input, Modal, ModalClose, ModalDialog, Option, Select, Typography } from '@mui/joy';
|
||||
|
||||
import { GptChatModelId, GptChatModels, useSettingsStore } from '../utilities/store';
|
||||
import { Link } from './Link';
|
||||
import { NoSSR } from './NoSSR';
|
||||
import { Link } from './util/Link';
|
||||
import { NoSSR } from './util/NoSSR';
|
||||
|
||||
|
||||
export const isValidOpenAIApiKey = (apiKey?: string) =>
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ if (!process.env.OPENAI_API_KEY)
|
||||
|
||||
// definition for OpenAI wire types
|
||||
|
||||
export interface ChatMessage {
|
||||
interface ChatMessage {
|
||||
role: 'assistant' | 'system' | 'user';
|
||||
content: string;
|
||||
}
|
||||
|
||||
+6
-6
@@ -8,10 +8,10 @@ import SmartToyOutlinedIcon from '@mui/icons-material/SmartToyOutlined';
|
||||
import SmartToyTwoToneIcon from '@mui/icons-material/SmartToyTwoTone';
|
||||
|
||||
import { ChatApiInput } from './api/chat';
|
||||
import { ChatMessage, UiMessage } from '../components/ChatMessage';
|
||||
import { Composer } from '../components/Composer';
|
||||
import { GptChatModels, SystemPurposeId, SystemPurposes, useSettingsStore } from '../utilities/store';
|
||||
import { NoSSR } from '../components/NoSSR';
|
||||
import { Message, UiMessage } from '../components/Message';
|
||||
import { NoSSR } from '../components/util/NoSSR';
|
||||
import { isValidOpenAIApiKey, Settings } from '../components/Settings';
|
||||
|
||||
|
||||
@@ -255,10 +255,10 @@ export default function Conversation() {
|
||||
<>
|
||||
<List sx={{ p: 0 }}>
|
||||
{messages.map(message =>
|
||||
<ChatMessage key={'msg-' + message.uid} uiMessage={message}
|
||||
onDelete={() => handleListDelete(message.uid)}
|
||||
onEdit={newText => handleListEdit(message.uid, newText)}
|
||||
onRunAgain={() => handleListRunAgain(message.uid)} />)}
|
||||
<Message key={'msg-' + message.uid} uiMessage={message}
|
||||
onDelete={() => handleListDelete(message.uid)}
|
||||
onEdit={newText => handleListEdit(message.uid, newText)}
|
||||
onRunAgain={() => handleListRunAgain(message.uid)} />)}
|
||||
<div ref={messagesEndRef}></div>
|
||||
</List>
|
||||
</>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"target": "ES6",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
|
||||
Reference in New Issue
Block a user