mirror of
https://github.com/enricoros/big-AGI.git
synced 2026-05-10 21:50:14 -07:00
Merge branch 'joriskalz-Persona-From-Text'. Fixes #282
This commit is contained in:
@@ -3,19 +3,20 @@ import { shallow } from 'zustand/shallow';
|
||||
|
||||
import { Box, Button, Checkbox, Grid, IconButton, Input, Stack, Textarea, Typography } from '@mui/joy';
|
||||
import ClearIcon from '@mui/icons-material/Clear';
|
||||
import ScienceIcon from '@mui/icons-material/Science';
|
||||
import SearchIcon from '@mui/icons-material/Search';
|
||||
import TelegramIcon from '@mui/icons-material/Telegram';
|
||||
|
||||
import { DConversationId, useChatStore } from '~/common/state/store-chats';
|
||||
import { Link } from '~/common/components/Link';
|
||||
import { navigateToPersonas } from '~/common/app.routes';
|
||||
import { useUIPreferencesStore } from '~/common/state/store-ui';
|
||||
import { useUXLabsStore } from '~/common/state/store-ux-labs';
|
||||
|
||||
import { SystemPurposeId, SystemPurposes } from '../../../../data';
|
||||
import { usePurposeStore } from './store-purposes';
|
||||
|
||||
|
||||
// 'special' purpose IDs, for tile hiding purposes
|
||||
const PURPOSE_ID_PERSONA_CREATOR = '__persona-creator__';
|
||||
|
||||
// Constants for tile sizes / grid width - breakpoints need to be computed here to work around
|
||||
// the "flex box cannot shrink over wrapped content" issue
|
||||
//
|
||||
@@ -47,7 +48,6 @@ export function PersonaSelector(props: { conversationId: DConversationId, runExa
|
||||
|
||||
// external state
|
||||
const showFinder = useUIPreferencesStore(state => state.showPurposeFinder);
|
||||
const labsPersonaYTCreator = useUXLabsStore(state => state.labsPersonaYTCreator);
|
||||
const { systemPurposeId, setSystemPurposeId } = useChatStore(state => {
|
||||
const conversation = state.conversations.find(conversation => conversation.id === props.conversationId);
|
||||
return {
|
||||
@@ -113,6 +113,8 @@ export function PersonaSelector(props: { conversationId: DConversationId, runExa
|
||||
const unfilteredPurposeIDs = (filteredIDs && showFinder) ? filteredIDs : Object.keys(SystemPurposes);
|
||||
const purposeIDs = editMode ? unfilteredPurposeIDs : unfilteredPurposeIDs.filter(id => !hiddenPurposeIDs.includes(id));
|
||||
|
||||
const hidePersonaCreator = hiddenPurposeIDs.includes(PURPOSE_ID_PERSONA_CREATOR);
|
||||
|
||||
const selectedPurpose = purposeIDs.length ? (SystemPurposes[systemPurposeId] ?? null) : null;
|
||||
const selectedExample = selectedPurpose?.examples && getRandomElement(selectedPurpose.examples) || null;
|
||||
|
||||
@@ -156,10 +158,14 @@ export function PersonaSelector(props: { conversationId: DConversationId, runExa
|
||||
<Button
|
||||
variant={(!editMode && systemPurposeId === spId) ? 'solid' : 'soft'}
|
||||
color={(!editMode && systemPurposeId === spId) ? 'primary' : SystemPurposes[spId as SystemPurposeId]?.highlighted ? 'warning' : 'neutral'}
|
||||
onClick={() => !editMode && handlePurposeChanged(spId as SystemPurposeId)}
|
||||
onClick={() => editMode
|
||||
? toggleHiddenPurposeId(spId)
|
||||
: handlePurposeChanged(spId as SystemPurposeId)
|
||||
}
|
||||
sx={{
|
||||
flexDirection: 'column',
|
||||
fontWeight: 500,
|
||||
// paddingInline: 1,
|
||||
gap: bpTileGap,
|
||||
height: bpTileSize,
|
||||
width: bpTileSize,
|
||||
@@ -171,9 +177,10 @@ export function PersonaSelector(props: { conversationId: DConversationId, runExa
|
||||
>
|
||||
{editMode && (
|
||||
<Checkbox
|
||||
label={<Typography level='body-sm'>show</Typography>}
|
||||
checked={!hiddenPurposeIDs.includes(spId)} onChange={() => toggleHiddenPurposeId(spId)}
|
||||
sx={{ alignSelf: 'flex-start' }}
|
||||
color='neutral'
|
||||
checked={!hiddenPurposeIDs.includes(spId)}
|
||||
// label={<Typography level='body-xs'>show</Typography>}
|
||||
sx={{ position: 'absolute', left: 8, top: 8 }}
|
||||
/>
|
||||
)}
|
||||
<div style={{ fontSize: '2rem' }}>
|
||||
@@ -185,28 +192,43 @@ export function PersonaSelector(props: { conversationId: DConversationId, runExa
|
||||
</Button>
|
||||
</Grid>
|
||||
))}
|
||||
{/* Button to start the YouTube persona creator */}
|
||||
{labsPersonaYTCreator && <Grid>
|
||||
{/* Button to start the Persona Creator */}
|
||||
{(editMode || !hidePersonaCreator) && <Grid>
|
||||
<Button
|
||||
variant='soft' color='neutral'
|
||||
component={Link} noLinkStyle href='/personas'
|
||||
onClick={() => editMode
|
||||
? toggleHiddenPurposeId(PURPOSE_ID_PERSONA_CREATOR)
|
||||
: void navigateToPersonas()
|
||||
}
|
||||
sx={{
|
||||
'--Icon-fontSize': '2rem',
|
||||
flexDirection: 'column',
|
||||
fontWeight: 500,
|
||||
// gap: bpTileGap,
|
||||
// paddingInline: 1,
|
||||
gap: bpTileGap,
|
||||
height: bpTileSize,
|
||||
width: bpTileSize,
|
||||
border: `1px dashed`,
|
||||
boxShadow: 'md',
|
||||
backgroundColor: 'background.surface',
|
||||
// border: `1px dashed`,
|
||||
// borderColor: 'neutral.softActiveBg',
|
||||
boxShadow: 'xs',
|
||||
backgroundColor: 'neutral.softDisabledBg',
|
||||
}}
|
||||
>
|
||||
{editMode && (
|
||||
<Checkbox
|
||||
color='neutral'
|
||||
checked={!hidePersonaCreator}
|
||||
// label={<Typography level='body-xs'>show</Typography>}
|
||||
sx={{ position: 'absolute', left: 8, top: 8 }}
|
||||
/>
|
||||
)}
|
||||
<div>
|
||||
<ScienceIcon />
|
||||
<div style={{ fontSize: '2rem' }}>
|
||||
🎭
|
||||
</div>
|
||||
{/*<SettingsAccessibilityIcon style={{ opacity: 0.5 }} />*/}
|
||||
</div>
|
||||
<div>
|
||||
YouTube persona creator
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
Persona Creator
|
||||
</div>
|
||||
</Button>
|
||||
</Grid>}
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
|
||||
import { Box, Container, ListDivider, Sheet, Typography } from '@mui/joy';
|
||||
|
||||
import { YTPersonaCreator } from './YTPersonaCreator';
|
||||
import { PersonaCreator } from './PersonaCreator';
|
||||
import ScienceIcon from '@mui/icons-material/Science';
|
||||
|
||||
|
||||
@@ -18,19 +18,12 @@ export function AppPersonas() {
|
||||
<Container disableGutters maxWidth='md' sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
|
||||
|
||||
<Typography level='title-lg' sx={{ textAlign: 'center' }}>
|
||||
Advanced AI Personas
|
||||
AI Personas Creator
|
||||
</Typography>
|
||||
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 1 }}>
|
||||
<Typography>
|
||||
Experimental
|
||||
</Typography>
|
||||
<ScienceIcon color='primary' />
|
||||
</Box>
|
||||
|
||||
<ListDivider sx={{ my: 2 }} />
|
||||
|
||||
<YTPersonaCreator />
|
||||
<PersonaCreator />
|
||||
|
||||
</Container>
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { Alert, Box, Button, Card, CardContent, CircularProgress, Grid, IconButton, Input, LinearProgress, Tooltip, Typography } from '@mui/joy';
|
||||
import { Alert, Box, Button, Card, CardContent, CircularProgress, Grid, Input, LinearProgress, Tab, TabList, TabPanel, Tabs, Textarea, Typography } from '@mui/joy';
|
||||
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
|
||||
import WhatshotIcon from '@mui/icons-material/Whatshot';
|
||||
import SettingsAccessibilityIcon from '@mui/icons-material/SettingsAccessibility';
|
||||
import TextFieldsIcon from '@mui/icons-material/TextFields';
|
||||
import YouTubeIcon from '@mui/icons-material/YouTube';
|
||||
|
||||
import { GoodModal } from '~/common/components/GoodModal';
|
||||
import { GoodTooltip } from '~/common/components/GoodTooltip';
|
||||
import { apiQuery } from '~/common/util/trpc.client';
|
||||
import { copyToClipboard } from '~/common/util/clipboardUtils';
|
||||
import { useFormRadioLlmType } from '~/common/components/forms/useFormRadioLlmType';
|
||||
@@ -37,9 +39,9 @@ function useTranscriptFromVideo(videoID: string | null) {
|
||||
}
|
||||
|
||||
|
||||
const YouTubePersonaSteps: LLMChainStep[] = [
|
||||
const PersonaCreationSteps: LLMChainStep[] = [
|
||||
{
|
||||
name: 'Analyzing the transcript',
|
||||
name: 'Analyzing the transcript / text',
|
||||
setSystem: 'You are skilled in analyzing and embodying diverse characters. You meticulously study transcripts to capture key attributes, draft comprehensive character sheets, and refine them for authenticity. Feel free to make assumptions without hedging, be concise and be creative.',
|
||||
addUserInput: true,
|
||||
addUser: 'Conduct comprehensive research on the provided transcript. Identify key characteristics of the speaker, including age, professional field, distinct personality traits, style of communication, narrative context, and self-awareness. Additionally, consider any unique aspects such as their use of humor, their cultural background, core values, passions, fears, personal history, and social interactions. Your output for this stage is an in-depth written analysis that exhibits an understanding of both the superficial and more profound aspects of the speaker\'s persona.',
|
||||
@@ -62,14 +64,15 @@ const YouTubePersonaSteps: LLMChainStep[] = [
|
||||
];
|
||||
|
||||
|
||||
export function YTPersonaCreator() {
|
||||
export function PersonaCreator() {
|
||||
// state
|
||||
const [videoURL, setVideoURL] = React.useState('');
|
||||
const [videoID, setVideoID] = React.useState('');
|
||||
const [personaTranscript, setPersonaTranscript] = React.useState<string | null>(null);
|
||||
const [personaText, setPersonaText] = React.useState('');
|
||||
|
||||
// external state
|
||||
const [diagramLlm, llmComponent] = useFormRadioLlmType();
|
||||
const [personaLlm, llmComponent] = useFormRadioLlmType('Persona Creation Model');
|
||||
|
||||
// fetch transcript when the Video ID is ready, then store it
|
||||
const { transcript, thumbnailUrl, title, isFetching, isError, error: transcriptError } =
|
||||
@@ -78,7 +81,7 @@ export function YTPersonaCreator() {
|
||||
|
||||
// use the transformation sequence to create a persona
|
||||
const { isFinished, isTransforming, chainProgress, chainIntermediates, chainStepName, chainOutput, chainError, abortChain } =
|
||||
useLLMChain(YouTubePersonaSteps, diagramLlm?.id, personaTranscript ?? undefined);
|
||||
useLLMChain(PersonaCreationSteps, personaLlm?.id, personaTranscript ?? undefined);
|
||||
|
||||
const handleVideoIdChange = (e: React.ChangeEvent<HTMLInputElement>) => setVideoURL(e.target.value);
|
||||
|
||||
@@ -93,61 +96,87 @@ export function YTPersonaCreator() {
|
||||
}
|
||||
};
|
||||
|
||||
// New handler for persona text change
|
||||
const handlePersonaTextChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
setPersonaText(e.target.value);
|
||||
};
|
||||
|
||||
return <>
|
||||
|
||||
<Box sx={{ display: 'flex', flexDirection: 'row', alignItems: 'center', gap: 1 }}>
|
||||
<YouTubeIcon sx={{ color: '#f00' }} />
|
||||
<Typography level='title-lg'>
|
||||
YouTube -> AI persona
|
||||
</Typography>
|
||||
</Box>
|
||||
<Typography level='title-sm' mb={3}>
|
||||
Create the <em>System Prompt</em> of an AI Persona from YouTube or Text.
|
||||
</Typography>
|
||||
|
||||
<form onSubmit={handleFetchTranscript}>
|
||||
<Box sx={{ display: 'flex', flexDirection: 'row', gap: 2 }}>
|
||||
<Input
|
||||
required
|
||||
type='url'
|
||||
fullWidth
|
||||
<Tabs defaultValue={0} variant='outlined'>
|
||||
<TabList sx={{ minHeight: 48 }}>
|
||||
<Tab>From YouTube Video</Tab>
|
||||
<Tab>From Text</Tab>
|
||||
</TabList>
|
||||
|
||||
{/* YouTube URL inputs */}
|
||||
<TabPanel value={0} sx={{ p: 3 }}>
|
||||
|
||||
<Typography level='title-md' startDecorator={<YouTubeIcon sx={{ color: '#f00' }} />} sx={{ mb: 3 }}>
|
||||
YouTube -> Persona
|
||||
</Typography>
|
||||
|
||||
<form onSubmit={handleFetchTranscript}>
|
||||
<Input
|
||||
required
|
||||
type='url'
|
||||
fullWidth
|
||||
variant='outlined'
|
||||
placeholder='YouTube Video URL'
|
||||
value={videoURL}
|
||||
onChange={handleVideoIdChange}
|
||||
sx={{ mb: 1.5 }}
|
||||
/>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Button type='submit' variant='solid' disabled={isFetching || isTransforming || !videoURL} loading={isFetching} sx={{ minWidth: 140 }}>
|
||||
Create
|
||||
</Button>
|
||||
<GoodTooltip title='This example comes from the popular Fireship YouTube channel, which presents technical topics with irreverent humor.'>
|
||||
<Button variant='outlined' color='neutral' onClick={() => setVideoURL('https://www.youtube.com/watch?v=M_wZpSEvOkc')}>
|
||||
Example
|
||||
</Button>
|
||||
</GoodTooltip>
|
||||
</Box>
|
||||
</form>
|
||||
</TabPanel>
|
||||
|
||||
{/* Text area for users to paste copied text */}
|
||||
<TabPanel value={1} sx={{ p: 3 }}>
|
||||
|
||||
<Typography level='title-md' startDecorator={<TextFieldsIcon />} sx={{ mb: 3 }}>
|
||||
<b>Text</b> -> Persona
|
||||
</Typography>
|
||||
|
||||
<Textarea
|
||||
variant='outlined'
|
||||
placeholder='YouTube Video URL'
|
||||
value={videoURL} onChange={handleVideoIdChange}
|
||||
endDecorator={
|
||||
<IconButton
|
||||
variant='outlined' color='neutral'
|
||||
onClick={() => setVideoURL('https://www.youtube.com/watch?v=M_wZpSEvOkc')}
|
||||
>
|
||||
<WhatshotIcon />
|
||||
</IconButton>
|
||||
}
|
||||
minRows={4} maxRows={8}
|
||||
placeholder='Paste your text here...'
|
||||
value={personaText}
|
||||
onChange={handlePersonaTextChange}
|
||||
sx={{
|
||||
backgroundColor: 'background.level1',
|
||||
'&:focus-within': {
|
||||
backgroundColor: 'background.popup',
|
||||
},
|
||||
lineHeight: 1.75,
|
||||
mb: 1.5,
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
type='submit'
|
||||
variant='solid' disabled={isFetching || isTransforming} loading={isFetching}
|
||||
sx={{ minWidth: 120 }}>
|
||||
Create
|
||||
</Button>
|
||||
</Box>
|
||||
</form>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Button variant='solid' disabled={isFetching || isTransforming || !personaText} onClick={() => setPersonaTranscript(personaText)} sx={{ minWidth: 140 }}>
|
||||
Create
|
||||
</Button>
|
||||
{!!personaText?.length && <Typography level='body-sm'>{personaText.length.toLocaleString()}</Typography>}
|
||||
</Box>
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
|
||||
{/* LLM selector (chat vs fast) */}
|
||||
{!isTransforming && !isFinished && llmComponent}
|
||||
|
||||
{/* 1. Transcript*/}
|
||||
{personaTranscript && (
|
||||
<Card sx={{ mt: 2, boxShadow: 'md' }}>
|
||||
<CardContent>
|
||||
<Typography level='title-md' sx={{ mb: 1 }}>
|
||||
{title || 'Transcript'}
|
||||
</Typography>
|
||||
<Box>
|
||||
{!!thumbnailUrl && <picture><img src={thumbnailUrl} alt='YouTube Video Image' height={80} style={{ float: 'left', marginRight: 8 }} /></picture>}
|
||||
<Typography level='body-sm'>
|
||||
{personaTranscript.slice(0, 280)}...
|
||||
</Typography>
|
||||
</Box>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
{!isTransforming && !isFinished && <Box sx={{ mt: 3 }}>{llmComponent}</Box>}
|
||||
|
||||
{/* Errors */}
|
||||
{isError && (
|
||||
@@ -161,49 +190,64 @@ export function YTPersonaCreator() {
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
|
||||
{/* Persona! */}
|
||||
{chainOutput && <Box sx={{ mt: 2 }}>
|
||||
<Typography level='title-lg'>
|
||||
YouTuber Persona System Prompt
|
||||
</Typography>
|
||||
<Card sx={{ boxShadow: 'md' }}>
|
||||
<CardContent sx={{
|
||||
position: 'relative',
|
||||
'&:hover > button': { opacity: 1 },
|
||||
}}>
|
||||
{chainOutput && <>
|
||||
<Card sx={{ boxShadow: 'md', mt: 3 }}>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Typography level='title-lg' color='success' startDecorator={<SettingsAccessibilityIcon color='success' />}>
|
||||
Persona Prompt
|
||||
</Typography>
|
||||
<GoodTooltip title='Copy system prompt'>
|
||||
<Button color='success' onClick={() => copyToClipboard(chainOutput, 'Persona prompt')} endDecorator={<ContentCopyIcon />} sx={{ minWidth: 120 }}>
|
||||
Copy
|
||||
</Button>
|
||||
</GoodTooltip>
|
||||
</Box>
|
||||
<CardContent>
|
||||
<Alert variant='soft' color='success' sx={{ mb: 1 }}>
|
||||
You can now copy the following text and use it as Custom prompt!
|
||||
You may now copy the text below and use it as Custom prompt!
|
||||
</Alert>
|
||||
<Tooltip title='Copy system prompt' variant='solid'>
|
||||
<IconButton
|
||||
variant='outlined' color='neutral' onClick={() => copyToClipboard(chainOutput, 'Persona prompt')}
|
||||
sx={{
|
||||
position: 'absolute', right: 0, zIndex: 10,
|
||||
// opacity: 0, transition: 'opacity 0.3s',
|
||||
}}>
|
||||
<ContentCopyIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Typography level='body-sm'>
|
||||
<Typography level='title-sm' sx={{ lineHeight: 1.75 }}>
|
||||
{chainOutput}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Box>}
|
||||
</>}
|
||||
|
||||
{/* Input: Transcript*/}
|
||||
{personaTranscript && <>
|
||||
<Typography level='title-lg' sx={{ mt: 3, mb: 0.5 }}>
|
||||
Input Data
|
||||
</Typography>
|
||||
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Typography level='title-md' sx={{ mb: 1 }}>
|
||||
{title || 'Transcript / Text'}
|
||||
</Typography>
|
||||
<Box>
|
||||
{!!thumbnailUrl && <picture><img src={thumbnailUrl} alt='YouTube Video Thumbnail' height={80} style={{ float: 'left', marginRight: 8 }} /></picture>}
|
||||
<Typography level='body-sm'>
|
||||
{personaTranscript.slice(0, 280)}...
|
||||
</Typography>
|
||||
</Box>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</>}
|
||||
|
||||
{/* Intermediate outputs rendered as cards in a grid */}
|
||||
{chainIntermediates && chainIntermediates.length > 0 && <Box sx={{ mt: 2 }}>
|
||||
<Typography level='title-lg'>
|
||||
{chainIntermediates && chainIntermediates.length > 0 && <>
|
||||
<Typography level='title-lg' sx={{ mt: 3, mb: 0.5 }}>
|
||||
{isTransforming ? 'Working...' : 'Intermediate Work'}
|
||||
</Typography>
|
||||
|
||||
<Grid container spacing={2}>
|
||||
{chainIntermediates.map((intermediate, i) =>
|
||||
<Grid xs={12} sm={6} md={4} key={i}>
|
||||
<Card>
|
||||
<Card sx={{ height: '100%' }}>
|
||||
<CardContent>
|
||||
<Typography level='title-sm' sx={{ mb: 1 }}>
|
||||
{i + 1}. {YouTubePersonaSteps[i].name}
|
||||
{i + 1}. {PersonaCreationSteps[i].name}
|
||||
</Typography>
|
||||
<Typography level='body-sm'>
|
||||
{intermediate?.slice(0, 140)}...
|
||||
@@ -213,27 +257,35 @@ export function YTPersonaCreator() {
|
||||
</Grid>,
|
||||
)}
|
||||
</Grid>
|
||||
</Box>}
|
||||
</>}
|
||||
|
||||
|
||||
{/* Embodiment Progress */}
|
||||
{/* Dialog: Embodiment Progress */}
|
||||
{isTransforming && <GoodModal open>
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', my: 2 }}>
|
||||
<CircularProgress color='primary' value={Math.max(10, 100 * chainProgress)} />
|
||||
</Box>
|
||||
<Typography color='success' level='title-lg' sx={{ mt: 1 }}>
|
||||
Embodying Persona ...
|
||||
</Typography>
|
||||
<Typography color='success' level='title-sm' sx={{ mt: 1, fontWeight: 600 }}>
|
||||
{chainStepName}
|
||||
</Typography>
|
||||
<LinearProgress color='success' determinate value={Math.max(10, 100 * chainProgress)} sx={{ mt: 1, mb: 2 }} />
|
||||
<Box>
|
||||
<Typography color='success' level='title-lg'>
|
||||
Embodying Persona ...
|
||||
</Typography>
|
||||
<Typography level='title-sm' sx={{ mt: 1 }}>
|
||||
Using: {personaLlm?.label}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box>
|
||||
<Typography color='success' level='title-sm' sx={{ fontWeight: 600 }}>
|
||||
{chainStepName}
|
||||
</Typography>
|
||||
<LinearProgress color='success' determinate value={Math.max(10, 100 * chainProgress)} sx={{ mt: 1.5 }} />
|
||||
</Box>
|
||||
<Typography level='title-sm'>
|
||||
This may take 1-2 minutes. Do not close this window or the progress will be lost.
|
||||
If you experience any errors (e.g. LLM timeouts, or context overflows for larger videos)
|
||||
While larger models will produce higher quality prompts,
|
||||
if you experience any errors (e.g. LLM timeouts, or context overflows for larger videos)
|
||||
please try again with faster/smaller models.
|
||||
</Typography>
|
||||
<Button variant='soft' color='neutral' onClick={abortChain} sx={{ ml: 'auto', minWidth: 100, mt: 5 }}>
|
||||
<Button variant='soft' color='neutral' onClick={abortChain} sx={{ ml: 'auto', minWidth: 100, mt: 3 }}>
|
||||
Cancel
|
||||
</Button>
|
||||
</GoodModal>}
|
||||
@@ -5,7 +5,6 @@ import AddAPhotoIcon from '@mui/icons-material/AddAPhoto';
|
||||
import CallIcon from '@mui/icons-material/Call';
|
||||
import FormatPaintIcon from '@mui/icons-material/FormatPaint';
|
||||
import VerticalSplitIcon from '@mui/icons-material/VerticalSplit';
|
||||
import YouTubeIcon from '@mui/icons-material/YouTube';
|
||||
|
||||
import { FormLabelStart } from '~/common/components/forms/FormLabelStart';
|
||||
import { FormSwitchControl } from '~/common/components/forms/FormSwitchControl';
|
||||
@@ -19,17 +18,12 @@ export function UxLabsSettings() {
|
||||
// external state
|
||||
const isMobile = useIsMobile();
|
||||
const {
|
||||
labsCalling, labsCameraDesktop, /*labsEnhancedUI,*/ labsMagicDraw, labsPersonaYTCreator, labsSplitBranching,
|
||||
setLabsCalling, setLabsCameraDesktop, /*setLabsEnhancedUI,*/ setLabsMagicDraw, setLabsPersonaYTCreator, setLabsSplitBranching,
|
||||
labsCalling, labsCameraDesktop, /*labsEnhancedUI,*/ labsMagicDraw, labsSplitBranching,
|
||||
setLabsCalling, setLabsCameraDesktop, /*setLabsEnhancedUI,*/ setLabsMagicDraw, setLabsSplitBranching,
|
||||
} = useUXLabsStore();
|
||||
|
||||
return <>
|
||||
|
||||
<FormSwitchControl
|
||||
title={<><YouTubeIcon color={labsPersonaYTCreator ? 'primary' : undefined} sx={{ mr: 0.25 }} /> YouTube Personas</>} description={labsPersonaYTCreator ? 'Creator Enabled' : 'Disabled'}
|
||||
checked={labsPersonaYTCreator} onChange={setLabsPersonaYTCreator}
|
||||
/>
|
||||
|
||||
<FormSwitchControl
|
||||
title={<><FormatPaintIcon color={labsMagicDraw ? 'primary' : undefined} sx={{ mr: 0.25 }} />Assisted Draw</>} description={labsMagicDraw ? 'Enabled' : 'Disabled'}
|
||||
checked={labsMagicDraw} onChange={setLabsMagicDraw}
|
||||
@@ -58,7 +52,7 @@ export function UxLabsSettings() {
|
||||
<FormControl orientation='horizontal' sx={{ justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<FormLabelStart title='Graduated' />
|
||||
<Typography level='body-xs'>
|
||||
<Link href='https://github.com/enricoros/big-agi/issues/192' target='_blank'>Auto Diagrams</Link> · Relative chat size · Text Tools · LLM Overheat
|
||||
<Link href='https://github.com/enricoros/big-AGI/issues/282' target='_blank'>Persona Creator</Link> · <Link href='https://github.com/enricoros/big-agi/issues/192' target='_blank'>Auto Diagrams</Link> · Relative chat size · Text Tools · LLM Overheat
|
||||
</Typography>
|
||||
</FormControl>
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ export const ROUTE_INDEX = '/';
|
||||
export const ROUTE_APP_CHAT = '/';
|
||||
export const ROUTE_APP_LINK_CHAT = '/link/chat/:linkId';
|
||||
export const ROUTE_APP_NEWS = '/news';
|
||||
export const ROUTE_APP_PERSONAS = '/personas';
|
||||
const ROUTE_CALLBACK_OPENROUTER = '/link/callback_openrouter';
|
||||
|
||||
|
||||
@@ -55,6 +56,8 @@ export const navigateToChat = async (conversationId?: DConversationId) => {
|
||||
};
|
||||
export const navigateToNews = navigateFn(ROUTE_APP_NEWS);
|
||||
|
||||
export const navigateToPersonas = navigateFn(ROUTE_APP_PERSONAS);
|
||||
|
||||
export const navigateBack = Router.back;
|
||||
|
||||
export const reloadPage = () => isBrowser && window.location.reload();
|
||||
|
||||
@@ -24,9 +24,6 @@ interface UXLabsStore {
|
||||
labsMagicDraw: boolean;
|
||||
setLabsMagicDraw: (labsMagicDraw: boolean) => void;
|
||||
|
||||
labsPersonaYTCreator: boolean;
|
||||
setLabsPersonaYTCreator: (labsPersonaYTCreator: boolean) => void;
|
||||
|
||||
labsSplitBranching: boolean;
|
||||
setLabsSplitBranching: (labsSplitBranching: boolean) => void;
|
||||
|
||||
@@ -48,9 +45,6 @@ export const useUXLabsStore = create<UXLabsStore>()(
|
||||
labsMagicDraw: false,
|
||||
setLabsMagicDraw: (labsMagicDraw: boolean) => set({ labsMagicDraw }),
|
||||
|
||||
labsPersonaYTCreator: true, // NOTE: default to true, as it is a graduated experiment
|
||||
setLabsPersonaYTCreator: (labsPersonaYTCreator: boolean) => set({ labsPersonaYTCreator }),
|
||||
|
||||
labsSplitBranching: false,
|
||||
setLabsSplitBranching: (labsSplitBranching: boolean) => set({ labsSplitBranching }),
|
||||
|
||||
|
||||
Reference in New Issue
Block a user