Skip to content

Commit

Permalink
Merge pull request #448 from l3vels/feat/settings-on-integrations
Browse files Browse the repository at this point in the history
Feat/settings on integrations
  • Loading branch information
Chkhikvadze authored Mar 5, 2024
2 parents 89859b0 + eee8c37 commit bbc246a
Show file tree
Hide file tree
Showing 21 changed files with 429 additions and 18 deletions.
4 changes: 1 addition & 3 deletions apps/server/agents/handle_agent_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ def handle_agent_error(err: Exception) -> str:
if isinstance(err, RateLimitError):
return "OpenAI reached it's rate limit, please check billing on OpenAI"
elif isinstance(err, AuthenticationError):
return (
"Your OpenAI API key is invalid. Please recheck it in [Settings](/settings)"
)
return "Your OpenAI API key is invalid. Please recheck it in [Settings](/integrations?setting=openai)"
elif isinstance(err, TimeoutError):
return "OpenAI timed out, please try again later"
elif isinstance(err, ServiceUnavailableError):
Expand Down
6 changes: 3 additions & 3 deletions apps/server/utils/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def get_llm(
if provider == ModelProviders.OPEN_AI:
if not settings.openai_api_key:
raise InvalidLLMApiKeyException(
"Please set OpenAI API Key in [Settings](/settings)"
"Please set OpenAI API Key in [Settings](/integrations?setting=openai)"
)

return ChatOpenAI(
Expand All @@ -134,7 +134,7 @@ def get_llm(
elif provider == ModelProviders.HUGGING_FACE:
if not settings.hugging_face_access_token:
raise InvalidLLMApiKeyException(
"Please set Hugging Face Access Token in [Settings](/settings)"
"Please set Hugging Face Access Token in [Settings](/integrations?setting=huggingface)"
)

return HuggingFaceHub(
Expand All @@ -147,7 +147,7 @@ def get_llm(
elif provider == ModelProviders.REPLICATE:
if not settings.replicate_api_token:
raise InvalidLLMApiKeyException(
"Please set Replicate API Token in [Settings](/settings)"
"Please set Replicate API Token in [Settings](/integrations?setting=replicate)"
)

os.environ["REPLICATE_API_TOKEN"] = settings.replicate_api_token
Expand Down
2 changes: 2 additions & 0 deletions apps/ui/src/Route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ import EditCampaignModal from 'modals/EditCampaignModal'
import CreateScheduleModal from 'modals/CreateScheduleModal'
import EditScheduleModal from 'modals/EditScheduleModal'
import VoiceOptionsModal from 'modals/VoiceOptionsModal'
import LlmSettingsModal from 'modals/LlmSettingsModal'

const Route = () => {
const { loading } = useContext(AuthContext)
Expand Down Expand Up @@ -432,6 +433,7 @@ const Route = () => {
<SettingsModal />
<ToolkitModal />
<VoiceModal />
<LlmSettingsModal />
<ChatLinkModal />
<ScheduleRunModal />
<RunLogsModal />
Expand Down
Binary file added apps/ui/src/assets/settings/hf-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/ui/src/assets/settings/openAi-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/ui/src/assets/settings/pinecone-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/ui/src/assets/settings/replicate-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/ui/src/assets/settings/weaviate-logo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 5 additions & 4 deletions apps/ui/src/components/HeaderButtons/HeaderButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const HeaderButtons = () => {
</Tooltip>
)}

<Tooltip
{/* <Tooltip
content={<span>{t('docs')}</span>}
position={Tooltip.positions.BOTTOM}
tooltipSize={Tooltip.tooltipSize.Small}
Expand All @@ -66,7 +66,7 @@ const HeaderButtons = () => {
/>
</StyledInnerButtonWrapper>
</ButtonTertiary>
</Tooltip>
</Tooltip> */}

{/* <Tooltip
content={() => <span>Twitter</span>}
Expand Down Expand Up @@ -101,7 +101,7 @@ const HeaderButtons = () => {
</ButtonTertiary>
</Tooltip> */}

{isLinkModule && (
{/* {isLinkModule && (
<Tooltip
content={<span>{t('github')}</span>}
position={Tooltip.positions.BOTTOM}
Expand All @@ -125,7 +125,7 @@ const HeaderButtons = () => {
</StyledInnerButtonWrapper>
</ButtonTertiary>
</Tooltip>
)}
)} */}
</StyledButtonsWrapper>
)
}
Expand All @@ -135,6 +135,7 @@ export default HeaderButtons
const StyledButtonsWrapper = styled.div`
display: flex;
align-items: center;
gap: 5px;
`
export const StyledImg = styled.img<{ customScale?: number }>`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import { atomDark } from 'react-syntax-highlighter/dist/esm/styles/prism'
import remarkGfm from 'remark-gfm'
import { useModal } from 'hooks'
import { memo } from 'react'
import { t } from 'i18next'

const YOUTUBE_REGEX = /^https:\/\/www\.youtube\.com\/watch\?v=([a-zA-Z0-9_-]+)&/
const IMAGE_REGEX = /\.(gif|jpe?g|tiff?|png|webp|bmp)$/i
const SETTINGS_REGEX = /\/setting/
// const SETTINGS_REGEX = /\/setting/
const TOOLKIT_REGEX = /\/toolkits\/[^/]+/
const VOICE_REGEX = /\/integrations\/voice\/[^/]+/
const SETTINGS_REGEX = /\/integrations\?setting=([^/]+)/
// const SETTINGS_REGEX = /\[Settings\]\(\/settings\)/

const AiMessageMarkdown = ({ isReply = false, children }: { isReply?: boolean; children: any }) => {
Expand Down Expand Up @@ -52,9 +54,17 @@ const AiMessageMarkdown = ({ isReply = false, children }: { isReply?: boolean; c
}

if (SETTINGS_REGEX.test(href as string)) {
const regex = /\/integrations\?setting=([^/]+)/
const match: any = regex.exec(href || '')
const slug = match[1]

return (
<button onClick={() => openModal({ name: 'settings-modal' })}>
<StyledText>Settings</StyledText>
<button
onClick={() =>
openModal({ name: 'llm-settings-modal', data: { settingsSlug: slug } })
}
>
<StyledText>here</StyledText>
</button>
)
}
Expand Down
35 changes: 35 additions & 0 deletions apps/ui/src/modals/LlmSettingsModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import withRenderModal from 'hocs/withRenderModal'

import Modal from 'share-ui/components/Modal/Modal'
import { useModal } from 'hooks'

import ToolView from 'pages/Toolkit/ToolView'
import { useToolView } from 'pages/Toolkit/ToolView/useToolView'
import { StyledModalBody } from './ToolkitModal'
import SettingView from 'pages/Settings/SettingView'

type LlmSettingsModalProps = {
data: {
settingsSlug: string
}
}

const LlmSettingsModal = ({ data }: LlmSettingsModalProps) => {
const { closeModal } = useModal()

const { configsData } = useToolView({})

if (!configsData) return <div />

return (
<>
<Modal onClose={() => closeModal('llm-settings-modal')} show backgroundColor='light'>
<StyledModalBody>
<SettingView settingSlug={data.settingsSlug} />
</StyledModalBody>
</Modal>
</>
)
}

export default withRenderModal('llm-settings-modal')(LlmSettingsModal)
62 changes: 60 additions & 2 deletions apps/ui/src/pages/Integrations/Integrations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ import ToolView from 'pages/Toolkit/ToolView'
import VoiceView from 'plugins/contact/pages/Voice/VoiceView'
import { useToolView } from 'pages/Toolkit/ToolView/useToolView'

import SettingView from 'pages/Settings/SettingView'
import { SETTINGS_FIELDS } from 'pages/Settings/SettingView/useSettingView'
import { settingLogos } from 'pages/Settings/constants'

const Integrations = () => {
const { getIntegrationModules } = useGetAccountModule()

Expand Down Expand Up @@ -63,6 +67,7 @@ const Integrations = () => {
const urlParams = new URLSearchParams(location.search)
const toolQuery = urlParams.get('tool') || ''
const voiceQuery = urlParams.get('voice') || ''
const settingQuery = urlParams.get('setting') || ''

const [activeTab, setActiveTab] = useState(0)
const handleTabClick = (tabId: number) => {
Expand All @@ -76,7 +81,8 @@ const Integrations = () => {
const { data: voiceTools } = useVoicesService()

useEffect(() => {
navigate(`/integrations?tool=${tools?.[0]?.slug}`)
if (!toolQuery && !voiceQuery && !settingQuery)
navigate(`/integrations?tool=${tools?.[0]?.slug}`)
}, [tools])

let isSettingsHidden = false
Expand All @@ -94,13 +100,19 @@ const Integrations = () => {

const handlePickTool = (slug: string) => {
navigate(`/integrations?tool=${slug}`)

setActiveTab(0)
}
const handlePickVoice = (slug: string) => {
navigate(`/integrations?voice=${slug}`)
setActiveTab(0)
}
const handlePickSetting = (slug: string) => {
navigate(`/integrations?setting=${slug}`)
setActiveTab(0)
}

const llmSettings = SETTINGS_FIELDS?.filter((setting: any) => setting.group === 'llm')
const vectorDbSettings = SETTINGS_FIELDS?.filter((setting: any) => setting.group === 'vectorDb')

return (
<>
Expand Down Expand Up @@ -149,6 +161,50 @@ const Integrations = () => {
/>
)
})}

<StyledHorizontalDivider />

<ListHeader title={`${t('LLM')}`} />

{llmSettings?.map((setting: any, index: number) => {
const filteredLogos = settingLogos.filter(
(toolLogo: any) => toolLogo.settingName === setting.title,
)

const logoSrc = filteredLogos?.[0]?.logoSrc || ''

return (
<MiniToolCard
key={index}
onClick={() => handlePickSetting(setting.slug)}
name={setting.title}
logo={logoSrc}
picked={settingQuery === setting.slug}
/>
)
})}

<StyledHorizontalDivider />

<ListHeader title={`${t('VectorDB')}`} />

{vectorDbSettings?.map((setting: any, index: number) => {
const filteredLogos = settingLogos.filter(
(toolLogo: any) => toolLogo.settingName === setting.title,
)

const logoSrc = filteredLogos?.[0]?.logoSrc || ''

return (
<MiniToolCard
key={index}
onClick={() => handlePickSetting(setting.slug)}
name={setting.title}
logo={logoSrc}
picked={settingQuery === setting.slug}
/>
)
})}
</StyledLeftColumn>

<StyledChatWrapper>
Expand All @@ -166,10 +222,12 @@ const Integrations = () => {
<TabPanel>
{toolQuery && <ToolView toolSlug={toolQuery} hideForm />}
{voiceQuery && <VoiceView voiceSlug={voiceQuery} hideForm />}
{settingQuery && <SettingView settingSlug={settingQuery} hideForm />}
</TabPanel>
<TabPanel>
{toolQuery && <ToolView toolSlug={toolQuery} hideInfo />}
{voiceQuery && <VoiceView voiceSlug={voiceQuery} hideInfo />}
{settingQuery && <SettingView settingSlug={settingQuery} hideInfo />}
</TabPanel>
</TabPanels>
</TabsContext>
Expand Down
113 changes: 113 additions & 0 deletions apps/ui/src/pages/Settings/SettingView/SettingView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import FormikTextField from 'components/TextFieldFormik'
import { SETTINGS_FIELDS, useSettingView } from './useSettingView'
import { FormikProvider } from 'formik'
import { StyledSectionWrapper } from 'pages/Home/homeStyle.css'
import {
StyledButtonWrapper,
StyledFieldsWrapper,
StyledImg,
StyledInnerWrapper,
StyledMainTextWrapper,
StyledTextWrapper,
} from 'pages/Toolkit/ToolView/ToolView'
import { ButtonPrimary } from 'components/Button/Button'
import Button from 'share-ui/components/Button/Button'
import Loader from 'share-ui/components/Loader/Loader'
import { t } from 'i18next'
import { settingLogos } from '../constants'
import TypographySecondary from 'components/Typography/Secondary'
import Typography from 'share-ui/components/typography/Typography'
import TypographyPrimary from 'components/Typography/Primary'
import { useModal } from 'hooks'

const SettingView = ({
settingSlug,
hideInfo,
hideForm,
}: {
settingSlug: string
hideInfo?: boolean
hideForm?: boolean
}) => {
const { closeModal } = useModal()

const fields = SETTINGS_FIELDS?.find((setting: any) => setting.slug === settingSlug)?.configs
const name = SETTINGS_FIELDS?.find((setting: any) => setting.slug === settingSlug)?.title
const { formik, isLoading, handleSubmit } = useSettingView({ fields })

const filteredLogos = settingLogos.find((setting: any) => setting.settingName === name)
const logoSrc = filteredLogos?.logoSrc || ''

const onHandleSubmit = async () => {
await handleSubmit(formik?.values)
closeModal('llm-settings-modal')
}
return (
<FormikProvider value={formik}>
<StyledSectionWrapper>
<StyledInnerWrapper>
{!hideInfo && (
<>
<StyledImg src={logoSrc} alt='' />
<StyledTextWrapper>
<TypographySecondary
value={t('by')}
type={Typography.types.LABEL}
size={Typography.sizes.xss}
/>

<TypographySecondary
value={t('l3')}
type={Typography.types.LABEL}
size={Typography.sizes.xss}
style={{ textDecoration: 'underline' }}
/>
</StyledTextWrapper>
<StyledMainTextWrapper>
<TypographyPrimary
value={name}
type={Typography.types.LABEL}
size={Typography.sizes.lg}
/>
{/* <TypographySecondary
value={description}
type={Typography.types.LABEL}
size={Typography.sizes.md}
/> */}
</StyledMainTextWrapper>
</>
)}

{!hideForm && (
<StyledFieldsWrapper>
{fields?.map((field: any) => {
return (
<FormikTextField
key={field.key}
name={field.key}
placeholder=''
label={field.label}
/>
)
})}
</StyledFieldsWrapper>
)}

{!hideForm && (
<StyledButtonWrapper>
<ButtonPrimary
onClick={onHandleSubmit}
disabled={isLoading}
size={Button.sizes?.MEDIUM}
>
{isLoading ? <Loader size={22} /> : t('save')}
</ButtonPrimary>
</StyledButtonWrapper>
)}
</StyledInnerWrapper>
</StyledSectionWrapper>
</FormikProvider>
)
}

export default SettingView
1 change: 1 addition & 0 deletions apps/ui/src/pages/Settings/SettingView/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './SettingView'
Loading

0 comments on commit bbc246a

Please sign in to comment.