Skip to content

Commit

Permalink
Merge pull request #121 from cheeseonamonkey/ModelConfig
Browse files Browse the repository at this point in the history
Model config
  • Loading branch information
jackschedel committed Apr 11, 2024
2 parents f774686 + 586b543 commit b9bbce1
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 186 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "koala-client",
"private": true,
"version": "2.1.0",
"version": "2.1.1",
"type": "module",
"homepage": "./",
"main": "electron/index.cjs",
Expand Down
18 changes: 18 additions & 0 deletions src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,21 @@ export const submitShareGPT = async (body: ShareGPTSubmitBodyInterface) => {
const url = `https://shareg.pt/${id}`;
window.open(url, '_blank');
};

export const fetchOpenAIModels = async (apiKey: string) => {
try {
const response = await fetch('https://api.openai.com/v1/models', {
headers: {
Authorization: `Bearer ${apiKey}`,
},
});
const data = await response.json();
const openaiModels = data.data.filter(
(model: { owned_by: string }) => model.owned_by === 'openai'
);
return openaiModels.map((model: { name: any }) => model.name);
} catch (error) {
console.error('Error fetching models:', error);
return [];
}
};
196 changes: 12 additions & 184 deletions src/components/ApiMenu/ApiMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import VisibleIcon from '@icon/VisibleIcon';

import DownChevronArrow from '@icon/DownChevronArrow';
import { tokenCostToCost } from '@utils/messageUtils';
import { ModelInput } from './ModelInput';

const ApiMenu = ({
setIsModalOpen,
Expand Down Expand Up @@ -136,7 +137,7 @@ const ApiMenu = ({
}}
>
<div className='min-w-fit text-custom-white text-sm flex flex-col gap-2 leading-relaxed'>
<p>Deleting an endpoint will delete all asociated models.</p>
<p>Deleting an endpoint will delete all associated models.</p>
<p>Whisper record always uses the first endpoint.</p>
<div className='flex flex-col max-w-full'>
<div className='flex items-center border-b border-neutral-base/50 mb-1 p-1'>
Expand Down Expand Up @@ -198,194 +199,21 @@ const ApiMenu = ({
<PlusIcon />
</div>
</div>

<div className='flex flex-col max-w-full'>
<div className='text-center font-bold items-center border-b border-neutral-base/50 mb-1 p-1'>
Models
</div>
{_modelDefs.map((modelDef, index) => (
<div key={'model' + index} className='mb-4'>
<div className='flex items-center border-b border-neutral-base/50 mb-1 p-1'>
<div className='flex-1'>
<input
type='text'
className='text-custom-black p-3 text-sm border-none bg-custom-white rounded-md m-0 w-full mr-0 h-8 focus:outline-none'
placeholder='Nickname'
value={modelDef.name}
onChange={(e) => {
_setModelDefs((prev) => {
const newModelDefs = [...prev];
newModelDefs[index].name = e.target.value;
return newModelDefs;
});
}}
/>
</div>
<div className='flex-1 px-1'>
<input
type='text'
className='text-custom-black p-3 text-sm border-none bg-custom-white rounded-md m-0 w-full mr-0 h-8 focus:outline-none'
placeholder='Model'
value={modelDef.model}
onChange={(e) => {
_setModelDefs((prev) => {
const newModelDefs = [...prev];
newModelDefs[index].model = e.target.value;
return newModelDefs;
});
}}
/>
</div>
<div className='flex-1'>
<button
className='btn bg-custom-white text-custom-black btn-small overflow-clip relative pr-6 w-80'
type='button'
onClick={() => {
if (activeDropdown === index) {
setActiveDropdown(null);
} else {
setActiveDropdown(index);
}
}}
>
<span className='inline-block truncate max-w-full'>
{_apiAuth[modelDef.endpoint]
? _apiAuth[modelDef.endpoint].endpoint.replace(
/^https?:\/\//,
''
)
: 'Endpoint Undefined'}
</span>

<DownChevronArrow className='absolute right-0 mr-1 flex items-center' />
</button>

<div
id='dropdown'
className={`${
activeDropdown != null && activeDropdown == index
? ''
: 'hidden'
} absolute top-100 bottom-100 z-10 w-80 bg-custom-white text-custom-black shadow-xl rounded-lg border border-neutral-base group`}
>
<ul
className='text-sm p-0 m-0 max-h-72 overflow-clip'
aria-labelledby='dropdownDefaultButton'
>
{_apiAuth.map((auth, authIndex) => (
<li
className='btn btn-small w-full overflow-clip hover:bg-neutral-light hover:text-custom-white cursor-pointer'
onClick={() => {
setModelEndpoint(index, authIndex);
setActiveDropdown(null);
}}
key={'dropdown' + authIndex}
>
{auth.endpoint.replace(/^https?:\/\//, '')}
</li>
))}
</ul>
</div>
</div>
<div
className='p-1 ml-2 hover:text-neutral-dark hover:bg-custom-white hover:rounded'
onClick={() => deleteModel(index)}
>
<CrossIcon
className={`${_modelDefs.length > 1 ? '' : 'invisible'}`}
/>
</div>
</div>
<div className='flex items-center border-b border-neutral-base/50 px-1'>
<div className='flex-1 pr-1'>
<input
type='text'
pattern='[0-9]*'
className='text-custom-black p-3 text-sm border-none bg-custom-white rounded-md m-0 w-full mr-0 h-8 focus:outline-none'
placeholder='Max Tokens'
value={modelDef.model_max_tokens || ''}
onChange={(e) => {
const value = Number(e.target.value);

if (!isNaN(value)) {
_setModelDefs((prev) => {
const newModelDefs = [...prev];
newModelDefs[index].model_max_tokens = value;
return newModelDefs;
});
}
}}
/>
</div>
<div className='flex-1 pr-1'>
<input
type='text'
pattern='[0-9]*'
className='text-custom-black p-3 text-sm border-none bg-custom-white rounded-md m-0 w-full mr-0 h-8 focus:outline-none'
placeholder='Max Context'
value={modelDef.model_max_context || ''}
onChange={(e) => {
const value = Number(e.target.value);

if (!isNaN(value)) {
_setModelDefs((prev) => {
const newModelDefs = [...prev];
newModelDefs[index].model_max_context = value;
return newModelDefs;
});
}
}}
/>
</div>
<div className='flex-1 pr-1'>
<input
type='text'
pattern='[0-9]*'
className='text-custom-black p-3 text-sm border-none bg-custom-white rounded-md m-0 w-full mr-0 h-8 focus:outline-none'
placeholder='Prompt Cost*'
value={modelDef?.prompt_cost_1000 || ''}
onChange={(e) => {
const value = Number(e.target.value);

if (!isNaN(value)) {
_setModelDefs((prev) => {
const newModelDefs = [...prev];
newModelDefs[index].prompt_cost_1000 = value;
return newModelDefs;
});
}
}}
/>
</div>
<div className='flex-1'>
<input
type='text'
pattern='[0-9]*'
className='text-custom-black p-3 text-sm border-none bg-custom-white rounded-md m-0 w-full mr-0 h-8 focus:outline-none'
placeholder='Completion Cost*'
value={modelDef.completion_cost_1000 || ''}
onChange={(e) => {
const value = Number(e.target.value);

if (!isNaN(value)) {
_setModelDefs((prev) => {
const newModelDefs = [...prev];
newModelDefs[index].completion_cost_1000 = value;
return newModelDefs;
});
}
}}
/>
</div>
<div className='p-1 ml-2 hover:text-custom-black hover:bg-custom-white hover:rounded'>
{_modelDefs[index].swap_visible ? (
<VisibleIcon onClick={() => setHideModel(index, false)} />
) : (
<HiddenIcon onClick={() => setHideModel(index, true)} />
)}
</div>
</div>
</div>
<ModelInput
key={index}
modelDef={modelDef}
index={index}
apiAuth={_apiAuth}
setModelDefs={_setModelDefs}
setHideModel={setHideModel}
deleteModel={deleteModel}
setModelEndpoint={setModelEndpoint}
/>
))}
</div>
<div className='flex justify-center mt-0 mb-8'>
Expand Down
Loading

0 comments on commit b9bbce1

Please sign in to comment.