Skip to content

Commit

Permalink
feat: add ollama settings
Browse files Browse the repository at this point in the history
  • Loading branch information
kangfenmao committed Aug 6, 2024
1 parent 1679889 commit 5edb53e
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 15 deletions.
3 changes: 3 additions & 0 deletions src/renderer/src/components/TopView/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useAppInit } from '@renderer/hooks/useAppInit'
import { message, Modal } from 'antd'
import React, { PropsWithChildren, useCallback, useEffect, useRef, useState } from 'react'

Expand Down Expand Up @@ -30,6 +31,8 @@ const TopViewContainer: React.FC<Props> = ({ children }) => {
const [messageApi, messageContextHolder] = message.useMessage()
const [modal, modalContextHolder] = Modal.useModal()

useAppInit()

useEffect(() => {
window.message = messageApi
window.modal = modal
Expand Down
18 changes: 18 additions & 0 deletions src/renderer/src/hooks/useOllama.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import store, { useAppSelector } from '@renderer/store'
import { setOllamaKeepAliveTime } from '@renderer/store/llm'
import { useDispatch } from 'react-redux'

export function useOllamaSettings() {
const settings = useAppSelector((state) => state.llm.settings.ollama)
const dispatch = useDispatch()

return { ...settings, setKeepAliveTime: (time: number) => dispatch(setOllamaKeepAliveTime(time)) }
}

export function getOllamaSettings() {
return store.getState().llm.settings.ollama
}

export function getOllamaKeepAliveTime() {
return store.getState().llm.settings.ollama.keepAliveTime + 'm'
}
6 changes: 2 additions & 4 deletions src/renderer/src/hooks/useTopic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ import { Assistant, Topic } from '@renderer/types'
import { find } from 'lodash'
import { useEffect, useState } from 'react'

const activeTopicsMap = new Map<string, Topic>()
let _activeTopic: Topic

export function useActiveTopic(assistant: Assistant) {
const [activeTopic, setActiveTopic] = useState(activeTopicsMap.get(assistant.id) || assistant?.topics[0])

activeTopicsMap.set(assistant.id, activeTopic)
const [activeTopic, setActiveTopic] = useState(_activeTopic || assistant?.topics[0])

useEffect(() => {
// activeTopic not in assistant.topics
Expand Down
12 changes: 12 additions & 0 deletions src/renderer/src/i18n/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,12 @@ const resources = {
italian: 'Italian',
portuguese: 'Portuguese',
arabic: 'Arabic'
},
ollama: {
title: 'Ollama',
'keep_alive_time.title': 'Keep Alive Time',
'keep_alive_time.placeholder': 'Minutes',
'keep_alive_time.description': 'The time in minutes to keep the connection alive, default is 5 minutes.'
}
}
},
Expand Down Expand Up @@ -393,6 +399,12 @@ const resources = {
italian: '意大利文',
portuguese: '葡萄牙文',
arabic: '阿拉伯文'
},
ollama: {
title: 'Ollama',
'keep_alive_time.title': '保持活跃时间',
'keep_alive_time.placeholder': '分钟',
'keep_alive_time.description': '对话后模型在内存中保持的时间(默认:5分钟)'
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const SelectModelDropdown: FC<Props & PropsWithChildren> = ({ children, model, o
menu={{ items, style: { maxHeight: '80vh', overflow: 'auto' } }}
trigger={['click']}
arrow
placement="bottomCenter"
placement="bottom"
overlayClassName="chat-nav-dropdown"
{...props}>
{children}
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/src/pages/home/components/input/Inputbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ const Inputbar: FC<Props> = ({ assistant, setActiveTopic }) => {
<Tag style={{ cursor: 'pointer' }}>{assistant?.settings?.contextCount ?? DEFAULT_CONEXTCOUNT}</Tag>
</Tooltip>
<Tooltip title={t('chat.input.estimated_tokens.tip')}>
<Tag style={{ cursor: 'pointer' }}>{`${inputTokenCount} / ${estimateTokenCount}`}</Tag>
<Tag style={{ cursor: 'pointer' }}> {`${inputTokenCount} / ${estimateTokenCount}`}</Tag>
</Tooltip>
</TextCount>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { FC, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'

import OllamSettings from '../providers/OllamaSettings'
import { SettingContainer, SettingSubtitle, SettingTitle } from '.'
import AddModelPopup from './AddModelPopup'
import EditModelsPopup from './EditModelsPopup'
Expand Down Expand Up @@ -126,6 +127,7 @@ const ProviderSetting: FC<Props> = ({ provider: _provider }) => {
/>
{apiEditable && <Button onClick={onReset}>{t('settings.provider.api.url.reset')}</Button>}
</Space.Compact>
{provider.id === 'ollama' && <OllamSettings />}
<SettingSubtitle>{t('common.models')}</SettingSubtitle>
{Object.keys(modelGroups).map((group) => (
<Card key={group} type="inner" title={group} style={{ marginBottom: '10px' }} size="small">
Expand Down Expand Up @@ -182,14 +184,14 @@ const ModelListHeader = styled.div`
align-items: center;
`

const HelpTextRow = styled.div`
export const HelpTextRow = styled.div`
display: flex;
flex-direction: row;
align-items: center;
padding: 5px 0;
`

const HelpText = styled.div`
export const HelpText = styled.div`
font-size: 11px;
color: var(--color-text);
opacity: 0.4;
Expand Down
35 changes: 35 additions & 0 deletions src/renderer/src/pages/settings/providers/OllamaSettings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { useOllamaSettings } from '@renderer/hooks/useOllama'
import { InputNumber } from 'antd'
import { FC, useState } from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'

import { SettingSubtitle } from '../components'
import { HelpText, HelpTextRow } from '../components/ProviderSetting'

const OllamSettings: FC = () => {
const { keepAliveTime, setKeepAliveTime } = useOllamaSettings()
const [keepAliveMinutes, setKeepAliveMinutes] = useState(keepAliveTime)
const { t } = useTranslation()

return (
<Container>
<SettingSubtitle>{t('ollama.keep_alive_time.title')}</SettingSubtitle>
<InputNumber
style={{ width: '100%' }}
value={keepAliveMinutes}
onChange={(e) => setKeepAliveMinutes(Number(e))}
onBlur={() => setKeepAliveTime(keepAliveMinutes)}
suffix={t('ollama.keep_alive_time.placeholder')}
step={5}
/>
<HelpTextRow>
<HelpText>{t('ollama.keep_alive_time.description')}</HelpText>
</HelpTextRow>
</Container>
)
}

const Container = styled.div``

export default OllamSettings
17 changes: 14 additions & 3 deletions src/renderer/src/services/ProviderSDK.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Anthropic from '@anthropic-ai/sdk'
import { MessageCreateParamsNonStreaming, MessageParam } from '@anthropic-ai/sdk/resources'
import { getOllamaKeepAliveTime } from '@renderer/hooks/useOllama'
import { Assistant, Message, Provider, Suggestion } from '@renderer/types'
import { getAssistantSettings, removeQuotes } from '@renderer/utils'
import { sum, takeRight } from 'lodash'
Expand All @@ -26,6 +27,10 @@ export default class ProviderSDK {
return this.provider.id === 'anthropic'
}

private get keepAliveTime() {
return this.provider.id === 'ollama' ? getOllamaKeepAliveTime() : undefined
}

public async completions(
messages: Message[],
assistant: Assistant,
Expand Down Expand Up @@ -61,11 +66,13 @@ export default class ProviderSDK {
})
)
} else {
// @ts-ignore key is not typed
const stream = await this.openaiSdk.chat.completions.create({
model: model.id,
messages: [systemMessage, ...userMessages].filter(Boolean) as ChatCompletionMessageParam[],
stream: true,
temperature: assistant?.settings?.temperature
temperature: assistant?.settings?.temperature,
keep_alive: this.keepAliveTime
})
for await (const chunk of stream) {
if (window.keyv.get(EVENT_NAMES.CHAT_COMPLETION_PAUSED)) break
Expand All @@ -92,10 +99,12 @@ export default class ProviderSDK {
})
return response.content[0].type === 'text' ? response.content[0].text : ''
} else {
// @ts-ignore key is not typed
const response = await this.openaiSdk.chat.completions.create({
model: model.id,
messages: messages as ChatCompletionMessageParam[],
stream: false
stream: false,
keep_alive: this.keepAliveTime
})
return response.choices[0].message?.content || ''
}
Expand Down Expand Up @@ -124,11 +133,13 @@ export default class ProviderSDK {

return message.content[0].type === 'text' ? message.content[0].text : null
} else {
// @ts-ignore key is not typed
const response = await this.openaiSdk.chat.completions.create({
model: model.id,
messages: [systemMessage, ...userMessages] as ChatCompletionMessageParam[],
stream: false,
max_tokens: 50
max_tokens: 50,
keep_alive: this.keepAliveTime
})

return removeQuotes(response.choices[0].message?.content || '')
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/src/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const persistedReducer = persistReducer(
{
key: 'cherry-studio',
storage,
version: 18,
version: 19,
blacklist: ['runtime'],
migrate
},
Expand Down
20 changes: 18 additions & 2 deletions src/renderer/src/store/llm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@ import { SYSTEM_MODELS } from '@renderer/config/models'
import { Model, Provider } from '@renderer/types'
import { uniqBy } from 'lodash'

type LlmSettings = {
ollama: {
keepAliveTime: number
}
}

export interface LlmState {
providers: Provider[]
defaultModel: Model
topicNamingModel: Model
translateModel: Model
settings: LlmSettings
}

const initialState: LlmState = {
Expand Down Expand Up @@ -132,7 +139,12 @@ const initialState: LlmState = {
isSystem: true,
enabled: false
}
]
],
settings: {
ollama: {
keepAliveTime: 0
}
}
}

const settingsSlice = createSlice({
Expand Down Expand Up @@ -179,6 +191,9 @@ const settingsSlice = createSlice({
},
setTranslateModel: (state, action: PayloadAction<{ model: Model }>) => {
state.translateModel = action.payload.model
},
setOllamaKeepAliveTime: (state, action: PayloadAction<number>) => {
state.settings.ollama.keepAliveTime = action.payload
}
}
})
Expand All @@ -192,7 +207,8 @@ export const {
removeModel,
setDefaultModel,
setTopicNamingModel,
setTranslateModel
setTranslateModel,
setOllamaKeepAliveTime
} = settingsSlice.actions

export default settingsSlice.reducer
10 changes: 9 additions & 1 deletion src/renderer/src/store/migrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,11 +272,19 @@ const migrateConfig = {
}
}
},
'18': (state: RootState) => {
'19': (state: RootState) => {
return {
...state,
agents: {
agents: []
},
llm: {
...state.llm,
settings: {
ollama: {
keepAliveTime: 5
}
}
}
}
}
Expand Down

0 comments on commit 5edb53e

Please sign in to comment.