Skip to content

Commit

Permalink
Added model switcher in sidebar for easy access
Browse files Browse the repository at this point in the history
  • Loading branch information
Royal-lobster committed Apr 13, 2024
1 parent 04e649f commit ace1efb
Show file tree
Hide file tree
Showing 12 changed files with 112 additions and 52 deletions.
2 changes: 1 addition & 1 deletion src/components/Layout/DialogPortal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react'
import type React from 'react'
import * as Dialog from '@radix-ui/react-dialog'
import { HiX } from 'react-icons/hi'

Expand Down
5 changes: 2 additions & 3 deletions src/components/Layout/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import React from 'react'
import { BsRobot } from 'react-icons/bs'

const Header = () => {
return (
<div>
<h1 className='cdx-flex cdx-items-center cdx-gap-3 items-center cdx-text-5xl cdx-mb-2 dark:cdx-text-neutral-100 cdx-text-neutral-800'>
<BsRobot className='cdx-text-blue-400' />
<h1 className="cdx-flex cdx-items-center cdx-gap-3 items-center cdx-text-5xl cdx-mb-2 dark:cdx-text-neutral-100 cdx-text-neutral-800">
<BsRobot className="cdx-text-blue-400" />
<span>Syncia</span>
</h1>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/QuickMenu/RecursiveItem.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
import { ContentClassNames, ItemClassNames } from '.'
import { Prompt } from '../../hooks/usePrompts'
import type { Prompt } from '../../hooks/usePrompts'
import { HiOutlineChevronRight } from 'react-icons/hi'

type RecursiveItemProps = {
Expand Down
2 changes: 1 addition & 1 deletion src/components/Settings/Elements/AddItemButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as Dialog from '@radix-ui/react-dialog'
import { useRef, useState } from 'react'
import { HiDocumentText, HiFolder } from 'react-icons/hi'
import TextareaAutosize from 'react-textarea-autosize'
import { Prompt, usePrompts } from '../../../hooks/usePrompts'
import { type Prompt, usePrompts } from '../../../hooks/usePrompts'
import DialogPortal from '../../Layout/DialogPortal'
import { getUUID } from '../../../lib/getUUID'

Expand Down
6 changes: 3 additions & 3 deletions src/components/Settings/Elements/DeletePromptButton.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState } from 'react'
import { Prompt, usePrompts } from '../../../hooks/usePrompts'
import { type Prompt, usePrompts } from '../../../hooks/usePrompts'
import * as Dialog from '@radix-ui/react-dialog'
import { HiTrash } from 'react-icons/hi'
import DialogPortal from '../../Layout/DialogPortal'
Expand All @@ -11,11 +11,11 @@ export const DeletePromptButton = ({ id }: { id: string }) => {
const handleDelete = () => {
const removeItem = (items: Prompt[], id: string): Prompt[] => {
const newItems = items.filter((item) => item.id !== id)
newItems.forEach((item) => {
for (const item of newItems) {
if (item.children) {
item.children = removeItem(item.children, id)
}
})
}
return newItems
}
setPrompts([])
Expand Down
2 changes: 1 addition & 1 deletion src/components/Settings/Elements/EditPromptButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as Dialog from '@radix-ui/react-dialog'
import { useRef, useState } from 'react'
import { HiPencilAlt } from 'react-icons/hi'
import TextareaAutosize from 'react-textarea-autosize'
import { Prompt, usePrompts } from '../../../hooks/usePrompts'
import { type Prompt, usePrompts } from '../../../hooks/usePrompts'
import DialogPortal from '../../Layout/DialogPortal'

export const EditPromptButton = ({
Expand Down
10 changes: 5 additions & 5 deletions src/components/Settings/Elements/FieldWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react'
import type React from 'react'

interface FieldWrapperProps {
title: string
Expand All @@ -18,20 +18,20 @@ const FieldWrapper = ({
return (
<form
data-row={row || undefined}
className='cdx-flex cdx-flex-col cdx-gap-1 data-[row]:cdx-items-center cdx-my-4 data-[row]:cdx-flex-row data-[row]:cdx-justify-between data-[row]:cdx-gap-2'
className="cdx-flex cdx-flex-col cdx-gap-1 data-[row]:cdx-items-center cdx-my-4 data-[row]:cdx-flex-row data-[row]:cdx-justify-between data-[row]:cdx-gap-2"
onSubmit={onSubmit}
>
<div>
<label className='cdx-text-xl dark:cdx-text-neutral-200 cdx-text-neutral-700'>
<label className="cdx-text-xl dark:cdx-text-neutral-200 cdx-text-neutral-700">
{title}
</label>
{description && (
<p className='cdx-text-sm cdx-mt-2 cdx-text-neutral-400'>
<p className="cdx-text-sm cdx-mt-2 cdx-text-neutral-400">
{description}
</p>
)}
</div>
<div className='cdx-mt-2'>{children}</div>
<div className="cdx-mt-2">{children}</div>
</form>
)
}
Expand Down
43 changes: 9 additions & 34 deletions src/components/Settings/Sections/ChatSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import React, { useCallback, useEffect } from 'react'
import SectionHeading from '../Elements/SectionHeading'
import FieldWrapper from '../Elements/FieldWrapper'
import * as Switch from '@radix-ui/react-switch'
import React, { useState } from 'react'
import { AiOutlineEye, AiOutlineEyeInvisible } from 'react-icons/ai'
import { useSettings } from '../../../hooks/useSettings'
import { validateApiKey } from '../../../lib/validApiKey'
import { AvailableModels, Mode } from '../../../config/settings'
import { useChatModels } from '../../../hooks/useChatModels'
import { capitalizeText } from '../../../lib/capitalizeText'
import { useState } from 'react'
import { AiOutlineEye, AiOutlineEyeInvisible } from 'react-icons/ai'
import axios from 'axios'
import * as Switch from '@radix-ui/react-switch'
import { validateApiKey } from '../../../lib/validApiKey'
import FieldWrapper from '../Elements/FieldWrapper'
import SectionHeading from '../Elements/SectionHeading'
import { type AvailableModels, Mode } from '../../../config/settings'

const ChatSettings = () => {
const [settings, setSettings] = useSettings()
const [showPassword, setShowPassword] = useState(false)
const [dynamicModels, setDynamicModels] = useState<string[]>([])
const { availableModels, fetchLocalModels } = useChatModels()
const OpenAiApiKeyInputRef = React.useRef<HTMLInputElement>(null)

const chatSettings = settings.chat
Expand Down Expand Up @@ -50,30 +49,6 @@ const ChatSettings = () => {
}
}

const fetchLocalModels = useCallback(async () => {
if (chatSettings.showLocalModels) {
const {
data: { models },
} = await axios<{ models: { name: string }[] }>(
'http://localhost:11434/api/tags',
)
if (models) {
setDynamicModels(models.map((m) => m.name))
}
} else {
setDynamicModels([])
}
}, [chatSettings.showLocalModels])

useEffect(() => {
fetchLocalModels()
}, [fetchLocalModels])

const availableModels = [
...Object.entries(AvailableModels),
...dynamicModels.map((m) => [m, m]),
]

return (
<div className="cdx-w-full cdx-flex-shrink-0 cdx-rounded-md">
<SectionHeading title="Chat" />
Expand Down
33 changes: 33 additions & 0 deletions src/components/Sidebar/chat/ChangeChatModel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { AvailableModels } from '../../../config/settings'
import { useChatModels } from '../../../hooks/useChatModels'
import { capitalizeText } from '../../../lib/capitalizeText'

const ChangeChatModel = () => {
const { availableModels, activeChatModel, setActiveChatModel } =
useChatModels()
return (
<div>
<select
value={activeChatModel}
className="input cdx-w-44"
onChange={(e) => {
setActiveChatModel(e.target.value as AvailableModels)
}}
>
{availableModels.map(([modal, value]) => (
<option key={modal} value={value}>
{capitalizeText(
modal
.toLowerCase()
.replace('gpt', 'GPT')
.replace('3_5', '3.5')
.replaceAll('_', ' '),
)}
</option>
))}
</select>
</div>
)
}

export default ChangeChatModel
5 changes: 2 additions & 3 deletions src/components/Sidebar/chat/ChatHistory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,8 @@ const ChatHistory = () => {
return (
<div>
<DropdownMenu.Root>
<DropdownMenu.Trigger className="cdx-border cdx-max-w-[280px] dark:cdx-bg-neutral-800/80 cdx-backdrop-blur cdx-border-neutral-500/20 cdx-flex cdx-gap-2 cdx-items-center cdx-py-2 cdx-px-3 cdx-text-sm cdx-text-neutral-700 dark:cdx-text-neutral-300 cdx-rounded-md">
<RiTimeLine size={18} className="cdx-flex-shrink-0" />{' '}
<span className="cdx-truncate">{currentChat?.name}</span>
<DropdownMenu.Trigger className="cdx-border dark:cdx-bg-neutral-800/80 cdx-backdrop-blur cdx-border-neutral-500/20 cdx-flex cdx-gap-2 cdx-items-center cdx-p-2 cdx-text-sm cdx-text-neutral-700 dark:cdx-text-neutral-300 cdx-rounded-md">
<RiTimeLine size={18} className="cdx-flex-shrink-0" /> History
</DropdownMenu.Trigger>
<DropdownMenu.Content
side="top"
Expand Down
2 changes: 2 additions & 0 deletions src/components/Sidebar/chat/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
} from '../../../hooks/useMessageDraft'
import FilePreviewBar from './FilePreviewBar'
import MessageDraftLengthCounter from './MessageDraftLengthCounter'
import ChangeChatModel from './ChangeChatModel'

interface SidebarInputProps {
loading: boolean
Expand Down Expand Up @@ -108,6 +109,7 @@ export function SidebarInput({
) : (
<div />
)}
<ChangeChatModel />
{(history.length || !chatIsEmpty) && <ChatHistory />}
</div>

Expand Down
52 changes: 52 additions & 0 deletions src/hooks/useChatModels.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useCallback, useEffect, useState } from 'react'
import { useSettings } from './useSettings'
import axios from 'axios'
import { AvailableModels } from '../config/settings'

export const useChatModels = () => {
const [settings, setSettings] = useSettings()
const [dynamicModels, setDynamicModels] = useState<string[]>([])
const chatSettings = settings.chat
const activeChatModel = chatSettings.modal

const fetchLocalModels = useCallback(async () => {
if (chatSettings.showLocalModels) {
const {
data: { models },
} = await axios<{ models: { name: string }[] }>(
'http://localhost:11434/api/tags',
)
if (models) {
setDynamicModels(models.map((m) => m.name))
}
} else {
setDynamicModels([])
}
}, [chatSettings.showLocalModels])

useEffect(() => {
fetchLocalModels()
}, [fetchLocalModels])

const availableModels = [
...Object.entries(AvailableModels),
...dynamicModels.map((m) => [m, m]),
]

const setActiveChatModel = (model: AvailableModels) => {
setSettings({
...settings,
chat: {
...chatSettings,
modal: model,
},
})
}

return {
availableModels,
activeChatModel,
setActiveChatModel,
fetchLocalModels,
}
}

0 comments on commit ace1efb

Please sign in to comment.