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

[Obs AI Assistant] Implement contextual actions #178405

Merged
merged 15 commits into from
Mar 16, 2024

Conversation

dgieselaar
Copy link
Member

@dgieselaar dgieselaar commented Mar 11, 2024

Implements contextual actions. With this change, consumers of the Observability AI Assistant can add contextual actions to screen context, which are functions that are executed on the client. Its results are then pushed back to the API and the LLM to continue the conversation. This allows consumers to do things like:

  • have the LLM navigate the app
  • push component/browser state to the LLM
  • provide functions that make the most sense in a specific UI context

Additionally, this also opens up the possibility for consumers of the complete API to implement their own functions.

@apmmachine
Copy link
Contributor

🤖 GitHub comments

Expand to view the GitHub comments

Just comment with:

  • /oblt-deploy : Deploy a Kibana instance using the Observability test environments.
  • /oblt-deploy-serverless : Deploy a serverless Kibana instance using the Observability test environments.
  • run elasticsearch-ci/docs : Re-trigger the docs validation. (use unformatted text in the comment!)

@dgieselaar
Copy link
Member Author

/ci

@dgieselaar dgieselaar marked this pull request as ready for review March 13, 2024 15:40
@dgieselaar dgieselaar requested a review from a team as a code owner March 13, 2024 15:40
@dgieselaar dgieselaar added release_note:enhancement v8.14.0 Team:obs-knowledge Observability Experience Knowledge team labels Mar 13, 2024
@elasticmachine
Copy link
Contributor

Pinging @elastic/obs-knowledge-team (Team:obs-knowledge)

@miltonhultgren miltonhultgren self-requested a review March 14, 2024 09:37
Copy link
Contributor

@miltonhultgren miltonhultgren left a comment

Choose a reason for hiding this comment

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

Cool stuff!

@@ -4,6 +4,8 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { ObservabilityAIAssistantChatService } from '../public';
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it allowed for common to import from public?

Copy link
Member Author

Choose a reason for hiding this comment

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

for types, yes

@@ -77,11 +79,37 @@ export interface KnowledgeBaseEntry {
role: KnowledgeBaseEntryRole;
}

export interface ObservabilityAIAssistantScreenContextRequest {
Copy link
Contributor

Choose a reason for hiding this comment

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

Off topic: Is it needed to prefix so many types with ObservabilityAIAssistant?

Copy link
Member Author

Choose a reason for hiding this comment

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

auto-imports search across all projects so in the end I think it's better to be more verbose... e.g. try to import KibanaReactProvider and see what comes up 😄

actions?: Array<{ name: string; description: string; parameters?: CompatibleJSONSchema }>;
}

export type ScreenContextActionRespondFunction<TArguments extends unknown> = ({}: {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Would it be wrong to just call this ScreenContextAction? or ScreenContextFunction?

Copy link
Member Author

Choose a reason for hiding this comment

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

it's an action and then it's the respond property of the action. I do understand it's verbose and I'm not too happy with it but I think it's better than those alternatives

name: string;
description: string;
parameters?: CompatibleJSONSchema;
respond: ScreenContextActionRespondFunction<TArguments>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Off topic: It's interesting to see how the language gets mixed between it being an "action" (function) and a "part of conversation" (respond).

});

it('the observable errors out', async () => {
await expect(async () => await lastValueFrom(callComplete())).rejects.toThrowError(
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it needed to make the call 3 times to check each thing?

Copy link
Member Author

Choose a reason for hiding this comment

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

mostly an artifact of expect and rejects. open to alternatives but couldn't easily figure out a better way.

if (functionClient.hasAction(functionCallName)) {
this.dependencies.logger.debug(`Executing client-side action: ${functionCallName}`);

functionClient.validate(
Copy link
Contributor

Choose a reason for hiding this comment

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

This throws an error if it fails? And if it fails, then what happens with the subscriber? Does it not complete?

Copy link
Member Author

Choose a reason for hiding this comment

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

the error falls through and eventually subscriber.error is called. but that shouldn't actually happen here, we should inject a function error message and send it back to the LLM. will fix and add a test, thanks.

Comment on lines +31 to +32
const originalPushState = window.history.pushState.bind(window.history);
const originalReplaceState = window.history.replaceState.bind(window.history);
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to revert these as part of a clean up for this hook?

Copy link
Member Author

Choose a reason for hiding this comment

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

it's hard to clean up because something else might have overridden window.history.pushState at that point. I'll add a flag for the setState calls and clean up the window listeners.

Comment on lines 43 to 49
window.addEventListener('popstate', () => {
setHref(window.location.href);
});

window.addEventListener('hashchange', () => {
setHref(window.location.href);
});
Copy link
Contributor

Choose a reason for hiding this comment

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

And clean these up maybe as well?

Comment on lines 59 to 77
createScreenContextAction(
{
name: 'foo',
description: 'foo',
parameters: {
type: 'object',
properties: {
foo: {
type: 'string',
},
},
},
},
async ({}) => {
return {
content: 'Action succesfully executed',
};
}
),
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess this is to clean up?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes (thanks :) )


const conversations = await observabilityAIAssistantAPIClient
.writeUser({
endpoint: 'POST /internal/observability_ai_assistant/conversations',
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this POST rather than GET?

Copy link
Member Author

Choose a reason for hiding this comment

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

it's a search request, with optionally a body with filters (right now just a query string).

@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
observabilityAIAssistant 80 85 +5
observabilityAIAssistantApp 211 212 +1
total +6

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
observabilityAIAssistant 216 225 +9

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
observabilityAIAssistant 13.7KB 15.7KB +1.9KB
observabilityAIAssistantApp 139.4KB 140.5KB +1.1KB
total +3.0KB

Public APIs missing exports

Total count of every type that is part of your API that should be exported but is not. This will cause broken links in the API documentation system. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats exports for more detailed information.

id before after diff
observabilityAIAssistant 21 24 +3

Page load bundle

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

id before after diff
observabilityAIAssistant 42.3KB 43.4KB +1.1KB
observabilityAIAssistantApp 12.3KB 12.3KB +51.0B
total +1.2KB
Unknown metric groups

API count

id before after diff
observabilityAIAssistant 218 227 +9

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@dgieselaar dgieselaar merged commit acc5beb into elastic:main Mar 16, 2024
19 checks passed
@kibanamachine kibanamachine added the backport:skip This commit does not require backporting label Mar 16, 2024
@dgieselaar dgieselaar deleted the obs-ai-assistant-screen-actions branch March 17, 2024 08:25
miltonhultgren added a commit that referenced this pull request Mar 21, 2024
#178405 made some changes to how
the chat service passes data to the API, while doing this we missed to
pass along the `responseLanguage` setting, breaking the language
selection feature.

This PR just wires those up again and adds a test to catch this for the
future.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting release_note:enhancement Team:obs-knowledge Observability Experience Knowledge team v8.14.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants