mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-18 09:20:15 +01:00
feat(Google): Support all Text/Chat Models, Response streaming, PaLM -> Google 🤖 (#1316)
* feat: update PaLM icons * feat: add additional google models * POC: formatting inputs for Vertex AI streaming * refactor: move endpoints services outside of /routes dir to /services/Endpoints * refactor: shorten schemas import * refactor: rename PALM to GOOGLE * feat: make Google editable endpoint * feat: reusable Ask and Edit controllers based off Anthropic * chore: organize imports/logic * fix(parseConvo): include examples in googleSchema * fix: google only allows odd number of messages to be sent * fix: pass proxy to AnthropicClient * refactor: change `google` altName to `Google` * refactor: update getModelMaxTokens and related functions to handle maxTokensMap with nested endpoint model key/values * refactor: google Icon and response sender changes (Codey and Google logo instead of PaLM in all cases) * feat: google support for maxTokensMap * feat: google updated endpoints with Ask/Edit controllers, buildOptions, and initializeClient * feat(GoogleClient): now builds prompt for text models and supports real streaming from Vertex AI through langchain * chore(GoogleClient): remove comments, left before for reference in git history * docs: update google instructions (WIP) * docs(apis_and_tokens.md): add images to google instructions * docs: remove typo apis_and_tokens.md * Update apis_and_tokens.md * feat(Google): use default settings map, fully support context for both text and chat models, fully support examples for chat models * chore: update more PaLM references to Google * chore: move playwright out of workflows to avoid failing tests
This commit is contained in:
parent
8a1968b2f8
commit
583e978a82
90 changed files with 1613 additions and 784 deletions
|
|
@ -5,7 +5,7 @@ import {
|
|||
AnthropicIcon,
|
||||
AzureMinimalIcon,
|
||||
BingAIMinimalIcon,
|
||||
PaLMinimalIcon,
|
||||
GoogleMinimalIcon,
|
||||
LightningIcon,
|
||||
} from '~/components/svg';
|
||||
import { cn } from '~/utils';
|
||||
|
|
@ -16,7 +16,7 @@ export const icons = {
|
|||
[EModelEndpoint.gptPlugins]: MinimalPlugin,
|
||||
[EModelEndpoint.anthropic]: AnthropicIcon,
|
||||
[EModelEndpoint.chatGPTBrowser]: LightningIcon,
|
||||
[EModelEndpoint.google]: PaLMinimalIcon,
|
||||
[EModelEndpoint.google]: GoogleMinimalIcon,
|
||||
[EModelEndpoint.bingAI]: BingAIMinimalIcon,
|
||||
[EModelEndpoint.assistant]: ({ className = '' }) => (
|
||||
<svg
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { useRecoilState } from 'recoil';
|
|||
import { useGetEndpointsQuery } from 'librechat-data-provider';
|
||||
import { cn, defaultTextProps, removeFocusOutlines, mapEndpoints } from '~/utils';
|
||||
import { Input, Label, Dropdown, Dialog, DialogClose, DialogButton } from '~/components/';
|
||||
import PopoverButtons from '~/components/Endpoints/PopoverButtons';
|
||||
import PopoverButtons from '~/components/Chat/Input/PopoverButtons';
|
||||
import DialogTemplate from '~/components/ui/DialogTemplate';
|
||||
import { useSetIndexOptions, useLocalize } from '~/hooks';
|
||||
import { EndpointSettings } from '~/components/Endpoints';
|
||||
|
|
@ -90,6 +90,7 @@ const EditPresetDialog = ({
|
|||
conversation={preset}
|
||||
setOption={setOption}
|
||||
isPreset={true}
|
||||
isMultiChat={true}
|
||||
className="h-full md:mb-4 md:h-[440px]"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useRef } from 'react';
|
||||
import { useUpdateMessageMutation } from 'librechat-data-provider';
|
||||
import { useUpdateMessageMutation, EModelEndpoint } from 'librechat-data-provider';
|
||||
import Container from '~/components/Messages/Content/Container';
|
||||
import { useChatContext } from '~/Providers';
|
||||
import type { TEditProps } from '~/common';
|
||||
|
|
@ -18,6 +18,7 @@ const EditMessage = ({
|
|||
|
||||
const textEditor = useRef<HTMLDivElement | null>(null);
|
||||
const { conversationId, parentMessageId, messageId } = message;
|
||||
const { endpoint } = conversation ?? { endpoint: null };
|
||||
const updateMessageMutation = useUpdateMessageMutation(conversationId ?? '');
|
||||
const localize = useLocalize();
|
||||
|
||||
|
|
@ -94,7 +95,9 @@ const EditMessage = ({
|
|||
<div className="mt-2 flex w-full justify-center text-center">
|
||||
<button
|
||||
className="btn btn-primary relative mr-2"
|
||||
disabled={isSubmitting}
|
||||
disabled={
|
||||
isSubmitting || (endpoint === EModelEndpoint.google && !message.isCreatedByUser)
|
||||
}
|
||||
onClick={resubmitMessage}
|
||||
>
|
||||
{localize('com_ui_save')} {'&'} {localize('com_ui_submit')}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,18 @@
|
|||
import { EModelEndpoint } from 'librechat-data-provider';
|
||||
import { Plugin, GPTIcon, AnthropicIcon, AzureMinimalIcon } from '~/components/svg';
|
||||
import {
|
||||
Plugin,
|
||||
GPTIcon,
|
||||
AnthropicIcon,
|
||||
AzureMinimalIcon,
|
||||
PaLMIcon,
|
||||
CodeyIcon,
|
||||
} from '~/components/svg';
|
||||
import { useAuthContext } from '~/hooks/AuthContext';
|
||||
import { IconProps } from '~/common';
|
||||
import { cn } from '~/utils';
|
||||
|
||||
const Icon: React.FC<IconProps> = (props) => {
|
||||
const { size = 30, isCreatedByUser, button, model = true, endpoint, error, jailbreak } = props;
|
||||
const { size = 30, isCreatedByUser, button, model = '', endpoint, error, jailbreak } = props;
|
||||
|
||||
const { user } = useAuthContext();
|
||||
|
||||
|
|
@ -52,8 +59,12 @@ const Icon: React.FC<IconProps> = (props) => {
|
|||
name: 'Plugins',
|
||||
},
|
||||
[EModelEndpoint.google]: {
|
||||
icon: <img src="/assets/google-palm.svg" alt="Palm Icon" />,
|
||||
name: 'PaLM2',
|
||||
icon: model?.includes('code') ? (
|
||||
<CodeyIcon size={size * 0.75} />
|
||||
) : (
|
||||
<PaLMIcon size={size * 0.7} />
|
||||
),
|
||||
name: model?.includes('code') ? 'Codey' : 'PaLM2',
|
||||
},
|
||||
[EModelEndpoint.anthropic]: {
|
||||
icon: <AnthropicIcon size={size * 0.5555555555555556} />,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import {
|
|||
LightningIcon,
|
||||
PluginMinimalIcon,
|
||||
BingAIMinimalIcon,
|
||||
PaLMinimalIcon,
|
||||
GoogleMinimalIcon,
|
||||
AnthropicIcon,
|
||||
} from '~/components/svg';
|
||||
import { cn } from '~/utils';
|
||||
|
|
@ -27,7 +27,7 @@ const MinimalIcon: React.FC<IconProps> = (props) => {
|
|||
},
|
||||
[EModelEndpoint.openAI]: { icon: <OpenAIMinimalIcon />, name: props.chatGptLabel || 'ChatGPT' },
|
||||
[EModelEndpoint.gptPlugins]: { icon: <PluginMinimalIcon />, name: 'Plugins' },
|
||||
[EModelEndpoint.google]: { icon: <PaLMinimalIcon />, name: props.modelLabel || 'PaLM2' },
|
||||
[EModelEndpoint.google]: { icon: <GoogleMinimalIcon />, name: props.modelLabel || 'Google' },
|
||||
[EModelEndpoint.anthropic]: {
|
||||
icon: <AnthropicIcon className="icon-md shrink-0 dark:text-white" />,
|
||||
name: props.modelLabel || 'Claude',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import TextareaAutosize from 'react-textarea-autosize';
|
||||
import { EModelEndpoint, endpointSettings } from 'librechat-data-provider';
|
||||
import type { TModelSelectProps } from '~/common';
|
||||
import { ESide } from '~/common';
|
||||
import {
|
||||
|
|
@ -31,7 +32,8 @@ export default function Settings({ conversation, setOption, models, readonly }:
|
|||
const setTopK = setOption('topK');
|
||||
const setMaxOutputTokens = setOption('maxOutputTokens');
|
||||
|
||||
const codeChat = model?.startsWith('codechat-');
|
||||
const isTextModel = !model?.includes('chat') && /code|text/.test(model ?? '');
|
||||
const google = endpointSettings[EModelEndpoint.google];
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-5 gap-6">
|
||||
|
|
@ -46,45 +48,41 @@ export default function Settings({ conversation, setOption, models, readonly }:
|
|||
containerClassName="flex w-full resize-none"
|
||||
/>
|
||||
</div>
|
||||
{!codeChat && (
|
||||
<>
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<Label htmlFor="modelLabel" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_custom_name')}{' '}
|
||||
<small className="opacity-40">({localize('com_endpoint_default_blank')})</small>
|
||||
</Label>
|
||||
<Input
|
||||
id="modelLabel"
|
||||
disabled={readonly}
|
||||
value={modelLabel || ''}
|
||||
onChange={(e) => setModelLabel(e.target.value ?? null)}
|
||||
placeholder={localize('com_endpoint_google_custom_name_placeholder')}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex h-10 max-h-10 w-full resize-none px-3 py-2',
|
||||
removeFocusOutlines,
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<Label htmlFor="promptPrefix" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_prompt_prefix')}{' '}
|
||||
<small className="opacity-40">({localize('com_endpoint_default_blank')})</small>
|
||||
</Label>
|
||||
<TextareaAutosize
|
||||
id="promptPrefix"
|
||||
disabled={readonly}
|
||||
value={promptPrefix || ''}
|
||||
onChange={(e) => setPromptPrefix(e.target.value ?? null)}
|
||||
placeholder={localize('com_endpoint_prompt_prefix_placeholder')}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex max-h-[138px] min-h-[100px] w-full resize-none px-3 py-2 ',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<Label htmlFor="modelLabel" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_custom_name')}{' '}
|
||||
<small className="opacity-40">({localize('com_endpoint_default_blank')})</small>
|
||||
</Label>
|
||||
<Input
|
||||
id="modelLabel"
|
||||
disabled={readonly}
|
||||
value={modelLabel || ''}
|
||||
onChange={(e) => setModelLabel(e.target.value ?? null)}
|
||||
placeholder={localize('com_endpoint_google_custom_name_placeholder')}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex h-10 max-h-10 w-full resize-none px-3 py-2',
|
||||
removeFocusOutlines,
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<Label htmlFor="promptPrefix" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_prompt_prefix')}{' '}
|
||||
<small className="opacity-40">({localize('com_endpoint_default_blank')})</small>
|
||||
</Label>
|
||||
<TextareaAutosize
|
||||
id="promptPrefix"
|
||||
disabled={readonly}
|
||||
value={promptPrefix || ''}
|
||||
onChange={(e) => setPromptPrefix(e.target.value ?? null)}
|
||||
placeholder={localize('com_endpoint_prompt_prefix_placeholder')}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex max-h-[138px] min-h-[100px] w-full resize-none px-3 py-2 ',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-5 flex flex-col items-center justify-start gap-6 px-3 sm:col-span-2">
|
||||
<HoverCard openDelay={300}>
|
||||
|
|
@ -92,16 +90,18 @@ export default function Settings({ conversation, setOption, models, readonly }:
|
|||
<div className="flex justify-between">
|
||||
<Label htmlFor="temp-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_temperature')}{' '}
|
||||
<small className="opacity-40">({localize('com_endpoint_default')}: 0.2)</small>
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default')}: {google.temperature.default})
|
||||
</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="temp-int"
|
||||
disabled={readonly}
|
||||
value={temperature}
|
||||
onChange={(value) => setTemperature(value ?? 0.2)}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.01}
|
||||
onChange={(value) => setTemperature(value ?? google.temperature.default)}
|
||||
max={google.temperature.max}
|
||||
min={google.temperature.min}
|
||||
step={google.temperature.step}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
|
|
@ -114,18 +114,18 @@ export default function Settings({ conversation, setOption, models, readonly }:
|
|||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[temperature ?? 0.2]}
|
||||
value={[temperature ?? google.temperature.default]}
|
||||
onValueChange={(value) => setTemperature(value[0])}
|
||||
doubleClickHandler={() => setTemperature(0.2)}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.01}
|
||||
doubleClickHandler={() => setTemperature(google.temperature.default)}
|
||||
max={google.temperature.max}
|
||||
min={google.temperature.min}
|
||||
step={google.temperature.step}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover endpoint={conversation?.endpoint ?? ''} type="temp" side={ESide.Left} />
|
||||
</HoverCard>
|
||||
{!codeChat && (
|
||||
{!isTextModel && (
|
||||
<>
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
|
|
@ -133,17 +133,17 @@ export default function Settings({ conversation, setOption, models, readonly }:
|
|||
<Label htmlFor="top-p-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_top_p')}{' '}
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default_with_num', '0.95')})
|
||||
({localize('com_endpoint_default_with_num', google.topP.default + '')})
|
||||
</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="top-p-int"
|
||||
disabled={readonly}
|
||||
value={topP}
|
||||
onChange={(value) => setTopP(value ?? '0.95')}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.01}
|
||||
onChange={(value) => setTopP(value ?? google.topP.default)}
|
||||
max={google.topP.max}
|
||||
min={google.topP.min}
|
||||
step={google.topP.step}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
|
|
@ -156,12 +156,12 @@ export default function Settings({ conversation, setOption, models, readonly }:
|
|||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[topP ?? 0.95]}
|
||||
value={[topP ?? google.topP.default]}
|
||||
onValueChange={(value) => setTopP(value[0])}
|
||||
doubleClickHandler={() => setTopP(0.95)}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.01}
|
||||
doubleClickHandler={() => setTopP(google.topP.default)}
|
||||
max={google.topP.max}
|
||||
min={google.topP.min}
|
||||
step={google.topP.step}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
|
|
@ -174,17 +174,17 @@ export default function Settings({ conversation, setOption, models, readonly }:
|
|||
<Label htmlFor="top-k-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_top_k')}{' '}
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default_with_num', '40')})
|
||||
({localize('com_endpoint_default_with_num', google.topK.default + '')})
|
||||
</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="top-k-int"
|
||||
disabled={readonly}
|
||||
value={topK}
|
||||
onChange={(value) => setTopK(value ?? 40)}
|
||||
max={40}
|
||||
min={1}
|
||||
step={0.01}
|
||||
onChange={(value) => setTopK(value ?? google.topK.default)}
|
||||
max={google.topK.max}
|
||||
min={google.topK.min}
|
||||
step={google.topK.step}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
|
|
@ -197,12 +197,12 @@ export default function Settings({ conversation, setOption, models, readonly }:
|
|||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[topK ?? 40]}
|
||||
value={[topK ?? google.topK.default]}
|
||||
onValueChange={(value) => setTopK(value[0])}
|
||||
doubleClickHandler={() => setTopK(40)}
|
||||
max={40}
|
||||
min={1}
|
||||
step={0.01}
|
||||
doubleClickHandler={() => setTopK(google.topK.default)}
|
||||
max={google.topK.max}
|
||||
min={google.topK.min}
|
||||
step={google.topK.step}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
|
|
@ -216,17 +216,17 @@ export default function Settings({ conversation, setOption, models, readonly }:
|
|||
<Label htmlFor="max-tokens-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_max_output_tokens')}{' '}
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default_with_num', '1024')})
|
||||
({localize('com_endpoint_default_with_num', google.maxOutputTokens.default + '')})
|
||||
</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="max-tokens-int"
|
||||
disabled={readonly}
|
||||
value={maxOutputTokens}
|
||||
onChange={(value) => setMaxOutputTokens(value ?? 1024)}
|
||||
max={1024}
|
||||
min={1}
|
||||
step={1}
|
||||
onChange={(value) => setMaxOutputTokens(value ?? google.maxOutputTokens.default)}
|
||||
max={google.maxOutputTokens.max}
|
||||
min={google.maxOutputTokens.min}
|
||||
step={google.maxOutputTokens.step}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
|
|
@ -239,12 +239,12 @@ export default function Settings({ conversation, setOption, models, readonly }:
|
|||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[maxOutputTokens ?? 1024]}
|
||||
value={[maxOutputTokens ?? google.maxOutputTokens.default]}
|
||||
onValueChange={(value) => setMaxOutputTokens(value[0])}
|
||||
doubleClickHandler={() => setMaxOutputTokens(1024)}
|
||||
max={1024}
|
||||
min={1}
|
||||
step={1}
|
||||
doubleClickHandler={() => setMaxOutputTokens(google.maxOutputTokens.default)}
|
||||
max={google.maxOutputTokens.max}
|
||||
min={google.maxOutputTokens.min}
|
||||
step={google.maxOutputTokens.step}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export default function GoogleView({ conversation, models, isPreset = false }) {
|
|||
const { showExamples, isCodeChat } = optionSettings;
|
||||
return showExamples && !isCodeChat ? (
|
||||
<Examples
|
||||
examples={examples ?? []}
|
||||
examples={examples ?? [{ input: { content: '' }, output: { content: '' } }]}
|
||||
setExample={setExample}
|
||||
addExample={addExample}
|
||||
removeExample={removeExample}
|
||||
|
|
|
|||
26
client/src/components/svg/CodeyIcon.tsx
Normal file
26
client/src/components/svg/CodeyIcon.tsx
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import { cn } from '~/utils';
|
||||
export default function CodeyIcon({
|
||||
size = 25,
|
||||
className = '',
|
||||
}: {
|
||||
size?: number;
|
||||
className?: string;
|
||||
}) {
|
||||
return (
|
||||
<svg
|
||||
// width="100%"
|
||||
// height="100%"
|
||||
width={size}
|
||||
height={size}
|
||||
className={cn('dark:fill-white', className)}
|
||||
viewBox="0 0 18 18"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
focusable="false"
|
||||
>
|
||||
<path
|
||||
d="M2 4.006C2 2.898 2.897 2 4.006 2h9.988C15.102 2 16 2.897 16 4.006v9.988A2.005 2.005 0 0 1 13.994 16H4.006A2.005 2.005 0 0 1 2 13.994V4.006zM13.992 9l.003-.003L10.997 6 9.75 7.247 11.503 9 9.75 10.753 10.997 12l2.997-2.997L13.992 9zm-9.99 0L4 8.997 6.997 6l1.247 1.247L6.492 9l1.753 1.753L6.997 12 4 9.003 4.003 9z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
15
client/src/components/svg/GoogleMinimalIcon.tsx
Normal file
15
client/src/components/svg/GoogleMinimalIcon.tsx
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import { cn } from '~/utils';
|
||||
export default function GoogleMinimalIcon({ className = '' }: { className?: string }) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="currentColor"
|
||||
width="800px"
|
||||
height="800px"
|
||||
viewBox="0 0 512 512"
|
||||
className={cn('h-4 w-4', className)}
|
||||
>
|
||||
<path d="M473.16,221.48l-2.26-9.59H262.46v88.22H387c-12.93,61.4-72.93,93.72-121.94,93.72-35.66,0-73.25-15-98.13-39.11a140.08,140.08,0,0,1-41.8-98.88c0-37.16,16.7-74.33,41-98.78s61-38.13,97.49-38.13c41.79,0,71.74,22.19,82.94,32.31l62.69-62.36C390.86,72.72,340.34,32,261.6,32h0c-60.75,0-119,23.27-161.58,65.71C58,139.5,36.25,199.93,36.25,256S56.83,369.48,97.55,411.6C141.06,456.52,202.68,480,266.13,480c57.73,0,112.45-22.62,151.45-63.66,38.34-40.4,58.17-96.3,58.17-154.9C475.75,236.77,473.27,222.12,473.16,221.48Z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
50
client/src/components/svg/PaLMIcon.tsx
Normal file
50
client/src/components/svg/PaLMIcon.tsx
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
export default function PaLMIcon({
|
||||
size = 25,
|
||||
className = '',
|
||||
}: {
|
||||
size?: number;
|
||||
className?: string;
|
||||
}) {
|
||||
return (
|
||||
<svg
|
||||
// width="100%"
|
||||
// height="100%"
|
||||
width={size}
|
||||
height={size}
|
||||
className={className}
|
||||
viewBox="0 0 19 17"
|
||||
fill="none"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
focusable="false"
|
||||
>
|
||||
<path
|
||||
d="M9.62674 16.2202H9.7049C10.4225 16.2202 11.0016 15.6412 11.0016 14.9236V4.04224H8.33008V14.92C8.33008 15.6376 8.90914 16.2202 9.62674 16.2202Z"
|
||||
fill="#F9AB00"
|
||||
/>
|
||||
<path
|
||||
d="M14.6819 8.02813C13.3249 6.66752 11.2964 6.39398 9.66577 7.2004L15.0585 12.5931C15.2823 12.8169 15.6624 12.7281 15.7583 12.4297C16.2308 10.927 15.8756 9.21822 14.6819 8.02813Z"
|
||||
fill="#5BB974"
|
||||
/>
|
||||
<path
|
||||
d="M4.64953 8.02813C6.00659 6.66752 8.03507 6.39398 9.66567 7.2004L4.27297 12.5931C4.04916 12.8169 3.66904 12.7281 3.57312 12.4297C3.10064 10.927 3.45589 9.21822 4.64953 8.02813Z"
|
||||
fill="#129EAF"
|
||||
/>
|
||||
<path
|
||||
d="M14.284 3.84326C12.1383 3.84326 10.3159 5.25005 9.66577 7.20038H18.1918C18.5399 7.20038 18.7744 6.83092 18.6145 6.5183C17.8081 4.93033 16.1704 3.84326 14.284 3.84326Z"
|
||||
fill="#AF5CF7"
|
||||
/>
|
||||
<path
|
||||
d="M10.5574 1.55901C9.04053 3.07593 8.74567 5.36019 9.66577 7.20039L15.6944 1.17179C15.943 0.923113 15.8436 0.496814 15.5132 0.390239C13.8151 -0.1604 11.8896 0.226822 10.5574 1.55901Z"
|
||||
fill="#FF8BCB"
|
||||
/>
|
||||
<path
|
||||
d="M8.77408 1.55901C10.291 3.07593 10.5859 5.36019 9.66576 7.20039L3.63716 1.17179C3.38848 0.923113 3.48795 0.496814 3.81833 0.390239C5.51643 -0.1604 7.44189 0.226822 8.77408 1.55901Z"
|
||||
fill="#FA7B17"
|
||||
/>
|
||||
<path
|
||||
d="M5.04752 3.84326C7.19323 3.84326 9.01566 5.25005 9.66577 7.20038H1.13976C0.791616 7.20038 0.55715 6.83092 0.717013 6.5183C1.52343 4.93033 3.16114 3.84326 5.04752 3.84326Z"
|
||||
fill="#4285F4"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
import React from 'react';
|
||||
|
||||
export default function PaLMinimalIcon() {
|
||||
import { cn } from '~/utils';
|
||||
export default function PaLMinimalIcon({ className = '' }: { className?: string }) {
|
||||
return (
|
||||
<svg
|
||||
stroke="currentColor"
|
||||
|
|
@ -9,7 +8,7 @@ export default function PaLMinimalIcon() {
|
|||
viewBox="0 0 32 32"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="h-4 w-4"
|
||||
className={cn('h-4 w-4', className)}
|
||||
height="1em"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
|
|||
|
|
@ -34,5 +34,8 @@ export { default as ChatGPTMinimalIcon } from './ChatGPTMinimalIcon';
|
|||
export { default as PluginMinimalIcon } from './PluginMinimalIcon';
|
||||
export { default as BingAIMinimalIcon } from './BingAIMinimalIcon';
|
||||
export { default as PaLMinimalIcon } from './PaLMinimalIcon';
|
||||
export { default as PaLMIcon } from './PaLMIcon';
|
||||
export { default as CodeyIcon } from './CodeyIcon';
|
||||
export { default as GoogleMinimalIcon } from './GoogleMinimalIcon';
|
||||
export { default as AnthropicMinimalIcon } from './AnthropicMinimalIcon';
|
||||
export { default as SendMessageIcon } from './SendMessageIcon';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue