Skip to content

[inference] Add cancelation support for chatComplete and output#203108

Merged
pgayvallet merged 13 commits intoelastic:mainfrom
pgayvallet:kbn-200757-add-request-cancelation
Dec 17, 2024
Merged

[inference] Add cancelation support for chatComplete and output#203108
pgayvallet merged 13 commits intoelastic:mainfrom
pgayvallet:kbn-200757-add-request-cancelation

Conversation

@pgayvallet
Copy link
Copy Markdown
Contributor

@pgayvallet pgayvallet commented Dec 5, 2024

Summary

Fix #200757

Add cancelation support for chatComplete and output, based on an abort signal.

Examples

response mode

import { isInferenceRequestAbortedError } from '@kbn/inference-common';

try {
  const abortController = new AbortController();
  const chatResponse = await inferenceClient.chatComplete({
    connectorId: 'some-gen-ai-connector',
    abortSignal: abortController.signal,
    messages: [{ role: MessageRole.User, content: 'Do something' }],
  });
} catch(e) {
  if(isInferenceRequestAbortedError(e)) {
    // request was aborted, do something
  } else {
    // was another error, do something else
  }
}

// elsewhere
abortController.abort()

stream mode

import { isInferenceRequestAbortedError } from '@kbn/inference-common';

const abortController = new AbortController();
const events$ = inferenceClient.chatComplete({
  stream: true,
  connectorId: 'some-gen-ai-connector',
  abortSignal: abortController.signal,
  messages: [{ role: MessageRole.User, content: 'Do something' }],
});

events$.subscribe({
  next: (event) => {
    // do something
  },
  error: (err) => {
    if(isInferenceRequestAbortedError(e)) {
      // request was aborted, do something
    } else {
      // was another error, do something else
    }
  }
});

abortController.abort();

@pgayvallet
Copy link
Copy Markdown
Contributor Author

/ci

@pgayvallet
Copy link
Copy Markdown
Contributor Author

/ci

@pgayvallet
Copy link
Copy Markdown
Contributor Author

/ci

@pgayvallet pgayvallet added release_note:skip Skip the PR/issue when compiling release notes backport:version Backport to applied version labels Team:AI Infra Platform AppEx AI Infrastructure Team t// v8.18.0 labels Dec 11, 2024
@pgayvallet
Copy link
Copy Markdown
Contributor Author

/ci

@pgayvallet pgayvallet marked this pull request as ready for review December 11, 2024 14:57
@pgayvallet pgayvallet requested a review from a team as a code owner December 11, 2024 14:57
@elasticmachine
Copy link
Copy Markdown
Contributor

Pinging @elastic/appex-ai-infra (Team:AI Infra)

Copy link
Copy Markdown
Member

@legrego legrego left a comment

Choose a reason for hiding this comment

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

LGTM!

},
complete: () => {
if (abortSignal.aborted) {
subscriber.error(createInferenceRequestAbortedError('Request was aborted'));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

question What other messages do we envision for these aborted request errors? This is the only place it's called today, and we pass in a hard-coded message.

I am not asking you to change this, I'm just curious if you have thoughts about the future.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that's a fair point. We probably don't need that message to be passed as a parameter to be honest. I was mostly following the pattern that was used for other inference error types. I will change that

source$.next(3);

expect(values).toEqual([1, 2]);
expect(thrownError).toBeDefined();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: should we assert the correct error instance is thrown?

Suggested change
expect(thrownError).toBeDefined();
expect(thrownError).toBeInstanceOf(InferenceTaskError);
expect(thrownError.code).toBe('requestAborted');

@elasticmachine
Copy link
Copy Markdown
Contributor

💚 Build Succeeded

Metrics [docs]

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
@kbn/inference-common 43 40 -3

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
inference 7.4KB 7.5KB +74.0B
Unknown metric groups

API count

id before after diff
@kbn/inference-common 136 141 +5

History

@pgayvallet pgayvallet merged commit 0b74f62 into elastic:main Dec 17, 2024
@kibanamachine
Copy link
Copy Markdown
Contributor

Starting backport for target branches: 8.x

https://github.com/elastic/kibana/actions/runs/12375857143

kibanamachine pushed a commit to kibanamachine/kibana that referenced this pull request Dec 17, 2024
…tic#203108)

## Summary

Fix elastic#200757

Add cancelation support for `chatComplete` and `output`, based on an
abort signal.

### Examples

#### response mode

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

try {
  const abortController = new AbortController();
  const chatResponse = await inferenceClient.chatComplete({
    connectorId: 'some-gen-ai-connector',
    abortSignal: abortController.signal,
    messages: [{ role: MessageRole.User, content: 'Do something' }],
  });
} catch(e) {
  if(isInferenceRequestAbortedError(e)) {
    // request was aborted, do something
  } else {
    // was another error, do something else
  }
}

// elsewhere
abortController.abort()
```

#### stream mode

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

const abortController = new AbortController();
const events$ = inferenceClient.chatComplete({
  stream: true,
  connectorId: 'some-gen-ai-connector',
  abortSignal: abortController.signal,
  messages: [{ role: MessageRole.User, content: 'Do something' }],
});

events$.subscribe({
  next: (event) => {
    // do something
  },
  error: (err) => {
    if(isInferenceRequestAbortedError(e)) {
      // request was aborted, do something
    } else {
      // was another error, do something else
    }
  }
});

abortController.abort();
```

(cherry picked from commit 0b74f62)
@kibanamachine
Copy link
Copy Markdown
Contributor

💚 All backports created successfully

Status Branch Result
8.x

Note: Successful backport PRs will be merged automatically after passing CI.

Questions ?

Please refer to the Backport tool documentation

stephmilovic pushed a commit that referenced this pull request Dec 17, 2024
…#203108) (#204588)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[inference] Add cancelation support for chatComplete and output
(#203108)](#203108)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Pierre
Gayvallet","email":"pierre.gayvallet@elastic.co"},"sourceCommit":{"committedDate":"2024-12-17T15:13:17Z","message":"[inference]
Add cancelation support for chatComplete and output (#203108)\n\n##
Summary\r\n\r\nFix
https://github.com/elastic/kibana/issues/200757\r\n\r\nAdd cancelation
support for `chatComplete` and `output`, based on an\r\nabort
signal.\r\n\r\n\r\n### Examples\r\n\r\n#### response
mode\r\n\r\n```ts\r\nimport { isInferenceRequestAbortedError } from
'@kbn/inference-common';\r\n\r\ntry {\r\n const abortController = new
AbortController();\r\n const chatResponse = await
inferenceClient.chatComplete({\r\n connectorId:
'some-gen-ai-connector',\r\n abortSignal: abortController.signal,\r\n
messages: [{ role: MessageRole.User, content: 'Do something' }],\r\n
});\r\n} catch(e) {\r\n if(isInferenceRequestAbortedError(e)) {\r\n //
request was aborted, do something\r\n } else {\r\n // was another error,
do something else\r\n }\r\n}\r\n\r\n//
elsewhere\r\nabortController.abort()\r\n```\r\n\r\n#### stream
mode\r\n\r\n```ts\r\nimport { isInferenceRequestAbortedError } from
'@kbn/inference-common';\r\n\r\nconst abortController = new
AbortController();\r\nconst events$ = inferenceClient.chatComplete({\r\n
stream: true,\r\n connectorId: 'some-gen-ai-connector',\r\n abortSignal:
abortController.signal,\r\n messages: [{ role: MessageRole.User,
content: 'Do something' }],\r\n});\r\n\r\nevents$.subscribe({\r\n next:
(event) => {\r\n // do something\r\n },\r\n error: (err) => {\r\n
if(isInferenceRequestAbortedError(e)) {\r\n // request was aborted, do
something\r\n } else {\r\n // was another error, do something else\r\n
}\r\n
}\r\n});\r\n\r\nabortController.abort();\r\n```","sha":"0b74f62a338fe1f6b281a019e71279f0d2ffb81f","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","backport:version","Team:AI
Infra","v8.18.0"],"title":"[inference] Add cancelation support for
chatComplete and
output","number":203108,"url":"https://github.com/elastic/kibana/pull/203108","mergeCommit":{"message":"[inference]
Add cancelation support for chatComplete and output (#203108)\n\n##
Summary\r\n\r\nFix
https://github.com/elastic/kibana/issues/200757\r\n\r\nAdd cancelation
support for `chatComplete` and `output`, based on an\r\nabort
signal.\r\n\r\n\r\n### Examples\r\n\r\n#### response
mode\r\n\r\n```ts\r\nimport { isInferenceRequestAbortedError } from
'@kbn/inference-common';\r\n\r\ntry {\r\n const abortController = new
AbortController();\r\n const chatResponse = await
inferenceClient.chatComplete({\r\n connectorId:
'some-gen-ai-connector',\r\n abortSignal: abortController.signal,\r\n
messages: [{ role: MessageRole.User, content: 'Do something' }],\r\n
});\r\n} catch(e) {\r\n if(isInferenceRequestAbortedError(e)) {\r\n //
request was aborted, do something\r\n } else {\r\n // was another error,
do something else\r\n }\r\n}\r\n\r\n//
elsewhere\r\nabortController.abort()\r\n```\r\n\r\n#### stream
mode\r\n\r\n```ts\r\nimport { isInferenceRequestAbortedError } from
'@kbn/inference-common';\r\n\r\nconst abortController = new
AbortController();\r\nconst events$ = inferenceClient.chatComplete({\r\n
stream: true,\r\n connectorId: 'some-gen-ai-connector',\r\n abortSignal:
abortController.signal,\r\n messages: [{ role: MessageRole.User,
content: 'Do something' }],\r\n});\r\n\r\nevents$.subscribe({\r\n next:
(event) => {\r\n // do something\r\n },\r\n error: (err) => {\r\n
if(isInferenceRequestAbortedError(e)) {\r\n // request was aborted, do
something\r\n } else {\r\n // was another error, do something else\r\n
}\r\n
}\r\n});\r\n\r\nabortController.abort();\r\n```","sha":"0b74f62a338fe1f6b281a019e71279f0d2ffb81f"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/203108","number":203108,"mergeCommit":{"message":"[inference]
Add cancelation support for chatComplete and output (#203108)\n\n##
Summary\r\n\r\nFix
https://github.com/elastic/kibana/issues/200757\r\n\r\nAdd cancelation
support for `chatComplete` and `output`, based on an\r\nabort
signal.\r\n\r\n\r\n### Examples\r\n\r\n#### response
mode\r\n\r\n```ts\r\nimport { isInferenceRequestAbortedError } from
'@kbn/inference-common';\r\n\r\ntry {\r\n const abortController = new
AbortController();\r\n const chatResponse = await
inferenceClient.chatComplete({\r\n connectorId:
'some-gen-ai-connector',\r\n abortSignal: abortController.signal,\r\n
messages: [{ role: MessageRole.User, content: 'Do something' }],\r\n
});\r\n} catch(e) {\r\n if(isInferenceRequestAbortedError(e)) {\r\n //
request was aborted, do something\r\n } else {\r\n // was another error,
do something else\r\n }\r\n}\r\n\r\n//
elsewhere\r\nabortController.abort()\r\n```\r\n\r\n#### stream
mode\r\n\r\n```ts\r\nimport { isInferenceRequestAbortedError } from
'@kbn/inference-common';\r\n\r\nconst abortController = new
AbortController();\r\nconst events$ = inferenceClient.chatComplete({\r\n
stream: true,\r\n connectorId: 'some-gen-ai-connector',\r\n abortSignal:
abortController.signal,\r\n messages: [{ role: MessageRole.User,
content: 'Do something' }],\r\n});\r\n\r\nevents$.subscribe({\r\n next:
(event) => {\r\n // do something\r\n },\r\n error: (err) => {\r\n
if(isInferenceRequestAbortedError(e)) {\r\n // request was aborted, do
something\r\n } else {\r\n // was another error, do something else\r\n
}\r\n
}\r\n});\r\n\r\nabortController.abort();\r\n```","sha":"0b74f62a338fe1f6b281a019e71279f0d2ffb81f"}},{"branch":"8.x","label":"v8.18.0","branchLabelMappingKey":"^v8.18.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Pierre Gayvallet <pierre.gayvallet@elastic.co>
JoseLuisGJ pushed a commit to JoseLuisGJ/kibana that referenced this pull request Dec 19, 2024
…tic#203108)

## Summary

Fix elastic#200757

Add cancelation support for `chatComplete` and `output`, based on an
abort signal.


### Examples

#### response mode

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

try {
  const abortController = new AbortController();
  const chatResponse = await inferenceClient.chatComplete({
    connectorId: 'some-gen-ai-connector',
    abortSignal: abortController.signal,
    messages: [{ role: MessageRole.User, content: 'Do something' }],
  });
} catch(e) {
  if(isInferenceRequestAbortedError(e)) {
    // request was aborted, do something
  } else {
    // was another error, do something else
  }
}

// elsewhere
abortController.abort()
```

#### stream mode

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

const abortController = new AbortController();
const events$ = inferenceClient.chatComplete({
  stream: true,
  connectorId: 'some-gen-ai-connector',
  abortSignal: abortController.signal,
  messages: [{ role: MessageRole.User, content: 'Do something' }],
});

events$.subscribe({
  next: (event) => {
    // do something
  },
  error: (err) => {
    if(isInferenceRequestAbortedError(e)) {
      // request was aborted, do something
    } else {
      // was another error, do something else
    }
  }
});

abortController.abort();
```
benakansara pushed a commit to benakansara/kibana that referenced this pull request Jan 2, 2025
…tic#203108)

## Summary

Fix elastic#200757

Add cancelation support for `chatComplete` and `output`, based on an
abort signal.


### Examples

#### response mode

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

try {
  const abortController = new AbortController();
  const chatResponse = await inferenceClient.chatComplete({
    connectorId: 'some-gen-ai-connector',
    abortSignal: abortController.signal,
    messages: [{ role: MessageRole.User, content: 'Do something' }],
  });
} catch(e) {
  if(isInferenceRequestAbortedError(e)) {
    // request was aborted, do something
  } else {
    // was another error, do something else
  }
}

// elsewhere
abortController.abort()
```

#### stream mode

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

const abortController = new AbortController();
const events$ = inferenceClient.chatComplete({
  stream: true,
  connectorId: 'some-gen-ai-connector',
  abortSignal: abortController.signal,
  messages: [{ role: MessageRole.User, content: 'Do something' }],
});

events$.subscribe({
  next: (event) => {
    // do something
  },
  error: (err) => {
    if(isInferenceRequestAbortedError(e)) {
      // request was aborted, do something
    } else {
      // was another error, do something else
    }
  }
});

abortController.abort();
```
viduni94 pushed a commit to viduni94/kibana that referenced this pull request Jan 23, 2025
…tic#203108)

## Summary

Fix elastic#200757

Add cancelation support for `chatComplete` and `output`, based on an
abort signal.


### Examples

#### response mode

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

try {
  const abortController = new AbortController();
  const chatResponse = await inferenceClient.chatComplete({
    connectorId: 'some-gen-ai-connector',
    abortSignal: abortController.signal,
    messages: [{ role: MessageRole.User, content: 'Do something' }],
  });
} catch(e) {
  if(isInferenceRequestAbortedError(e)) {
    // request was aborted, do something
  } else {
    // was another error, do something else
  }
}

// elsewhere
abortController.abort()
```

#### stream mode

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

const abortController = new AbortController();
const events$ = inferenceClient.chatComplete({
  stream: true,
  connectorId: 'some-gen-ai-connector',
  abortSignal: abortController.signal,
  messages: [{ role: MessageRole.User, content: 'Do something' }],
});

events$.subscribe({
  next: (event) => {
    // do something
  },
  error: (err) => {
    if(isInferenceRequestAbortedError(e)) {
      // request was aborted, do something
    } else {
      // was another error, do something else
    }
  }
});

abortController.abort();
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport:version Backport to applied version labels release_note:skip Skip the PR/issue when compiling release notes Team:AI Infra Platform AppEx AI Infrastructure Team t// v8.18.0 v9.0.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[inference] Add support for request cancelation

4 participants