Skip to content

Commit

Permalink
add text and switch language option
Browse files Browse the repository at this point in the history
  • Loading branch information
JulienDupont76 committed May 21, 2024
1 parent ac201aa commit e99a97a
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 39 deletions.
25 changes: 25 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"dependencies": {
"@mantine/core": "^7.9.1",
"@mlc-ai/web-llm": "^0.2.35",
"@tabler/icons-react": "^3.4.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
Expand Down
30 changes: 28 additions & 2 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
.textbox-container {
width: 100%;
display: flex;
align-items: center;
}

.textbox-container .textarea {
Expand Down Expand Up @@ -54,17 +55,34 @@
}

.progress-text {
z-index: 2;
text-align: center;
padding: 0 1rem;
}

.progress-bars-container {
padding: 8px;
height: 140px;
width: 80%;
}

.vertical-switch-button {
display: none;
}

.switch-button:not([disabled]):hover {
border-color: transparent;
}

.switch-button {
&:disabled,
&[data-disabled] {
background-color: transparent;
}
}

@media (max-width: 768px) {
.textbox-container {
flex-direction: column;
gap: 2rem;
}

.textbox-container .textarea {
Expand All @@ -75,4 +93,12 @@
flex-direction: column;
height: 15rem;
}

.horizontal-switch-button {
display: none;
}

.vertical-switch-button {
display: block;
}
}
107 changes: 80 additions & 27 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
} from '@mlc-ai/web-llm';
import { appConfig } from './app-config';
import Progress from './components/Progress';
import { Button, Textarea } from '@mantine/core';
import { ActionIcon, Button, Textarea, Tooltip } from '@mantine/core';
import { IconSwitchHorizontal, IconSwitchVertical } from '@tabler/icons-react';

appConfig.useIndexedDBCache = true;

Expand All @@ -21,6 +22,10 @@ if (appConfig.useIndexedDBCache) {

function App() {
const selectedModel = 'CroissantLLMChat-v0.1-q0f16';
const promptEnglishToFrench =
"Pouvez-vous traduire ce texte en francais sans ajouter d'informations ?";
const promptFrenchToEnglish =
'Can you translate this text in english for me without adding informations';
const [engine, setEngine] = useState<EngineInterface | null>(null);
const [progress, setProgress] = useState('Not loaded');
const [progressPercentage, setProgressPercentage] = useState(0);
Expand All @@ -30,33 +35,27 @@ function App() {
const [input, setInput] = useState<string>('');
const [output, setOutput] = useState<string>('');
const [modelInCache, setModelInCache] = useState<boolean | null>(null);

// useEffect(() => {
// if (!engine) {
// loadEngine();
// }
// }, []);
const [switched, setSwitched] = useState<boolean>(false);

useEffect(() => {
checkModelInCache();
if (!engine) {
loadEngine();
}
}, []);

const initProgressCallback = (report: InitProgressReport) => {
//console.log(report);
if (modelInCache) {
if (
modelInCache === true ||
report.text.startsWith('Loading model from cache')
) {
setOutput('Chargement du modèle dans la RAM...');
} else {
setOutput(
'Téléchargement des points du modèle dans la cache de votre navigateur, cela peut prendre quelques minutes.'
);
}
// if (report.text.startsWith('Loading model from cache')) {
// setOutput('Loading from cache...');
// } else {
// setOutput(
// 'Téléchargement des points du modèle dans la cache de votre navigateur, cela peut prendre quelques minutes.'
// );
// }

if (report.progress !== 0) {
setProgressPercentage(report.progress);
Expand All @@ -71,7 +70,7 @@ function App() {
const loadEngine = async () => {
console.log('Loading engine...');
setIsFetching(true);
setOutput('Loading model... (this might take a bit)');
setOutput('Chargement du modèle...');

const engine: EngineInterface = await CreateWebWorkerEngine(
new Worker(new URL('./worker.ts', import.meta.url), {
Expand All @@ -82,6 +81,8 @@ function App() {
);
setIsFetching(false);
setEngine(engine);
const isInChache = await hasModelInCache(selectedModel, appConfig);
setModelInCache(isInChache);
return engine;
};

Expand All @@ -95,7 +96,8 @@ function App() {

const userMessage: ChatCompletionMessageParam = {
role: 'user',
content: 'Tu peux me traduire ce texte en anglais :' + input,
content:
(switched ? promptEnglishToFrench : promptFrenchToEnglish) + input,
};

if (!loadedEngine) {
Expand All @@ -113,6 +115,7 @@ function App() {

try {
await loadedEngine.resetChat();
console.log(userMessage);
const completion = await loadedEngine.chat.completions.create({
stream: true,
messages: [userMessage],
Expand Down Expand Up @@ -167,18 +170,29 @@ function App() {

return (
<>
<h1>🥐 CroissantLLM</h1>
<h2>A Truly Bilingual French-English Language Model</h2>

<Button variant='light' color='gray' onClick={loadEngine}>
<h1>Traduction Anglais/Français</h1>
<h2>Un service 100% souverain et confidentiel</h2>
<p>
Cette traduction est le résultat d'un traitement local dans votre
navigateur. Vos données ne quittent pas votre ordinateur et ne
transitent par aucun serveur.
</p>

{/* <Button variant='light' color='gray' onClick={loadEngine}>
Load
</Button>
</Button> */}

<Button variant='light' color='gray' onClick={checkModelInCache}>
{/* <Button variant='light' color='gray' onClick={checkModelInCache}>
Check Cache
</Button>
{modelInCache && <p>Modèle téléchargé : {modelInCache ? '✅' : '❌'}</p>}
<Button variant='light' color='gray' onClick={() => engine?.unload()}>
Unload
</Button> */}

{modelInCache !== null && (
<p>Modèle téléchargé : {modelInCache === true ? '✅' : '❌'}</p>
)}

<div className='textbox-container'>
<Textarea
Expand All @@ -190,10 +204,42 @@ function App() {
disabled={isFecthing}
variant='filled'
size='lg'
label='Français'
label={switched ? 'Anglais' : 'Français'}
placeholder='Écrivez ou collez votre texte ici.'
className='textarea'
/>

<div>
<div className='horizontal-switch-button'>
<Tooltip label='Intervertir les langues source et cible'>
<ActionIcon
variant='transparent'
color='black'
size='xl'
data-disabled={isFecthing || isGenerating}
onClick={() => setSwitched((prevState) => !prevState)}
className='switch-button'
>
<IconSwitchHorizontal style={{ width: '90%', height: '90%' }} />
</ActionIcon>
</Tooltip>
</div>
<div className='vertical-switch-button'>
<Tooltip label='Intervertir les langues source et cible'>
<ActionIcon
variant='transparent'
color='black'
size='xl'
disabled={isFecthing || isGenerating}
onClick={() => setSwitched((prevState) => !prevState)}
className='switch-button'
>
<IconSwitchVertical style={{ width: '90%', height: '90%' }} />
</ActionIcon>
</Tooltip>
</div>
</div>

<Textarea
value={output}
autosize
Expand All @@ -202,7 +248,7 @@ function App() {
disabled={isFecthing}
variant='filled'
size='lg'
label='Anglais'
label={switched ? 'Français' : 'Anglais'}
className='textarea'
/>
{/* <textarea
Expand Down Expand Up @@ -252,8 +298,15 @@ function App() {
</div>
)}

<div>{progress}</div>
<div className='progress-text'>{progress}</div>
{runtimeStats && <p>Performances : {runtimeStats}</p>}
<p>
Motorisé par {''}
<a href='https://huggingface.co/croissantllm' target='_blank'>
🥐CroissantLLM
</a>
, un LLM souverain par CentraleSupélec.
</p>
</>
);
}
Expand Down
20 changes: 10 additions & 10 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ h2 {
text-align: center;
}

p {
text-align: center;
padding: 0 1rem;
}

a {
color: inherit;
text-decoration: none;
}

textarea {
padding: 0.6em;
}
Expand All @@ -44,16 +54,6 @@ button[disabled] {
cursor: not-allowed;
}

textarea,
button {
border-radius: 8px;
border: 1px solid transparent;
font-size: 1em;
font-family: inherit;
background-color: #f9f9f9;
transition: border-color 0.25s;
}

textarea:hover,
button:not([disabled]):hover {
border-color: black;
Expand Down

0 comments on commit e99a97a

Please sign in to comment.