-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can split them, make the constants and service names in a There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
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); |
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; |
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'; |
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'], | ||
}; |
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" | ||
} |
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'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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](); |
There was a problem hiding this comment.
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?There was a problem hiding this comment.
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)