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

Introduce the InferenceChatModel for langchain #206429

Open
wants to merge 48 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
999943a
create @kbn/inference-langchain package
pgayvallet Jan 13, 2025
77514a2
initial implementation
pgayvallet Jan 13, 2025
8711d3d
add fake id tool to inference-common
pgayvallet Jan 13, 2025
bc887ca
export stuff
pgayvallet Jan 13, 2025
2e57060
fix comment->tsdoc
pgayvallet Jan 13, 2025
b3df181
move zod-to-json-schema from dev to prod dependencies
pgayvallet Jan 13, 2025
1b93869
add some basic readme
pgayvallet Jan 13, 2025
331bbf7
bootstrap
pgayvallet Jan 13, 2025
bf7633c
Add reference in the inference's readme
pgayvallet Jan 13, 2025
a610078
Merge remote-tracking branch 'upstream/main' into kbn-xxx-inference-l…
pgayvallet Jan 15, 2025
f144a28
add support for temperature param
pgayvallet Jan 15, 2025
683c5f6
extract response conversion
pgayvallet Jan 15, 2025
f2a2df5
add ref
pgayvallet Jan 15, 2025
05967e3
set tool_calls as undefined instead of empty list when not used
pgayvallet Jan 15, 2025
17b7915
Merge remote-tracking branch 'upstream/main' into kbn-xxx-inference-l…
pgayvallet Jan 17, 2025
1f7492a
add support for model parameter
pgayvallet Jan 17, 2025
27d8f00
replay CI commits
pgayvallet Jan 17, 2025
85ce0a5
support another format of tool definition
pgayvallet Jan 17, 2025
db586f3
implement withStructuredOutput
pgayvallet Jan 17, 2025
79b34ce
implement identifyingParams
pgayvallet Jan 17, 2025
50c3469
implement _combineLLMOutput
pgayvallet Jan 17, 2025
adf0c3d
implement completionWithRetry
pgayvallet Jan 17, 2025
9ed8721
[CI] Auto-commit changed files from 'node scripts/notice'
kibanamachine Jan 17, 2025
821a99f
add explicit properties for constructor props
pgayvallet Jan 20, 2025
8b08579
Merge remote-tracking branch 'upstream/main' into kbn-xxx-inference-l…
pgayvallet Jan 20, 2025
19dac67
Merge remote-tracking branch 'upstream/main' into kbn-xxx-inference-l…
pgayvallet Jan 24, 2025
ca2ec30
expose `getChatModel` from the inference plugin
pgayvallet Jan 27, 2025
9923ed7
Merge remote-tracking branch 'upstream/main' into kbn-xxx-inference-l…
pgayvallet Jan 27, 2025
df03721
move connector util to common package
pgayvallet Jan 27, 2025
2ad2052
intercept tool validation errors
pgayvallet Jan 27, 2025
dad02ea
remove reference to action plugin
pgayvallet Jan 27, 2025
2874f10
ts ref
pgayvallet Jan 27, 2025
9373172
fix import
pgayvallet Jan 27, 2025
9f7fe88
detect more meta things
pgayvallet Jan 27, 2025
b9cdf02
update readmes
pgayvallet Jan 27, 2025
0a33655
pass down logger
pgayvallet Jan 27, 2025
a8943f8
[CI] Auto-commit changed files from 'node scripts/notice'
kibanamachine Jan 27, 2025
bc50918
add tests, starting self review
pgayvallet Jan 28, 2025
66cfefc
first batch of unit tests for the chat model
pgayvallet Jan 29, 2025
f9442c1
[CI] Auto-commit changed files from 'node scripts/notice'
kibanamachine Jan 29, 2025
e41b59b
more unit tests
pgayvallet Jan 29, 2025
267a043
done with unit tests
pgayvallet Jan 29, 2025
3e5cd91
Merge remote-tracking branch 'upstream/main' into kbn-xxx-inference-l…
pgayvallet Jan 29, 2025
4293011
Merge remote-tracking branch 'upstream/main' into kbn-xxx-inference-l…
pgayvallet Jan 29, 2025
10ce51a
include status code in inference responses
pgayvallet Jan 29, 2025
2a7ef42
add mocks + test for unrecoverable errors
pgayvallet Jan 29, 2025
d9f8c57
Merge remote-tracking branch 'upstream/main' into kbn-xxx-inference-l…
pgayvallet Jan 30, 2025
9acb9f7
fix unit test
pgayvallet Jan 30, 2025
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
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,7 @@ x-pack/platform/packages/private/security/ui_components @elastic/kibana-security
x-pack/platform/packages/shared/ai-assistant/common @elastic/search-kibana
x-pack/platform/packages/shared/ai-assistant/icon @elastic/appex-sharedux
x-pack/platform/packages/shared/ai-infra/inference-common @elastic/appex-ai-infra
x-pack/platform/packages/shared/ai-infra/inference-langchain @elastic/appex-ai-infra
x-pack/platform/packages/shared/ai-infra/product-doc-common @elastic/appex-ai-infra
x-pack/platform/packages/shared/file-upload-common @elastic/ml-ui
x-pack/platform/packages/shared/index-lifecycle-management/index_lifecycle_management_common_shared @elastic/kibana-management
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,7 @@
"@kbn/inference-common": "link:x-pack/platform/packages/shared/ai-infra/inference-common",
"@kbn/inference-endpoint-plugin": "link:x-pack/platform/plugins/shared/inference_endpoint",
"@kbn/inference-endpoint-ui-common": "link:x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common",
"@kbn/inference-langchain": "link:x-pack/platform/packages/shared/ai-infra/inference-langchain",
"@kbn/inference-plugin": "link:x-pack/platform/plugins/shared/inference",
"@kbn/inference_integration_flyout": "link:x-pack/platform/packages/private/ml/inference_integration_flyout",
"@kbn/infra-forge": "link:x-pack/platform/packages/private/kbn-infra-forge",
Expand Down Expand Up @@ -1301,7 +1302,8 @@
"yaml": "^2.5.1",
"yauzl": "^2.10.0",
"yazl": "^2.5.1",
"zod": "^3.22.3"
"zod": "^3.22.3",
"zod-to-json-schema": "^3.23.0"
},
"devDependencies": {
"@apidevtools/swagger-parser": "^10.1.1",
Expand Down Expand Up @@ -1871,8 +1873,7 @@
"xml-crypto": "^6.0.0",
"xmlbuilder": "15.1.1",
"yargs": "^15.4.1",
"yarn-deduplicate": "^6.0.2",
"zod-to-json-schema": "^3.23.0"
"yarn-deduplicate": "^6.0.2"
},
"packageManager": "[email protected]"
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
*/

import { z, isZod } from '@kbn/zod';
// eslint-disable-next-line import/no-extraneous-dependencies
import zodToJsonSchema from 'zod-to-json-schema';
import type { OpenAPIV3 } from 'openapi-types';

Expand Down
2 changes: 2 additions & 0 deletions tsconfig.base.json
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,8 @@
"@kbn/inference-endpoint-plugin/*": ["x-pack/platform/plugins/shared/inference_endpoint/*"],
"@kbn/inference-endpoint-ui-common": ["x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common"],
"@kbn/inference-endpoint-ui-common/*": ["x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/*"],
"@kbn/inference-langchain": ["x-pack/platform/packages/shared/ai-infra/inference-langchain"],
"@kbn/inference-langchain/*": ["x-pack/platform/packages/shared/ai-infra/inference-langchain/*"],
"@kbn/inference-plugin": ["x-pack/platform/plugins/shared/inference"],
"@kbn/inference-plugin/*": ["x-pack/platform/plugins/shared/inference/*"],
"@kbn/infra-forge": ["x-pack/platform/packages/private/kbn-infra-forge"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,17 @@ export {
isInferenceRequestError,
isInferenceRequestAbortedError,
} from './src/errors';
export { generateFakeToolCallId } from './src/utils';
export { elasticModelDictionary } from './src/const';

export { truncateList } from './src/truncate_list';
export {
InferenceConnectorType,
isSupportedConnectorType,
isSupportedConnector,
getConnectorDefaultModel,
getConnectorProvider,
connectorToInference,
type InferenceConnector,
} from './src/connectors';
export {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export type ToolMessage<
TToolResponse extends Record<string, any> | unknown = Record<string, any> | unknown,
TToolData extends Record<string, any> | undefined = Record<string, any> | undefined
> = MessageBase<MessageRole.Tool> & {
/*
/**
* The name of the tool called. Used for refining the type of the response.
*/
name: TName;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* 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 { type InferenceConnector, InferenceConnectorType } from './connectors';

/**
* Returns the default model as defined in the connector's config, if available.
*
* Note: preconfigured connectors only expose their config if their `exposeConfig` flag
* is set to true.
*/
export const getConnectorDefaultModel = (connector: InferenceConnector): string | undefined => {
switch (connector.type) {
case InferenceConnectorType.OpenAI:
case InferenceConnectorType.Gemini:
case InferenceConnectorType.Bedrock:
return connector.config?.defaultModel ?? undefined;
case InferenceConnectorType.Inference:
return connector.config?.providerConfig?.model_id ?? undefined;
}
};

/**
* Returns the provider used for the given connector
*
* Inferred from the type for "legacy" connectors,
* and from the provider config field for inference connectors.
*/
export const getConnectorProvider = (connector: InferenceConnector): string => {
switch (connector.type) {
case InferenceConnectorType.OpenAI:
return 'openai';
case InferenceConnectorType.Gemini:
return 'gemini';
case InferenceConnectorType.Bedrock:
return 'bedrock';
case InferenceConnectorType.Inference:
return connector.config?.provider ?? 'unknown';
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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 { createInferenceRequestError } from '../errors';
import type { InferenceConnector, RawConnector } from './connectors';
import { isSupportedConnector } from './is_supported_connector';

/**
* Converts an action connector to the internal inference connector format.
*
* The function will throw if the provided connector is not compatible
*/
export const connectorToInference = (connector: RawConnector): InferenceConnector => {
if (!isSupportedConnector(connector)) {
throw createInferenceRequestError(
`Connector '${connector.id}' of type '${connector.actionTypeId}' not recognized as a supported connector`,
400
);
}

return {
connectorId: connector.id,
name: connector.name,
type: connector.actionTypeId,
config: connector.config ?? {},
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* 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.
*/

/**
* The list of connector types that can be used with the inference APIs
*/
export enum InferenceConnectorType {
OpenAI = '.gen-ai',
Bedrock = '.bedrock',
Gemini = '.gemini',
Inference = '.inference',
}

export const allSupportedConnectorTypes = Object.values(InferenceConnectorType);

/**
* Represents a stack connector that can be used for inference.
*/
export interface InferenceConnector {
/** the type of the connector, see {@link InferenceConnectorType} */
type: InferenceConnectorType;
/** the name of the connector */
name: string;
/** the id of the connector */
connectorId: string;
/**
* configuration (without secrets) of the connector.
* the list of properties depends on the connector type (and subtype for inference)
*/
config: Record<string, any>;
}

/**
* Connector types are living in the actions plugin and we can't afford
* having dependencies from this package to some mid-level plugin,
* so we're just using our own connector mixin type.
*/
export interface RawConnector {
id: string;
actionTypeId: string;
name: string;
config?: Record<string, any>;
}

export interface RawInferenceConnector {
id: string;
actionTypeId: InferenceConnectorType;
name: string;
config?: Record<string, any>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* 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 { isSupportedConnectorType, isSupportedConnector } from './is_supported_connector';
export { connectorToInference } from './connector_to_inference';
export { getConnectorDefaultModel, getConnectorProvider } from './connector_config';
export { InferenceConnectorType, type InferenceConnector } from './connectors';
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@
* 2.0.
*/

import { InferenceConnectorType, RawConnector } from './connectors';
import {
InferenceConnectorType,
isSupportedConnectorType,
isSupportedConnector,
RawConnector,
COMPLETION_TASK_TYPE,
} from './connectors';
} from './is_supported_connector';

const createRawConnector = (parts: Partial<RawConnector>): RawConnector => {
return {
Expand All @@ -36,8 +35,6 @@ describe('isSupportedConnectorType', () => {
});

describe('isSupportedConnector', () => {
// TODO

it('returns true for OpenAI connectors', () => {
expect(
isSupportedConnector(createRawConnector({ actionTypeId: InferenceConnectorType.OpenAI }))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,15 @@
* 2.0.
*/

/**
* The list of connector types that can be used with the inference APIs
*/
export enum InferenceConnectorType {
OpenAI = '.gen-ai',
Bedrock = '.bedrock',
Gemini = '.gemini',
Inference = '.inference',
}
import {
InferenceConnectorType,
RawInferenceConnector,
RawConnector,
allSupportedConnectorTypes,
} from './connectors';

export const COMPLETION_TASK_TYPE = 'chat_completion';

const allSupportedConnectorTypes = Object.values(InferenceConnectorType);

/**
* Represents a stack connector that can be used for inference.
*/
export interface InferenceConnector {
/** the type of the connector, see {@link InferenceConnectorType} */
type: InferenceConnectorType;
/** the name of the connector */
name: string;
/** the id of the connector */
connectorId: string;
/**
* configuration (without secrets) of the connector.
* the list of properties depends on the connector type (and subtype for inference)
*/
config: Record<string, any>;
}

/**
* Checks if a given connector type is compatible for inference.
*
Expand Down Expand Up @@ -67,22 +45,3 @@ export function isSupportedConnector(connector: RawConnector): connector is RawI
}
return true;
}

/**
* Connector types are living in the actions plugin and we can't afford
* having dependencies from this package to some mid-level plugin,
* so we're just using our own connector mixin type.
*/
export interface RawConnector {
id: string;
actionTypeId: string;
name: string;
config?: Record<string, any>;
}

interface RawInferenceConnector {
id: string;
actionTypeId: InferenceConnectorType;
name: string;
config?: Record<string, any>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ export class InferenceTaskError<
super(message);
}

public get status() {
if (typeof this.meta === 'object' && this.meta.status) {
return this.meta.status as number;
}
return undefined;
}

toJSON(): InferenceTaskErrorEvent {
return {
type: InferenceTaskEventType.error,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* 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 { generateFakeToolCallId } from './tool_calls';
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.
*/

import { v4 } from 'uuid';

export function generateFakeToolCallId() {
return v4().substr(0, 6);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# @kbn/inference-langchain

This package exposes utilities to use the inference APIs and plugin with langchain

## InferenceChatModel

The inference chat model is a langchain model leveraging the inference APIs under the hood.

The main upside is that the unification and normalization layers are then fully handled
by the inference plugin. The developer / consumer doesn't even need to know which provider
is being used under the hood.

The easiest way to create an `InferenceChatModel` is by using the inference APIs:

```ts
const chatModel = await inferenceStart.getChatModel({
request,
connectorId: myInferenceConnectorId,
chatModelOptions: {
temperature: 0.2,
},
});

// just use it as another langchain chatModel
```

But the chatModel can also be instantiated directly if needed:

```ts
import { connectorToInference } from '@kbn/inference-common';

const chatModel = new InferenceChatModel({
chatComplete: inference.chatComplete,
connector: connectorToInference(someInferenceConnector),
logger: myPluginLogger,
});

// just use it as another langchain chatModel
```
Loading