Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ai][assistant] Create package for logos and other static information for AI Assistant #203191

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,9 @@ x-pack/examples/third_party_vis_lens_example @elastic/kibana-visualizations
x-pack/examples/triggers_actions_ui_example @elastic/response-ops
x-pack/examples/ui_actions_enhanced_examples @elastic/appex-sharedux
x-pack/packages/ai-infra/product-doc-artifact-builder @elastic/appex-ai-infra
x-pack/packages/ai/service_providers @elastic/appex-ai-infra
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If @elastic/appex-ai-infra is really supposed to be the owner of those new packages, then please create any ai-infra plugin / package in their new home (see #202410):

  • x-pack/platform/plugins/shared/ai_infra/
  • x-pack/platform/packages/shared/ai-infra/

(Also we don't do nested-nested package in that team, so ai/service_providers will have to get flat)

If that's supposed to be shared ownership, then we probably want something like x-pack/platform/packages/shared/gen-ai/* or similar?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(note: the core team added to the repo the script they are using to move packages around, which should significantly reduce the burden of moving those packages where they should belong)

x-pack/packages/kbn-ai-assistant @elastic/search-kibana
x-pack/packages/kbn-ai-assistant/packages/service_providers @elastic/appex-ai-infra
x-pack/packages/kbn-alerting-comparators @elastic/response-ops
x-pack/packages/kbn-alerting-state-types @elastic/response-ops
x-pack/packages/kbn-random-sampling @elastic/kibana-visualizations
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@
"@kbn/ai-assistant-common": "link:x-pack/platform/packages/shared/ai-assistant/common",
"@kbn/ai-assistant-icon": "link:x-pack/platform/packages/shared/ai-assistant/icon",
"@kbn/ai-assistant-management-plugin": "link:src/platform/plugins/shared/ai_assistant_management/selection",
"@kbn/ai-assistant-service-providers": "link:x-pack/packages/kbn-ai-assistant/packages/service_providers",
"@kbn/ai-service-providers": "link:x-pack/packages/ai/service_providers",
"@kbn/aiops-change-point-detection": "link:x-pack/platform/packages/private/ml/aiops_change_point_detection",
"@kbn/aiops-common": "link:x-pack/platform/packages/shared/ml/aiops_common",
"@kbn/aiops-components": "link:x-pack/platform/packages/private/ml/aiops_components",
Expand Down
4 changes: 4 additions & 0 deletions tsconfig.base.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
"@kbn/ai-assistant-icon/*": ["x-pack/platform/packages/shared/ai-assistant/icon/*"],
"@kbn/ai-assistant-management-plugin": ["src/platform/plugins/shared/ai_assistant_management/selection"],
"@kbn/ai-assistant-management-plugin/*": ["src/platform/plugins/shared/ai_assistant_management/selection/*"],
"@kbn/ai-assistant-service-providers": ["x-pack/packages/kbn-ai-assistant/packages/service_providers"],
"@kbn/ai-assistant-service-providers/*": ["x-pack/packages/kbn-ai-assistant/packages/service_providers/*"],
"@kbn/ai-service-providers": ["x-pack/packages/ai/service_providers"],
"@kbn/ai-service-providers/*": ["x-pack/packages/ai/service_providers/*"],
"@kbn/aiops-change-point-detection": ["x-pack/platform/packages/private/ml/aiops_change_point_detection"],
"@kbn/aiops-change-point-detection/*": ["x-pack/platform/packages/private/ml/aiops_change_point_detection/*"],
"@kbn/aiops-common": ["x-pack/platform/packages/shared/ml/aiops_common"],
Expand Down
46 changes: 46 additions & 0 deletions x-pack/packages/ai/service_providers/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# @kbn/ai-service-providers

This package contains static information about AI service providers that can be used in Kibana:

- IDs
- Names
- Logos
- Connector types
- Supported solutions

## Logos

Logos for each Service Provider are stored in the `logos` directory of the package. They can be imported directly for static imports:

```ts
import GeminiLogoSVG from '@kbn/ai-service-providers/logos/gemini.svg';
import GeminiLogoComponent from '@kbn/ai-service-providers/logos/gemini';
```

They can also be loaded asynchronously, in one of three formats:

```tsx
// Returns a lazily-loaded logo as a React component, already wrapped in a Suspense boundary.
const Gemini = getReactComponentLogo('gemini');

return (
<div><Logo /></div>
);
Comment on lines +24 to +28
Copy link
Contributor

@pgayvallet pgayvallet Dec 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the PR is going into the right direction, but I have concerns mixing things that are shared between browser and server (e.g service Id, service name and so on) and things that are strictly going to be used browser-side, suchs as SVG assets. This seems like an architectural smell to me?

(Unless this package is meant to only be used browser-side, in which case that argument is obviously invalid)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can split them, make the constants and service names in a common package, and the svgs and components in a browser package?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm aware how painful it is to create dozens of mini packages, and I usually try to not force it when not strictly necessary, but in that case (given we have webpack-loader type of imports, that are just not supported on the server), I think that would make sense?


// Returns a base64-encoded logo as a string.
const gemini = await getBase64Logo('gemini');

return <EuiIcon type={gemini} />;

// Returns a logo as a URL to a static asset.
// This means the logo *will not* respond to dark mode changes.
const gemini = await getUrlLogo('gemini');

return <EuiIcon type={gemini} />;
```

## Note

This package is an extraction of information from `@kbn/stack-connectors-plugin` relevant to `@kbn/ai-assistant`. It is intended to be used by the AI Assistant to display a list of available AI service providers to the user.

We can move more or all of this information from `@kbn/stack-connectors-plugin` to this package, if others agree that a centralized location for this information is prudent.
24 changes: 24 additions & 0 deletions x-pack/packages/ai/service_providers/connector_id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { ServiceProviderID } from './id';

// There are more service providers and connector types in @kbn/stack-connectors-plugin,
// but until we know which other logos or properties we'd like to migrate, we're only
// including those currently in use by the AI Assistant.
export const SERVICE_PROVIDER_CONNECTOR_IDS: Record<ServiceProviderID, string> = {
bedrock: '.bedrock',
openai: '.gen-ai',
gemini: '.gemini',
};

/**
* Returns true if the given string is a supported connector type, false otherwise.
* @param id The connector type ID to check.
*/
export const isSupportedConnectorId = (id: string) =>
Object.values(SERVICE_PROVIDER_CONNECTOR_IDS).includes(id);
36 changes: 36 additions & 0 deletions x-pack/packages/ai/service_providers/id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

/**
* Available AI Service Provider IDs.
*/
export type ServiceProviderID = (typeof SERVICE_PROVIDER_IDS)[number];

// There are more service providers in @kbn/stack-connectors-plugin, but until
// we know which other logos or properties we'd like to migrate, we're only
// including those currently in use by the AI Assistant.

/**
* Available AI Service Provider IDs.
*/
export const SERVICE_PROVIDER_IDS = [
// 'alibabacloud-ai-search',
'bedrock',
// 'anthropic',
// 'azureopenai',
// 'azureaistudio',
// 'cohere',
// 'elasticsearch',
// 'elser',
'gemini',
// 'googleaistudio',
// 'googlevertexai',
// 'hugging_face',
// 'mistral',
'openai',
// 'watsonxai',
] as const;
74 changes: 74 additions & 0 deletions x-pack/packages/ai/service_providers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

export { type ServiceProviderID, SERVICE_PROVIDER_IDS } from './id';
export { getReactComponentLogo, getBase64Logo, getUrlLogo } from './logo';
export type { ProviderSolution } from './solutions';

import { SERVICE_PROVIDER_CONNECTOR_IDS } from './connector_id';
import { type ServiceProviderID, SERVICE_PROVIDER_IDS } from './id';
import { SERVICE_PROVIDER_NAMES } from './name';
import { type ProviderSolution, SERVICE_PROVIDER_SOLUTIONS } from './solutions';

/**
* An AI Service Provider available to used in Kibana.
*/
export interface ServiceProvider {
/** The ID of the provider. */
id: ServiceProviderID;
/** A display name for the provider. */
name: string;
/** Solutions in which the provider can be used. */
solutions: readonly ProviderSolution[];
/** The connector type ID of the provider. */
connectorId: string;
}

/**
* A static map of all AI Service Providers available for use in Kibana.
*/
export const SERVICE_PROVIDERS = SERVICE_PROVIDER_IDS.reduce((acc, id) => {
acc[id] = {
id,
name: SERVICE_PROVIDER_NAMES[id],
solutions: SERVICE_PROVIDER_SOLUTIONS[id],
connectorId: SERVICE_PROVIDER_CONNECTOR_IDS[id],
};

return acc;
}, {} as Record<ServiceProviderID, ServiceProvider>);

export const {
/** Amazon Bedrock */
bedrock,
/** Google Gemini */
gemini,
/** Open AI */
openai,
} = SERVICE_PROVIDERS;

/**
* Return all Service Provider IDs.
*/
export const getServiceProviderIds = () => SERVICE_PROVIDER_IDS;

/**
* Return all Service Providers, mapped by ID.
*/
export const getServiceProviders = () => SERVICE_PROVIDERS;

/**
* Return a Service Provider by ID.
* @param id The ID of the Service Provider.
*/
export const getServiceProvider = (id: ServiceProviderID) => SERVICE_PROVIDERS[id];

/**
* Returns true if the given string is a supported connector type, false otherwise.
* @param id The connector type ID to check.
*/
export { isSupportedConnectorId } from './connector_id';
12 changes: 12 additions & 0 deletions x-pack/packages/ai/service_providers/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

module.exports = {
preset: '@kbn/test',
rootDir: '../../../..',
roots: ['<rootDir>/x-pack/packages/ai/service_providers'],
};
6 changes: 6 additions & 0 deletions x-pack/packages/ai/service_providers/kibana.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"type": "shared-common",
"id": "@kbn/ai-service-providers",
"owner": "@elastic/appex-ai-infra",
"visibility": "shared"
}
13 changes: 13 additions & 0 deletions x-pack/packages/ai/service_providers/logo/bedrock.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import React from 'react';
import { LogoProps } from '../types';

const Logo = (props: LogoProps) => (
const Bedrock = (props: React.SVGProps<SVGSVGElement>) => (
<svg
{...props}
width="64"
Expand All @@ -26,4 +24,4 @@ const Logo = (props: LogoProps) => (
);

// eslint-disable-next-line import/no-default-export
export { Logo as default };
export { Bedrock as default };
16 changes: 16 additions & 0 deletions x-pack/packages/ai/service_providers/logo/gemini.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
*/

import React from 'react';
import { LogoProps } from '../types';

const Logo = (props: LogoProps) => (
const Gemini = (props: React.SVGProps<SVGSVGElement>) => (
<svg
{...props}
xmlns="http://www.w3.org/2000/svg"
Expand All @@ -29,4 +28,4 @@ const Logo = (props: LogoProps) => (
);

// eslint-disable-next-line import/no-default-export
export { Logo as default };
export { Gemini as default };
65 changes: 65 additions & 0 deletions x-pack/packages/ai/service_providers/logo/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { dynamic } from '@kbn/shared-ux-utility';
import { ServiceProviderID } from '../id';

const LOGO_REACT = {
bedrock: dynamic(() => import('./bedrock')),
gemini: dynamic(() => import('./gemini')),
openai: dynamic(() => import('./open_ai')),
} as const;

const toBase64 = (data: string) => `data:image/svg+xml;base64,${btoa(data)}`;

const LOGO_BASE_64 = {
bedrock: async () => {
const svg = await import('!!raw-loader!./bedrock.svg');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mistic How would this need to change with Webpack 5?

return toBase64(svg.default);
},
gemini: async () => {
const svg = await import('!!raw-loader!./gemini.svg');
return toBase64(svg.default);
},
openai: async () => {
const svg = await import('!!raw-loader!./open_ai.svg');
return toBase64(svg.default);
},
};

const LOGO_URL = {
bedrock: async () => {
const svg = await import('./bedrock.svg');
return toBase64(svg.default);
},
gemini: async () => {
const svg = await import('./gemini.svg');
return toBase64(svg.default);
},
openai: async () => {
const svg = await import('./open_ai.svg');
return toBase64(svg.default);
},
};

/**
* Get a lazy-loaded React component, wrapped in a `Suspense` boundary, for the logo of a service provider.
* @param id The ID of the service provider.
*/
export const getReactComponentLogo = (id: ServiceProviderID) => LOGO_REACT[id];

/**
* Get the base64-encoded SVG of the logo of a service provider.
* @param id The ID of the service provider.
*/
export const getBase64Logo = async (id: ServiceProviderID) => LOGO_BASE_64[id]();

/**
* Get the URL of the logo of a service provider.
* @param id The ID of the service provider.
*/
export const getUrlLogo = async (id: ServiceProviderID) => LOGO_URL[id]();
11 changes: 11 additions & 0 deletions x-pack/packages/ai/service_providers/logo/open_ai.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
*/

import React from 'react';
import { LogoProps } from '../types';

const Logo = (props: LogoProps) => (
const OpenAI = (props: React.SVGProps<SVGSVGElement>) => (
<svg
{...props}
fill="#000000"
Expand All @@ -24,4 +23,4 @@ const Logo = (props: LogoProps) => (
);

// eslint-disable-next-line import/no-default-export
export { Logo as default };
export { OpenAI as default };
Loading