import React, { FC, useEffect, useRef } from 'react'; import { observer } from 'mobx-react-lite'; import { WorkHeader } from '../components/WorkHeader'; import { Button, Dropdown, Input, Option, Textarea } from '@fluentui/react-components'; import { Labeled } from '../components/Labeled'; import { ValuedSlider } from '../components/ValuedSlider'; import { useTranslation } from 'react-i18next'; import { ApiParameters } from './Configs'; import commonStore, { ModelStatus } from '../stores/commonStore'; import { fetchEventSource } from '@microsoft/fetch-event-source'; import { toast } from 'react-toastify'; export type CompletionParams = Omit & { stop: string } export type CompletionPreset = { name: string, prompt: string, params: CompletionParams } export const defaultPresets: CompletionPreset[] = [{ name: 'Writer', prompt: 'The following is an epic science fiction masterpiece that is immortalized, with delicate descriptions and grand depictions of interstellar civilization wars.\nChapter 1.\n', params: { maxResponseToken: 4100, temperature: 1, topP: 0.5, presencePenalty: 0.4, frequencyPenalty: 0.4, stop: '' } }, { name: 'Translator', prompt: '', params: { maxResponseToken: 4100, temperature: 1, topP: 0.5, presencePenalty: 0.4, frequencyPenalty: 0.4, stop: '' } }, { name: 'Catgirl', prompt: '', params: { maxResponseToken: 4100, temperature: 1, topP: 0.5, presencePenalty: 0.4, frequencyPenalty: 0.4, stop: '' } }, { name: 'Explain Code', prompt: '', params: { maxResponseToken: 4100, temperature: 1, topP: 0.5, presencePenalty: 0.4, frequencyPenalty: 0.4, stop: '' } }, { name: 'Werewolf', prompt: '', params: { maxResponseToken: 4100, temperature: 1, topP: 0.5, presencePenalty: 0.4, frequencyPenalty: 0.4, stop: '' } }, { name: 'Blank', prompt: '', params: { maxResponseToken: 4100, temperature: 1, topP: 0.5, presencePenalty: 0.4, frequencyPenalty: 0.4, stop: '' } }]; const CompletionPanel: FC = observer(() => { const { t } = useTranslation(); const inputRef = useRef(null); const port = commonStore.getCurrentModelConfig().apiParameters.apiPort; const sseControllerRef = useRef(null); const scrollToBottom = () => { if (inputRef.current) inputRef.current.scrollTop = inputRef.current.scrollHeight; }; useEffect(() => { if (inputRef.current) inputRef.current.style.height = '100%'; scrollToBottom(); }, []); const setPreset = (preset: CompletionPreset) => { commonStore.setCompletionPreset({ ...preset, prompt: t(preset.prompt) }); }; if (!commonStore.completionPreset) setPreset(defaultPresets[0]); const name = commonStore.completionPreset!.name; const prompt = commonStore.completionPreset!.prompt; const setPrompt = (prompt: string) => { commonStore.setCompletionPreset({ ...commonStore.completionPreset!, prompt }); }; const params = commonStore.completionPreset!.params; const setParams = (newParams: Partial) => { commonStore.setCompletionPreset({ ...commonStore.completionPreset!, params: { ...commonStore.completionPreset!.params, ...newParams } }); }; const onSubmit = (prompt: string) => { if (commonStore.status.status === ModelStatus.Offline) { toast(t('Please click the button in the top right corner to start the model'), { type: 'warning' }); commonStore.setCompletionGenerating(false); return; } let answer = ''; sseControllerRef.current = new AbortController(); fetchEventSource(`http://127.0.0.1:${port}/completions`, // https://api.openai.com/v1/completions || http://127.0.0.1:${port}/completions { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer sk-` }, body: JSON.stringify({ prompt, stream: true, model: 'text-davinci-003', max_tokens: params.maxResponseToken, temperature: params.temperature, top_p: params.topP, presence_penalty: params.presencePenalty, frequency_penalty: params.frequencyPenalty, stop: params.stop || undefined }), signal: sseControllerRef.current?.signal, onmessage(e) { console.log('sse message', e); scrollToBottom(); if (e.data === '[DONE]') { commonStore.setCompletionGenerating(false); return; } let data; try { data = JSON.parse(e.data); } catch (error) { console.debug('json error', error); return; } if (data.choices && Array.isArray(data.choices) && data.choices.length > 0) { answer += data.choices[0].text; setPrompt(prompt + answer); } }, onclose() { console.log('Connection closed'); }, onerror(err) { commonStore.setCompletionGenerating(false); throw err; } }); }; return (