Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5d6e2c5c5 | ||
|
|
2993ab8dc1 |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cherry-studio",
|
||||
"version": "0.3.0",
|
||||
"version": "0.3.1",
|
||||
"description": "A powerful AI assistant for producer.",
|
||||
"main": "./out/main/index.js",
|
||||
"author": "kangfenmao@qq.com",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { QuestionCircleOutlined } from '@ant-design/icons'
|
||||
import { DEFAULT_CONEXTCOUNT, DEFAULT_TEMPERATURE } from '@renderer/config/constant'
|
||||
import { useAssistants } from '@renderer/hooks/useAssistant'
|
||||
import { useAssistant, useAssistants } from '@renderer/hooks/useAssistant'
|
||||
import { Assistant } from '@renderer/types'
|
||||
import { Button, Col, InputNumber, Popover, Row, Slider, Tooltip } from 'antd'
|
||||
import { debounce } from 'lodash'
|
||||
@@ -12,10 +12,11 @@ interface Props {
|
||||
assistant: Assistant
|
||||
}
|
||||
|
||||
const PopoverContent: FC<Props> = ({ assistant }) => {
|
||||
const PopoverContent: FC<Props> = (props) => {
|
||||
const { assistant } = useAssistant(props.assistant.id)
|
||||
const { updateAssistant } = useAssistants()
|
||||
const [temperature, setTemperature] = useState(assistant.settings?.temperature ?? DEFAULT_TEMPERATURE)
|
||||
const [contextCount, setConextCount] = useState(assistant.settings?.contextCount ?? DEFAULT_CONEXTCOUNT)
|
||||
const [temperature, setTemperature] = useState(assistant?.settings?.temperature ?? DEFAULT_TEMPERATURE)
|
||||
const [contextCount, setConextCount] = useState(assistant?.settings?.contextCount ?? DEFAULT_CONEXTCOUNT)
|
||||
const { t } = useTranslation()
|
||||
|
||||
const onUpdateAssistantSettings = useCallback(
|
||||
@@ -64,8 +65,8 @@ const PopoverContent: FC<Props> = ({ assistant }) => {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setTemperature(assistant.settings?.temperature ?? DEFAULT_TEMPERATURE)
|
||||
setConextCount(assistant.settings?.contextCount ?? DEFAULT_CONEXTCOUNT)
|
||||
setTemperature(assistant?.settings?.temperature ?? DEFAULT_TEMPERATURE)
|
||||
setConextCount(assistant?.settings?.contextCount ?? DEFAULT_CONEXTCOUNT)
|
||||
}, [assistant])
|
||||
|
||||
return (
|
||||
|
||||
@@ -5,9 +5,10 @@ import { useAssistants } from '@renderer/hooks/useAssistant'
|
||||
import { getDefaultTopic } from '@renderer/services/assistant'
|
||||
import { Assistant } from '@renderer/types'
|
||||
import { droppableReorder, uuid } from '@renderer/utils'
|
||||
import { Dropdown, MenuProps } from 'antd'
|
||||
import { Dropdown } from 'antd'
|
||||
import { ItemType } from 'antd/es/menu/interface'
|
||||
import { last } from 'lodash'
|
||||
import { FC, useRef } from 'react'
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
|
||||
@@ -19,7 +20,6 @@ interface Props {
|
||||
|
||||
const Assistants: FC<Props> = ({ activeAssistant, setActiveAssistant, onCreateAssistant }) => {
|
||||
const { assistants, removeAssistant, updateAssistant, addAssistant, updateAssistants } = useAssistants()
|
||||
const targetAssistant = useRef<Assistant | null>(null)
|
||||
|
||||
const { t } = useTranslation()
|
||||
|
||||
@@ -29,26 +29,25 @@ const Assistants: FC<Props> = ({ activeAssistant, setActiveAssistant, onCreateAs
|
||||
removeAssistant(assistant.id)
|
||||
}
|
||||
|
||||
const items: MenuProps['items'] = [
|
||||
const getMenuItems = (assistant: Assistant) =>
|
||||
[
|
||||
{
|
||||
label: t('common.edit'),
|
||||
key: 'edit',
|
||||
icon: <EditOutlined />,
|
||||
async onClick() {
|
||||
if (targetAssistant.current) {
|
||||
const _assistant = await AssistantSettingPopup.show({ assistant: targetAssistant.current })
|
||||
const _assistant = await AssistantSettingPopup.show({ assistant })
|
||||
updateAssistant(_assistant)
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
label: t('common.duplicate'),
|
||||
key: 'duplicate',
|
||||
icon: <CopyOutlined />,
|
||||
async onClick() {
|
||||
const assistant: Assistant = { ...activeAssistant, id: uuid(), topics: [getDefaultTopic()] }
|
||||
addAssistant(assistant)
|
||||
setActiveAssistant(assistant)
|
||||
onClick: async () => {
|
||||
const _assistant: Assistant = { ...assistant, id: uuid(), topics: [getDefaultTopic()] }
|
||||
addAssistant(_assistant)
|
||||
setActiveAssistant(_assistant)
|
||||
}
|
||||
},
|
||||
{ type: 'divider' },
|
||||
@@ -57,11 +56,9 @@ const Assistants: FC<Props> = ({ activeAssistant, setActiveAssistant, onCreateAs
|
||||
key: 'delete',
|
||||
icon: <DeleteOutlined />,
|
||||
danger: true,
|
||||
onClick: () => {
|
||||
targetAssistant.current && onDelete(targetAssistant.current)
|
||||
onClick: () => onDelete(assistant)
|
||||
}
|
||||
}
|
||||
]
|
||||
] as ItemType[]
|
||||
|
||||
const onDragEnd = (result: DropResult) => {
|
||||
if (result.destination) {
|
||||
@@ -82,11 +79,7 @@ const Assistants: FC<Props> = ({ activeAssistant, setActiveAssistant, onCreateAs
|
||||
<Draggable key={`draggable_${assistant.id}_${index}`} draggableId={assistant.id} index={index}>
|
||||
{(provided) => (
|
||||
<div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
||||
<Dropdown
|
||||
key={assistant.id}
|
||||
menu={{ items }}
|
||||
trigger={['contextMenu']}
|
||||
onOpenChange={() => (targetAssistant.current = assistant)}>
|
||||
<Dropdown key={assistant.id} menu={{ items: getMenuItems(assistant) }} trigger={['contextMenu']}>
|
||||
<AssistantItem
|
||||
onClick={() => setActiveAssistant(assistant)}
|
||||
className={assistant.id === activeAssistant?.id ? 'active' : ''}>
|
||||
|
||||
@@ -65,7 +65,6 @@ const Messages: FC<Props> = ({ assistant, topic }) => {
|
||||
useEffect(() => {
|
||||
const unsubscribes = [
|
||||
EventEmitter.on(EVENT_NAMES.SEND_MESSAGE, async (msg: Message) => {
|
||||
console.debug({ assistant, provider, message: msg, topic })
|
||||
onSendMessage(msg)
|
||||
fetchChatCompletion({ assistant, messages: [...messages, msg], topic, onResponse: setLastMessage })
|
||||
}),
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useShowRightSidebar } from '@renderer/hooks/useStore'
|
||||
import { fetchMessagesSummary } from '@renderer/services/api'
|
||||
import { Assistant, Topic } from '@renderer/types'
|
||||
import { Button, Dropdown, MenuProps, Popconfirm } from 'antd'
|
||||
import { FC, useRef } from 'react'
|
||||
import { FC } from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { DeleteOutlined, EditOutlined, SignatureOutlined } from '@ant-design/icons'
|
||||
import LocalStorage from '@renderer/services/storage'
|
||||
@@ -21,22 +21,20 @@ interface Props {
|
||||
const Topics: FC<Props> = ({ assistant, activeTopic, setActiveTopic }) => {
|
||||
const { showRightSidebar } = useShowRightSidebar()
|
||||
const { removeTopic, updateTopic, removeAllTopics, updateTopics } = useAssistant(assistant.id)
|
||||
const currentTopic = useRef<Topic | null>(null)
|
||||
const { t } = useTranslation()
|
||||
|
||||
const topicMenuItems: MenuProps['items'] = [
|
||||
const getTopicMenuItems = (topic: Topic) => {
|
||||
const menus: MenuProps['items'] = [
|
||||
{
|
||||
label: t('assistant.topics.auto_rename'),
|
||||
key: 'auto-rename',
|
||||
icon: <SignatureOutlined />,
|
||||
async onClick() {
|
||||
if (currentTopic.current) {
|
||||
const messages = await LocalStorage.getTopicMessages(currentTopic.current.id)
|
||||
const messages = await LocalStorage.getTopicMessages(topic.id)
|
||||
if (messages.length >= 2) {
|
||||
const summaryText = await fetchMessagesSummary({ messages, assistant })
|
||||
if (summaryText) {
|
||||
updateTopic({ ...currentTopic.current, name: summaryText })
|
||||
}
|
||||
updateTopic({ ...topic, name: summaryText })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,31 +47,33 @@ const Topics: FC<Props> = ({ assistant, activeTopic, setActiveTopic }) => {
|
||||
const name = await PromptPopup.show({
|
||||
title: t('assistant.topics.edit.title'),
|
||||
message: t('assistant.topics.edit.placeholder'),
|
||||
defaultValue: currentTopic.current?.name || ''
|
||||
defaultValue: topic?.name || ''
|
||||
})
|
||||
if (name && currentTopic.current && currentTopic.current?.name !== name) {
|
||||
updateTopic({ ...currentTopic.current, name })
|
||||
if (name && topic?.name !== name) {
|
||||
updateTopic({ ...topic, name })
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
if (assistant.topics.length > 1) {
|
||||
topicMenuItems.push({ type: 'divider' })
|
||||
topicMenuItems.push({
|
||||
menus.push({ type: 'divider' })
|
||||
menus.push({
|
||||
label: t('common.delete'),
|
||||
danger: true,
|
||||
key: 'delete',
|
||||
icon: <DeleteOutlined />,
|
||||
onClick() {
|
||||
if (assistant.topics.length === 1) return
|
||||
currentTopic.current && removeTopic(currentTopic.current)
|
||||
currentTopic.current = null
|
||||
removeTopic(topic)
|
||||
setActiveTopic(assistant.topics[0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return menus
|
||||
}
|
||||
|
||||
const onDragEnd = (result: DropResult) => {
|
||||
if (result.destination) {
|
||||
const sourceIndex = result.source.index
|
||||
@@ -108,11 +108,7 @@ const Topics: FC<Props> = ({ assistant, activeTopic, setActiveTopic }) => {
|
||||
<Draggable key={`draggable_${topic.id}_${index}`} draggableId={topic.id} index={index}>
|
||||
{(provided) => (
|
||||
<div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
||||
<Dropdown
|
||||
menu={{ items: topicMenuItems }}
|
||||
trigger={['contextMenu']}
|
||||
key={topic.id}
|
||||
onOpenChange={(open) => open && (currentTopic.current = topic)}>
|
||||
<Dropdown menu={{ items: getTopicMenuItems(topic) }} trigger={['contextMenu']} key={topic.id}>
|
||||
<TopicListItem
|
||||
className={topic.id === activeTopic?.id ? 'active' : ''}
|
||||
onClick={() => setActiveTopic(topic)}>
|
||||
|
||||
@@ -47,7 +47,7 @@ export default class ProviderSDK {
|
||||
model: model.id,
|
||||
messages: [systemMessage, ...userMessages].filter(Boolean) as MessageParam[],
|
||||
max_tokens: 4096,
|
||||
temperature: assistant.settings?.temperature
|
||||
temperature: assistant?.settings?.temperature
|
||||
})
|
||||
.on('text', (text) => onChunk({ text: text || '' }))
|
||||
.on('finalMessage', (message) =>
|
||||
@@ -64,7 +64,7 @@ export default class ProviderSDK {
|
||||
model: model.id,
|
||||
messages: [systemMessage, ...userMessages].filter(Boolean) as ChatCompletionMessageParam[],
|
||||
stream: true,
|
||||
temperature: assistant.settings?.temperature
|
||||
temperature: assistant?.settings?.temperature
|
||||
})
|
||||
for await (const chunk of stream) {
|
||||
if (window.keyv.get(EVENT_NAMES.CHAT_COMPLETION_PAUSED)) break
|
||||
|
||||
@@ -169,10 +169,10 @@ export function getFirstCharacter(str) {
|
||||
}
|
||||
|
||||
export const getAssistantSettings = (assistant: Assistant): AssistantSettings => {
|
||||
const contextCount = assistant.settings?.contextCount ?? DEFAULT_CONEXTCOUNT
|
||||
const contextCount = assistant?.settings?.contextCount ?? DEFAULT_CONEXTCOUNT
|
||||
return {
|
||||
contextCount: contextCount === 20 ? 100000 : contextCount,
|
||||
temperature: assistant.settings?.temperature ?? DEFAULT_TEMPERATURE
|
||||
temperature: assistant?.settings?.temperature ?? DEFAULT_TEMPERATURE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user