added support for Anthropic and it is recommended

move code to work with AI from rest class to separate class
This commit is contained in:
Nikita 2024-12-27 14:31:22 +03:00
parent 1eda5f0e15
commit e67eca2ee0
14 changed files with 797 additions and 342 deletions

View file

@ -21,12 +21,38 @@ import { __ } from '@wordpress/i18n';
* Internal dependencies
*/
import isValidOpenAIApiKey from '../../utils/is-valid-openai-api-key';
import isValidAnthropicApiKey from '../../utils/is-valid-anthropic-api-key';
import { ReactComponent as LoadingIcon } from '../../icons/loading.svg';
const models = [
{
title: __('Claude 3.5 Sonnet', 'mind'),
name: 'claude-3-5-sonnet',
description: __('Best quality and recommended', 'mind'),
},
{
title: __('Claude 3.5 Haiku', 'mind'),
name: 'claude-3-5-haiku',
description: __('Fast and accurate', 'mind'),
},
{
title: __('GPT-4o', 'mind'),
name: 'gpt-4o',
description: __('Quick and reliable', 'mind'),
},
{
title: __('GPT-4o mini', 'mind'),
name: 'gpt-4o-mini',
description: __('Basic and fastest', 'mind'),
},
];
export default function PageSettings() {
const [pendingSettings, setPendingSettings] = useState({});
const [settingsChanged, setSettingsChanged] = useState(false);
const [isInvalidAPIKey, setIsInvalidAPIKey] = useState(false);
const [isInvalidAnthropicAPIKey, setIsInvalidAnthropicAPIKey] =
useState(false);
const [isInvalidOpenAIAPIKey, setIsInvalidOpenAIAPIKey] = useState(false);
const { updateSettings } = useDispatch('mind/settings');
@ -54,12 +80,118 @@ export default function PageSettings() {
<>
<div className="mind-admin-settings-card">
<div className="mind-admin-settings-card-name">
<label htmlFor="mind-settings-openai-api-key">
{__('OpenAI API Key', 'mind')}
<label htmlFor="mind-settings-ai-model">
{__('Model', 'mind')}
</label>
</div>
<div className="mind-admin-settings-card-button-group">
{models.map((model) => (
<button
key={model.title}
onClick={(e) => {
e.preventDefault();
setPendingSettings({
...pendingSettings,
ai_model: model.name,
});
}}
className={clsx(
'mind-admin-settings-card-button',
pendingSettings.ai_model === model.name &&
'mind-admin-settings-card-button-active'
)}
>
{model.title}
<span>{model.description}</span>
</button>
))}
</div>
</div>
{pendingSettings.ai_model?.includes('claude') && (
<div className="mind-admin-settings-card">
<div className="mind-admin-settings-card-name">
<label htmlFor="mind-settings-anthropic-api-key">
{__('Anthropic API Key', 'mind')}
</label>
</div>
<div
className={clsx(
'mind-admin-settings-card-input',
isInvalidAnthropicAPIKey &&
'mind-admin-settings-card-input-error'
)}
>
<input
id="mind-settings-anthropic-api-key"
type="text"
placeholder={__('Enter API key', 'mind')}
value={pendingSettings.anthropic_api_key || ''}
onChange={(e) => {
e.preventDefault();
setPendingSettings({
...pendingSettings,
anthropic_api_key: e.target.value,
});
}}
/>
{isInvalidAnthropicAPIKey && (
<div className="mind-admin-setting-error">
{__('Please enter a valid API key', 'mind')}
</div>
)}
</div>
<div className="mind-admin-settings-card-description">
{__(
'This setting is required, since our plugin works with OpenAI.',
'This setting is required to use Anthropic models.',
'mind'
)}{' '}
<a
href="https://console.anthropic.com/settings/keys"
target="_blank"
rel="noreferrer"
>
{__('Create API key', 'mind')}
</a>
</div>
</div>
)}
{pendingSettings.ai_model?.includes('gpt') && (
<div className="mind-admin-settings-card">
<div className="mind-admin-settings-card-name">
<label htmlFor="mind-settings-openai-api-key">
{__('OpenAI API Key', 'mind')}
</label>
</div>
<div
className={clsx(
'mind-admin-settings-card-input',
isInvalidOpenAIAPIKey &&
'mind-admin-settings-card-input-error'
)}
>
<input
id="mind-settings-openai-api-key"
type="text"
placeholder={__('Enter API key', 'mind')}
value={pendingSettings.openai_api_key || ''}
onChange={(e) => {
e.preventDefault();
setPendingSettings({
...pendingSettings,
openai_api_key: e.target.value,
});
}}
/>
{isInvalidOpenAIAPIKey && (
<div className="mind-admin-setting-error">
{__('Please enter a valid API key', 'mind')}
</div>
)}
</div>
<div className="mind-admin-settings-card-description">
{__(
'This setting is required to use OpenAI models.',
'mind'
)}{' '}
<a
@ -71,33 +203,8 @@ export default function PageSettings() {
</a>
</div>
</div>
<div
className={clsx(
'mind-admin-settings-card-input',
isInvalidAPIKey &&
'mind-admin-settings-card-input-error'
)}
>
<input
id="mind-settings-openai-api-key"
type="text"
placeholder={__('Enter API key', 'mind')}
value={pendingSettings.openai_api_key || ''}
onChange={(e) => {
e.preventDefault();
setPendingSettings({
...pendingSettings,
openai_api_key: e.target.value,
});
}}
/>
{isInvalidAPIKey && (
<div className="mind-admin-setting-error">
{__('Please enter a valid API key', 'mind')}
</div>
)}
</div>
</div>
)}
{error && <div className="mind-admin-settings-error">{error}</div>}
<div className="mind-admin-settings-actions">
<button
@ -105,14 +212,27 @@ export default function PageSettings() {
onClick={(e) => {
e.preventDefault();
// Check if Anthropic API key is valid.
if (
!pendingSettings.openai_api_key ||
isValidOpenAIApiKey(pendingSettings.openai_api_key)
pendingSettings.anthropic_api_key &&
!isValidAnthropicApiKey(
pendingSettings.anthropic_api_key
)
) {
setIsInvalidAPIKey(false);
updateSettings(pendingSettings);
setIsInvalidAnthropicAPIKey(true);
// Check if OpenAI API key is valid.
} else if (
pendingSettings.openai_api_key &&
!isValidOpenAIApiKey(pendingSettings.openai_api_key)
) {
setIsInvalidOpenAIAPIKey(true);
// Update settings.
} else {
setIsInvalidAPIKey(true);
setIsInvalidOpenAIAPIKey(false);
setIsInvalidAnthropicAPIKey(false);
updateSettings(pendingSettings);
}
}}
>