fix: select modal bugs
This commit is contained in:
parent
4296f49e66
commit
f077cf290d
@ -30,11 +30,6 @@ export function useAssistants() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useDefaultModel() {
|
|
||||||
const defaultModel = useAppSelector((state) => state.llm.defaultModel)
|
|
||||||
return { defaultModel }
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useAssistant(id: string) {
|
export function useAssistant(id: string) {
|
||||||
const assistant = useAppSelector((state) => state.assistants.assistants.find((a) => a.id === id) as Assistant)
|
const assistant = useAppSelector((state) => state.assistants.assistants.find((a) => a.id === id) as Assistant)
|
||||||
const dispatch = useAppDispatch()
|
const dispatch = useAppDispatch()
|
||||||
@ -60,3 +55,8 @@ export function useAssistant(id: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useDefaultModel() {
|
||||||
|
const defaultModel = useAppSelector((state) => state.llm.defaultModel)
|
||||||
|
return { defaultModel }
|
||||||
|
}
|
||||||
|
|||||||
@ -31,10 +31,6 @@ export function useProviderByAssistant(assistant: Assistant) {
|
|||||||
return provider
|
return provider
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useDefaultProvider() {
|
|
||||||
return useAppSelector((state) => state.llm.providers.find((p) => p.isDefault))
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useSystemProviders() {
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,13 +2,13 @@ import { Navbar, NavbarLeft, NavbarRight } from '@renderer/components/app/Navbar
|
|||||||
import { useAssistants } from '@renderer/hooks/useAssistant'
|
import { useAssistants } from '@renderer/hooks/useAssistant'
|
||||||
import { FC, useState } from 'react'
|
import { FC, useState } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import Chat from './components/Chat/Chat'
|
import Chat from './components/Chat'
|
||||||
import Assistants from './components/Assistants'
|
import Assistants from './components/Assistants'
|
||||||
import { uuid } from '@renderer/utils'
|
import { uuid } from '@renderer/utils'
|
||||||
import { getDefaultAssistant } from '@renderer/services/assistant'
|
import { getDefaultAssistant } from '@renderer/services/assistant'
|
||||||
import { useShowRightSidebar } from '@renderer/hooks/useStore'
|
import { useShowRightSidebar } from '@renderer/hooks/useStore'
|
||||||
import { Tooltip } from 'antd'
|
import { Tooltip } from 'antd'
|
||||||
import NavigationCenter from './components/Chat/NavigationCenter'
|
import Navigation from './components/Navigation'
|
||||||
|
|
||||||
const HomePage: FC = () => {
|
const HomePage: FC = () => {
|
||||||
const { assistants, addAssistant } = useAssistants()
|
const { assistants, addAssistant } = useAssistants()
|
||||||
@ -30,7 +30,7 @@ const HomePage: FC = () => {
|
|||||||
<i className="iconfont icon-a-addchat"></i>
|
<i className="iconfont icon-a-addchat"></i>
|
||||||
</NewButton>
|
</NewButton>
|
||||||
</NavbarLeft>
|
</NavbarLeft>
|
||||||
<NavigationCenter activeAssistant={activeAssistant} />
|
<Navigation activeAssistant={activeAssistant} />
|
||||||
<NavbarRight style={{ justifyContent: 'flex-end', padding: 5 }}>
|
<NavbarRight style={{ justifyContent: 'flex-end', padding: 5 }}>
|
||||||
<Tooltip placement="left" title={showRightSidebar ? 'Hide Topics' : 'Show Topics'} arrow>
|
<Tooltip placement="left" title={showRightSidebar ? 'Hide Topics' : 'Show Topics'} arrow>
|
||||||
<NewButton onClick={setShowRightSidebar}>
|
<NewButton onClick={setShowRightSidebar}>
|
||||||
|
|||||||
@ -38,20 +38,17 @@ const Conversations: FC<Props> = ({ assistant, topic }) => {
|
|||||||
|
|
||||||
const autoRenameTopic = useCallback(async () => {
|
const autoRenameTopic = useCallback(async () => {
|
||||||
if (topic.name === DEFAULT_TOPIC_NAME && messages.length >= 2) {
|
if (topic.name === DEFAULT_TOPIC_NAME && messages.length >= 2) {
|
||||||
const summaryText = await fetchConversationSummary({ messages })
|
const summaryText = await fetchConversationSummary({ messages, assistant })
|
||||||
if (summaryText) {
|
summaryText && updateTopic({ ...topic, name: summaryText })
|
||||||
updateTopic({ ...topic, name: summaryText })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, [messages, topic, updateTopic])
|
}, [assistant, messages, topic, updateTopic])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubscribes = [
|
const unsubscribes = [
|
||||||
EventEmitter.on(EVENT_NAMES.SEND_MESSAGE, async (msg: Message) => {
|
EventEmitter.on(EVENT_NAMES.SEND_MESSAGE, async (msg: Message) => {
|
||||||
console.debug({ assistant, provider, message: msg, topic })
|
console.debug({ assistant, provider, message: msg, topic })
|
||||||
return
|
|
||||||
onSendMessage(msg)
|
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) => {
|
EventEmitter.on(EVENT_NAMES.AI_CHAT_COMPLETION, async (msg: Message) => {
|
||||||
setLastMessage(null)
|
setLastMessage(null)
|
||||||
@ -66,12 +63,12 @@ const Conversations: FC<Props> = ({ assistant, topic }) => {
|
|||||||
})
|
})
|
||||||
]
|
]
|
||||||
return () => unsubscribes.forEach((unsub) => unsub())
|
return () => unsubscribes.forEach((unsub) => unsub())
|
||||||
}, [assistant, autoRenameTopic, onSendMessage, topic, updateTopic])
|
}, [assistant, autoRenameTopic, onSendMessage, provider, topic, updateTopic])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
runAsyncFunction(async () => {
|
runAsyncFunction(async () => {
|
||||||
const messages = await LocalStorage.getTopicMessages(topic.id)
|
const messages = await LocalStorage.getTopicMessages(topic.id)
|
||||||
setMessages(messages)
|
setMessages(messages || [])
|
||||||
})
|
})
|
||||||
}, [topic.id])
|
}, [topic.id])
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ const TopicList: FC<Props> = ({ assistant, activeTopic, setActiveTopic }) => {
|
|||||||
if (currentTopic.current) {
|
if (currentTopic.current) {
|
||||||
const messages = await LocalStorage.getTopicMessages(currentTopic.current.id)
|
const messages = await LocalStorage.getTopicMessages(currentTopic.current.id)
|
||||||
if (messages.length >= 2) {
|
if (messages.length >= 2) {
|
||||||
const summaryText = await fetchConversationSummary({ messages })
|
const summaryText = await fetchConversationSummary({ messages, assistant })
|
||||||
if (summaryText) {
|
if (summaryText) {
|
||||||
updateTopic({ ...currentTopic.current, name: summaryText })
|
updateTopic({ ...currentTopic.current, name: summaryText })
|
||||||
}
|
}
|
||||||
@ -39,7 +39,13 @@ const ModalProviderSetting: FC<Props> = ({ provider }) => {
|
|||||||
<Title>{provider.name}</Title>
|
<Title>{provider.name}</Title>
|
||||||
<Divider style={{ width: '100%', margin: '10px 0' }} />
|
<Divider style={{ width: '100%', margin: '10px 0' }} />
|
||||||
<SubTitle>API Key</SubTitle>
|
<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>
|
<SubTitle>API Host</SubTitle>
|
||||||
<Input
|
<Input
|
||||||
value={apiHost}
|
value={apiHost}
|
||||||
|
|||||||
@ -3,30 +3,29 @@ import { uuid } from '@renderer/utils'
|
|||||||
import { EVENT_NAMES, EventEmitter } from './event'
|
import { EVENT_NAMES, EventEmitter } from './event'
|
||||||
import { ChatCompletionMessageParam, ChatCompletionSystemMessageParam } from 'openai/resources'
|
import { ChatCompletionMessageParam, ChatCompletionSystemMessageParam } from 'openai/resources'
|
||||||
import OpenAI from 'openai'
|
import OpenAI from 'openai'
|
||||||
|
import { getAssistantProvider } from './assistant'
|
||||||
|
|
||||||
interface FetchChatCompletionParams {
|
interface FetchChatCompletionParams {
|
||||||
message: Message
|
message: Message
|
||||||
topic: Topic
|
topic: Topic
|
||||||
assistant: Assistant
|
assistant: Assistant
|
||||||
provider: Provider
|
|
||||||
onResponse: (message: Message) => void
|
onResponse: (message: Message) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchChatCompletion({
|
const getOpenAiProvider = (provider: Provider) => {
|
||||||
message,
|
return new OpenAI({
|
||||||
topic,
|
|
||||||
assistant,
|
|
||||||
provider,
|
|
||||||
onResponse
|
|
||||||
}: FetchChatCompletionParams) {
|
|
||||||
const openaiProvider = new OpenAI({
|
|
||||||
dangerouslyAllowBrowser: true,
|
dangerouslyAllowBrowser: true,
|
||||||
apiKey: provider.apiKey,
|
apiKey: provider.apiKey,
|
||||||
baseURL: `${provider.apiHost}/v1/`
|
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({
|
const stream = await openaiProvider.chat.completions.create({
|
||||||
model: assistant.model?.name || '',
|
model: assistant.model?.id || '',
|
||||||
messages: [
|
messages: [
|
||||||
{ role: 'system', content: assistant.prompt },
|
{ role: 'system', content: assistant.prompt },
|
||||||
{ role: 'user', content: message.content }
|
{ role: 'user', content: message.content }
|
||||||
@ -59,9 +58,13 @@ export async function fetchChatCompletion({
|
|||||||
|
|
||||||
interface FetchConversationSummaryParams {
|
interface FetchConversationSummaryParams {
|
||||||
messages: Message[]
|
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) => ({
|
const userMessages: ChatCompletionMessageParam[] = messages.map((message) => ({
|
||||||
role: 'user',
|
role: 'user',
|
||||||
content: message.content
|
content: message.content
|
||||||
@ -74,7 +77,7 @@ export async function fetchConversationSummary({ messages }: FetchConversationSu
|
|||||||
}
|
}
|
||||||
|
|
||||||
const response = await openaiProvider.chat.completions.create({
|
const response = await openaiProvider.chat.completions.create({
|
||||||
model: 'Qwen/Qwen2-7B-Instruct',
|
model: assistant.model?.id || '',
|
||||||
messages: [systemMessage, ...userMessages],
|
messages: [systemMessage, ...userMessages],
|
||||||
stream: false
|
stream: false
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Assistant } from '@renderer/types'
|
import { Assistant, Provider } from '@renderer/types'
|
||||||
import { getDefaultTopic } from './topic'
|
import { getDefaultTopic } from './topic'
|
||||||
|
import store from '@renderer/store'
|
||||||
|
|
||||||
export function getDefaultAssistant(): Assistant {
|
export function getDefaultAssistant(): Assistant {
|
||||||
return {
|
return {
|
||||||
@ -10,3 +11,13 @@ export function getDefaultAssistant(): Assistant {
|
|||||||
topics: [getDefaultTopic()]
|
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
|
||||||
|
}
|
||||||
|
|||||||
@ -12,15 +12,18 @@ const rootReducer = combineReducers({
|
|||||||
llm
|
llm
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const persistedReducer = persistReducer(
|
||||||
|
{
|
||||||
|
key: 'cherry-ai',
|
||||||
|
storage,
|
||||||
|
version: 1
|
||||||
|
},
|
||||||
|
rootReducer
|
||||||
|
)
|
||||||
|
|
||||||
const store = configureStore({
|
const store = configureStore({
|
||||||
reducer: persistReducer(
|
// @ts-ignore store type is unknown
|
||||||
{
|
reducer: persistedReducer as typeof rootReducer,
|
||||||
key: 'cherry-ai',
|
|
||||||
storage,
|
|
||||||
version: 1
|
|
||||||
},
|
|
||||||
rootReducer
|
|
||||||
),
|
|
||||||
middleware: (getDefaultMiddleware) => {
|
middleware: (getDefaultMiddleware) => {
|
||||||
return getDefaultMiddleware({
|
return getDefaultMiddleware({
|
||||||
serializableCheck: {
|
serializableCheck: {
|
||||||
|
|||||||
@ -38,7 +38,7 @@ const initialState: LlmState = {
|
|||||||
id: 'groq',
|
id: 'groq',
|
||||||
name: 'Groq',
|
name: 'Groq',
|
||||||
apiKey: '',
|
apiKey: '',
|
||||||
apiHost: 'https://api.groq.com',
|
apiHost: 'https://api.groq.com/openai',
|
||||||
isSystem: true,
|
isSystem: true,
|
||||||
models: SYSTEM_MODELS.groq.filter((m) => m.defaultEnabled)
|
models: SYSTEM_MODELS.groq.filter((m) => m.defaultEnabled)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,7 +36,6 @@ export type Provider = {
|
|||||||
apiHost: string
|
apiHost: string
|
||||||
models: Model[]
|
models: Model[]
|
||||||
isSystem?: boolean
|
isSystem?: boolean
|
||||||
isDefault?: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Model = {
|
export type Model = {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user