fix: select modal bugs

This commit is contained in:
kangfenmao 2024-07-05 10:19:32 +08:00
parent 4296f49e66
commit f077cf290d
15 changed files with 62 additions and 47 deletions

View File

@ -30,11 +30,6 @@ export function useAssistants() {
}
}
export function useDefaultModel() {
const defaultModel = useAppSelector((state) => state.llm.defaultModel)
return { defaultModel }
}
export function useAssistant(id: string) {
const assistant = useAppSelector((state) => state.assistants.assistants.find((a) => a.id === id) as Assistant)
const dispatch = useAppDispatch()
@ -60,3 +55,8 @@ export function useAssistant(id: string) {
}
}
}
export function useDefaultModel() {
const defaultModel = useAppSelector((state) => state.llm.defaultModel)
return { defaultModel }
}

View File

@ -31,10 +31,6 @@ export function useProviderByAssistant(assistant: Assistant) {
return provider
}
export function useDefaultProvider() {
return useAppSelector((state) => state.llm.providers.find((p) => p.isDefault))
}
export function useSystemProviders() {
return useAppSelector((state) => state.llm.providers.filter((p) => p.isSystem))
return useAppSelector((state) => state.llm.providers.filter((p) => p.isSystem)) as unknown as Provider
}

View File

@ -2,13 +2,13 @@ import { Navbar, NavbarLeft, NavbarRight } from '@renderer/components/app/Navbar
import { useAssistants } from '@renderer/hooks/useAssistant'
import { FC, useState } from 'react'
import styled from 'styled-components'
import Chat from './components/Chat/Chat'
import Chat from './components/Chat'
import Assistants from './components/Assistants'
import { uuid } from '@renderer/utils'
import { getDefaultAssistant } from '@renderer/services/assistant'
import { useShowRightSidebar } from '@renderer/hooks/useStore'
import { Tooltip } from 'antd'
import NavigationCenter from './components/Chat/NavigationCenter'
import Navigation from './components/Navigation'
const HomePage: FC = () => {
const { assistants, addAssistant } = useAssistants()
@ -30,7 +30,7 @@ const HomePage: FC = () => {
<i className="iconfont icon-a-addchat"></i>
</NewButton>
</NavbarLeft>
<NavigationCenter activeAssistant={activeAssistant} />
<Navigation activeAssistant={activeAssistant} />
<NavbarRight style={{ justifyContent: 'flex-end', padding: 5 }}>
<Tooltip placement="left" title={showRightSidebar ? 'Hide Topics' : 'Show Topics'} arrow>
<NewButton onClick={setShowRightSidebar}>

View File

@ -38,20 +38,17 @@ const Conversations: FC<Props> = ({ assistant, topic }) => {
const autoRenameTopic = useCallback(async () => {
if (topic.name === DEFAULT_TOPIC_NAME && messages.length >= 2) {
const summaryText = await fetchConversationSummary({ messages })
if (summaryText) {
updateTopic({ ...topic, name: summaryText })
}
const summaryText = await fetchConversationSummary({ messages, assistant })
summaryText && updateTopic({ ...topic, name: summaryText })
}
}, [messages, topic, updateTopic])
}, [assistant, messages, topic, updateTopic])
useEffect(() => {
const unsubscribes = [
EventEmitter.on(EVENT_NAMES.SEND_MESSAGE, async (msg: Message) => {
console.debug({ assistant, provider, message: msg, topic })
return
onSendMessage(msg)
fetchChatCompletion({ assistant, provider, message: msg, topic, onResponse: setLastMessage })
fetchChatCompletion({ assistant, message: msg, topic, onResponse: setLastMessage })
}),
EventEmitter.on(EVENT_NAMES.AI_CHAT_COMPLETION, async (msg: Message) => {
setLastMessage(null)
@ -66,12 +63,12 @@ const Conversations: FC<Props> = ({ assistant, topic }) => {
})
]
return () => unsubscribes.forEach((unsub) => unsub())
}, [assistant, autoRenameTopic, onSendMessage, topic, updateTopic])
}, [assistant, autoRenameTopic, onSendMessage, provider, topic, updateTopic])
useEffect(() => {
runAsyncFunction(async () => {
const messages = await LocalStorage.getTopicMessages(topic.id)
setMessages(messages)
setMessages(messages || [])
})
}, [topic.id])

View File

@ -29,7 +29,7 @@ const TopicList: FC<Props> = ({ assistant, activeTopic, setActiveTopic }) => {
if (currentTopic.current) {
const messages = await LocalStorage.getTopicMessages(currentTopic.current.id)
if (messages.length >= 2) {
const summaryText = await fetchConversationSummary({ messages })
const summaryText = await fetchConversationSummary({ messages, assistant })
if (summaryText) {
updateTopic({ ...currentTopic.current, name: summaryText })
}

View File

@ -39,7 +39,13 @@ const ModalProviderSetting: FC<Props> = ({ provider }) => {
<Title>{provider.name}</Title>
<Divider style={{ width: '100%', margin: '10px 0' }} />
<SubTitle>API Key</SubTitle>
<Input value={apiKey} placeholder="API Key" onChange={(e) => setApiKey(e.target.value)} onBlur={onUpdateApiKey} />
<Input
value={apiKey}
placeholder="API Key"
onChange={(e) => setApiKey(e.target.value)}
onBlur={onUpdateApiKey}
spellCheck={false}
/>
<SubTitle>API Host</SubTitle>
<Input
value={apiHost}

View File

@ -3,30 +3,29 @@ import { uuid } from '@renderer/utils'
import { EVENT_NAMES, EventEmitter } from './event'
import { ChatCompletionMessageParam, ChatCompletionSystemMessageParam } from 'openai/resources'
import OpenAI from 'openai'
import { getAssistantProvider } from './assistant'
interface FetchChatCompletionParams {
message: Message
topic: Topic
assistant: Assistant
provider: Provider
onResponse: (message: Message) => void
}
export async function fetchChatCompletion({
message,
topic,
assistant,
provider,
onResponse
}: FetchChatCompletionParams) {
const openaiProvider = new OpenAI({
const getOpenAiProvider = (provider: Provider) => {
return new OpenAI({
dangerouslyAllowBrowser: true,
apiKey: provider.apiKey,
baseURL: `${provider.apiHost}/v1/`
})
}
export async function fetchChatCompletion({ message, topic, assistant, onResponse }: FetchChatCompletionParams) {
const provider = getAssistantProvider(assistant)
const openaiProvider = getOpenAiProvider(provider)
const stream = await openaiProvider.chat.completions.create({
model: assistant.model?.name || '',
model: assistant.model?.id || '',
messages: [
{ role: 'system', content: assistant.prompt },
{ role: 'user', content: message.content }
@ -59,9 +58,13 @@ export async function fetchChatCompletion({
interface FetchConversationSummaryParams {
messages: Message[]
assistant: Assistant
}
export async function fetchConversationSummary({ messages }: FetchConversationSummaryParams) {
export async function fetchConversationSummary({ messages, assistant }: FetchConversationSummaryParams) {
const provider = getAssistantProvider(assistant)
const openaiProvider = getOpenAiProvider(provider)
const userMessages: ChatCompletionMessageParam[] = messages.map((message) => ({
role: 'user',
content: message.content
@ -74,7 +77,7 @@ export async function fetchConversationSummary({ messages }: FetchConversationSu
}
const response = await openaiProvider.chat.completions.create({
model: 'Qwen/Qwen2-7B-Instruct',
model: assistant.model?.id || '',
messages: [systemMessage, ...userMessages],
stream: false
})

View File

@ -1,5 +1,6 @@
import { Assistant } from '@renderer/types'
import { Assistant, Provider } from '@renderer/types'
import { getDefaultTopic } from './topic'
import store from '@renderer/store'
export function getDefaultAssistant(): Assistant {
return {
@ -10,3 +11,13 @@ export function getDefaultAssistant(): Assistant {
topics: [getDefaultTopic()]
}
}
export function getAssistantProvider(assistant: Assistant) {
const providers = store.getState().llm.providers
return providers.find((p) => p.id === assistant.id) || getDefaultProvider()
}
export function getDefaultProvider() {
const provider = store.getState().llm.providers.find((p) => p.isSystem)
return provider as Provider
}

View File

@ -12,15 +12,18 @@ const rootReducer = combineReducers({
llm
})
const persistedReducer = persistReducer(
{
key: 'cherry-ai',
storage,
version: 1
},
rootReducer
)
const store = configureStore({
reducer: persistReducer(
{
key: 'cherry-ai',
storage,
version: 1
},
rootReducer
),
// @ts-ignore store type is unknown
reducer: persistedReducer as typeof rootReducer,
middleware: (getDefaultMiddleware) => {
return getDefaultMiddleware({
serializableCheck: {

View File

@ -38,7 +38,7 @@ const initialState: LlmState = {
id: 'groq',
name: 'Groq',
apiKey: '',
apiHost: 'https://api.groq.com',
apiHost: 'https://api.groq.com/openai',
isSystem: true,
models: SYSTEM_MODELS.groq.filter((m) => m.defaultEnabled)
}

View File

@ -36,7 +36,6 @@ export type Provider = {
apiHost: string
models: Model[]
isSystem?: boolean
isDefault?: boolean
}
export type Model = {