-
Notifications
You must be signed in to change notification settings - Fork 76
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
Add ai-constructs
and default implementation of conversation handler
#1822
Add ai-constructs
and default implementation of conversation handler
#1822
Conversation
🦋 Changeset detectedLatest commit: cf7778f The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
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.
Looks good overall.
packages/backend-ai/package.json
Outdated
@@ -0,0 +1,35 @@ | |||
{ | |||
"name": "@aws-amplify/backend-ai", |
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.
Should we follow the same nomenclature as auth where we have a construct
package and a backend
package such that this will be ai-construct
and later we introduce backend-ai
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.
We were (still are?) struggling with vision around packaging "ai features".
Couple of thoughts:
- The coming "ai features" seem to be independent islands of functionality. I.e.
defineAi
,ai-construct
(singular) kind of abstraction don't seem to be correct. E.g. conversational bot is different set of components than generating images from description. These seem to be clusters of functionality under single "theme" (ai). - Because of point 1. If we were to follow
auth
anddata
we'll end up with multitude of packages likeai-conversation-handler-construct
,ai-image-generation-construct
etc. This seems a bit too aggressive and fragmented approach. Especially that we're introducing lower level public components like "conversation handler" (and there doesn't seem to be alternative for that). Hence, a strategy that seems to fit is to use package names for "ai theme" and namespaces to do functionality taxonomy inside. - The reason why
data
andauth
constructs are separated is that there was hard requirement for them to be usable in raw CDK. On the other hand test I wrote seems to indicate that data + conversation construct could be used in raw CDK. (and a good signal to reconsider dumping everything tobackend-ai
). - While prototyping it felt odd that "construct package" would host 99% of the code now and "backend-ai" would be rather a facade. But, having that split eagerly might not be a bad idea to show next set of features a trajectory to follow.
- The "conversation handler" construct is exposed publicly, so that both conversation transformer AND defineConversationHandler can see and use it. There didn't seem to be other need for construct to be public. But then
defineConversationHandler
translates tonew Construct
in raw CDK world. But we don't have strict requirement for raw CDK, so conversation construct being public is a necessity rather than desire right now.
I think we should take your suggestion, with small modification. I.e. do this:
- Introduce a commonjs package called
ai-constructs
(plural!) . That will host any raw CDK components we need for ai "theme". (Today it's gonna be construct + lambda runtime components) backend-ai
to adapt raw CDK primitives to "Gen2 backend style". I.e. today it'll havedefineConversationHandler
+ re-exports of lambda runtime apis).
Additional supporting thought for such split is that data construct depending on ai-constructs seems to smell much better than data construct depending on backend-ai.
@Amplifiyer @atierian @josefaidt @dbanksdesign any objections to this ?
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.
Discussed offline. We'll create ai-constructs
package to host CDK stuff.
packages/backend-ai/README.md
Outdated
This package contains components for interacting with AI models, simplifying the process | ||
of incorporating AI functionality into Amplify projects. |
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.
We should also include the composition of the construct or the architecture (e.g. it's a combination of a pre-defined lambda function with a log group)
bundling: { | ||
bundleAwsSDK: true, | ||
}, | ||
logGroup: new LogGroup(this, 'conversationHandlerFunctionLogGroup', { |
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.
should we allow users passing in their own log group?
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.
We don't do that in defineFunction
.
But on the other hand we don't expose any construct there.
Custom log group comes from requirement to redact access tokens in case they get mistakenly logged by lambda.
This is one of the things that can be added later without breaks. So my suggestion would be to punt this.
if (bedrockResponse.output?.message) { | ||
messages.push(bedrockResponse.output?.message); | ||
} |
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.
Is this for a subsequent askBedRock
for the same turnevent?
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.
yeah, this is a remnant from transplanting poc code.
I.e. yes, it will be needed in subsequent PRs when we bring tools. But in this one is not needed, I'll remove this for now.
packages/backend-ai/src/conversation/runtime/conversation_turn_response_sender.ts
Outdated
Show resolved
Hide resolved
|
||
sendResponse = async (message: ContentBlock[]) => { | ||
const request = this.createMutationRequest(message); | ||
const res = await this._fetch(request); |
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.
Shouldn't there be a try/catch as well since fetch can throw?
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.
I refrained from aggressively catching exceptions, following this philosophy. https://softwareengineering.stackexchange.com/questions/365427/try-catch-log-rethrow-is-anti-pattern .
From practical point of view (that I observed when working on this)
- When
fetch
throws:- Exception bubbles up all the way to lambda runtime
- Exception is logged into CW as is.
- Lambda metrics show failed executions.
- Statements below were added to catch "silent failures":
- When request comes back with non-2xx status
- When GQL error is in payload with 2xx status (this is horrible btw...)
- In both cases (without these extra checks) fetch was happy and there was no trace of failure.
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.
I agree with just re-throwing is bad, but if a better error message can be included I think it's worth it. Since this is a data plane call and going through AppSync, what will customers see when this fails?
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 a better error message can be included I think it's worth it
We can do that. But right place for that is going to be in top level component. I.e. add try-catch to this top level messaging
amplify-backend/packages/backend-ai/src/conversation/runtime/conversation_turn_executor.ts
Lines 27 to 30 in ae3fbba
console.log( | |
`Conversation turn event handled successfully, currentMessageId=${this.event.currentMessageId}, conversationId=${this.event.conversationId}` | |
); | |
}; |
Since this is a data plane call and going through AppSync, what will customers see when this fails?
This is a questionable part. As lambda invocation is asynchronous from appsync pov (fire and forget). I.e. frontend will see bot going silent.
This is a tradeoff made in upstream (appsync part) design and there doesn't seem to be 100% good solution visible right now.
packages/backend-ai/API.md
Outdated
type ConversationTurnEvent = { | ||
conversationId: string; | ||
currentMessageId: string; | ||
responseMutationName: string; | ||
responseMutationInputTypeName: string; | ||
graphqlApiEndpoint: string; | ||
modelConfiguration: { | ||
modelId: string; | ||
systemPrompt: string; | ||
region?: string; | ||
}; | ||
request: { | ||
headers: { | ||
authorization: string; | ||
}; | ||
}; | ||
messages: Array<ConversationMessage>; | ||
}; |
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.
I'm guessing this is defined by AppSync? How will we manage changes in this type?
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.
AppSync will be sending these events.
However, conversation-transformer that will deploy lambda in default scenario is going to see this type (through dependency on new construct) and can use this definition to deploy correct event producer.
In addition. conversation-transformer and handler are going to be part of same deps graph and deploy together, so risk of them going out of sync is zero (or near zero).
@atierian please correct me if I'm wrong here.
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.
Correct.
can use this definition to deploy correct event producer.
We're not currently doing this in the transformer, but this sounds like a good idea. Made a note to explore this.
backend-ai
and default implementation of conversation handlerai-constructs
and default implementation of conversation handler
if (this.props.entry && !path.isAbsolute(this.props.entry)) { | ||
throw new Error('Entry must be absolute path'); | ||
} |
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.
I added this restriction for now. We need some smarter resolution logic which is similar to what defineFunction
and NodeJSFunction
construct is doing. But I didn't want to inflate this PR with that.
We'll address this later (when defineConversationHandler
) happens.
if (this.props.models && this.props.models.length > 0) { | ||
const resources = this.props.models.map( | ||
(model) => | ||
`arn:aws:bedrock:${model.region}::foundation-model/${model.modelId}` |
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.
What happens if a customer's account is in one region and they use a model in a different region? Or is that not possible/not a concern?
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 a customer's account
I guess you mean main stack resources. Account has access to many regions.
they use a model in a different region?
That is perfectly legal. It just ends up being cross region call which comes with extra latency. The API is created in such a way that they have to opt in to do this and upstream layers (data construct?) will do some defaulting.
It is possible to allow usage of same model in multiple regions, one just adds another entry with same modelid and different region.
The reason to expose region at all as an option is that number of models available per region varies and is quite constrained comparing to other resources we provision (like cognito).
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.
Not in scope of this PR but maybe we can add a warning that there will be extra latency. Might be confusing if you switch models to one in another region and all of a sudden your conversation handler consistently times out.
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.
That latency penalty is not that high comparing to LLM execution time.
Take a look at this post https://repost.aws/questions/QUl7IRSjpMQVe2mMOFojP6qA/a-question-about-inter-region-latency to get a raw estimate of how impactful this can be. I.e. in case of S3 1MB transfers it seem to range between 81ms and 755ms depending on regions selections. Which is still order of magnitude less than LLM execution alone.
I'd say we should hold with such a warning as it's not something magical we'd be doing. Customer explicitly specifies that, so the fact that cross region communication may be costly should be rather obvious.
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.
Got it, wasn't sure if the extra latency would be substantial or not compared to the total execution time.
packages/ai-constructs/src/conversation/conversation_handler_construct.ts
Show resolved
Hide resolved
|
||
const stack = backend.createStack('conversationHandlerStack'); | ||
|
||
new ConversationHandlerFunction(stack, 'conversationHandlerFunction', { |
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.
is this connected to anything?
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.
In real life it will be - to appsync resolver.
in the test, we're mocking the upstream appsync component so that we can (kind of) e2e test this in isolation while other components are still built.
I.e.
The test sends event instead of appsync resolver here and we assert that response was published here
This might get replaced with simpler approach later when other components (related to schema builder changes) mature. But for now this is what can be done.
… conversation handler (#1948) * Add `ai-constructs` and default implementation of conversation handler (#1822) * add backend-ai package * commonjs * default handler - wip * fix bedrock version * fix that * e2e test * update response type * update response type * make code testable * some PR feedback * rename construct package * top level try catch * construct unit tests * lint * more tests * ehhh * adapter test * more tests * addressing TODOs * readme * undo that * Add Bedrock tools to conversation handler (#1830) * add tools * changeset * add e2e test for programmatic tool * add e2e test for data tool * lint * adapter tests * refactor event tools * refactor event tools * gql tool test * provider test * factory test * detect all duplicates * pr feedback. * Merge main to conversation handler (#1846) * update cdk error mapper to catch all deployment errors (#1826) * update cdk error mapper to catch all deployment errors * add package-loc * prevent ctrl+c handling for pnpm (#1818) * feat: Multi bucket support (#1742) * feat: init multi-bucket support * refactor: BackendOutput type * update package-lock * temp * feat: update schema and client_config * feat: increment schema and client_config versions to 1.1 * rename to buckets and remove friendlyName * chore: add changeset * chore: update API.md * fix: remove duplicated code * fix: construct test * feat: validate isDefault * chore: remove as any * test: fix client_config_contributor * chore: update package-lock * fix: getOutput * refactor: backend_output_client * refactor: DefaultBackendOutputClient * revert changes on addBackendOutputEntry, use appendToBackendOutputList * update JSdocs for construct * make storageOutput more specific * add factoryCounter and hasDefault * use factoryCounter as postfix * update changeset * fix: buckets output schema * feat: add name to buckets * feat: throw no isdefault error before deploy * chore: remove post-deploy error * refactor: use factoryCounter for policy * refactor: pass buckets to appendToBackendOutputList * remove StorageOutputPayloadToStore * fix construct test * revert BackendOutput type * chore: update changeset * fix: client_config_contributer_v1 and test * fix: pin api-extractor to 7.40.0 * chore: update API.md * refactor: use global factoryCounter for policy * refactor: use addBackendOutputEntry for default * test: fix storage construct test * this works * move DeepPartial * remove StorageBucketsPayload * refactor: use Aspects to validate storage * fix: add buckets to metadata * fix: factory unit test * fix: metadata_output_storage_strategy unit test * fix: not export AmplifyStorage * refactor: addOrUpdateMetadata * update package-lock * update package-lock * Update packages/backend-storage/src/factory.ts Co-authored-by: Amplifiyer <[email protected]> * Update packages/backend-storage/src/factory.ts Co-authored-by: Amplifiyer <[email protected]> * refactor: remove redundant code in StorageClientConfigContributor * test: add unit tests for construct and factory * fix: one bucket no default case * fix: unit test * test log currentCodebaseOutputs and npmOutputs * fix: convert bucketName, storageRegion into bucket_name, aws_region * fix: client_config_contributor_v1.test * refactor: use Aspect to replact factory static * fix: buckets keys * fix: unit test * fix MultipleDefaultBucketError and add more unit tests * remove policyCount static * Update packages/backend-storage/src/factory.ts Co-authored-by: Amplifiyer <[email protected]> * refactor StorageValidator * Refactor: storeOutput to factory * remove comment * Update packages/backend-storage/src/factory.ts Co-authored-by: Kamil Sobol <[email protected]> * Update packages/backend-storage/src/factory.ts Co-authored-by: Kamil Sobol <[email protected]> * Update packages/backend-storage/src/factory.ts Co-authored-by: Kamil Sobol <[email protected]> * Update packages/backend-storage/src/construct.ts Co-authored-by: Kamil Sobol <[email protected]> * Revert "test log currentCodebaseOutputs and npmOutputs" This reverts commit 4ce8db5. * rename defaultStorageFound * remove firstStorage from getInstance * rename buckets to storage, and fix unit tests * use isStorageProcessed * fix construct test * fix StackMetadataBackendOutputStorageStrategy unit test * fix a typo to make lint happy * Update packages/backend-storage/src/factory.ts Co-authored-by: Amplifiyer <[email protected]> * Update packages/client-config/src/client-config-contributor/client_config_contributor_v1.ts Co-authored-by: Edward Foyle <[email protected]> * fix type error in client_config_contributer_v1 * refactor: use early return * test: fix test name * refactor: move Aspects to another file * refactor: remove this.node * Update packages/backend-storage/src/storage_outputs_aspect.ts Co-authored-by: Amplifiyer <[email protected]> * add isMatch to match outputs * add unit test for aspects --------- Co-authored-by: Kamil Sobol <[email protected]> Co-authored-by: Amplifiyer <[email protected]> Co-authored-by: Kamil Sobol <[email protected]> Co-authored-by: Edward Foyle <[email protected]> * chore(deps): bump fast-xml-parser, @aws-sdk/client-amplify, @aws-sdk/client-cloudformation, @aws-sdk/client-cognito-identity-provider, @aws-sdk/client-dynamodb, @aws-sdk/client-iam, @aws-sdk/client-s3 and @aws-sdk/client-ssm (#1836) Bumps [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) to 4.4.1 and updates ancestor dependencies [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser), [@aws-sdk/client-amplify](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-amplify), [@aws-sdk/client-cloudformation](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-cloudformation), [@aws-sdk/client-cognito-identity-provider](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-cognito-identity-provider), [@aws-sdk/client-dynamodb](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-dynamodb), [@aws-sdk/client-iam](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-iam), [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3) and [@aws-sdk/client-ssm](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-ssm). These dependencies need to be updated together. Updates `fast-xml-parser` from 4.1.2 to 4.4.1 - [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases) - [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md) - [Commits](NaturalIntelligence/fast-xml-parser@v4.1.2...v4.4.1) Updates `@aws-sdk/client-amplify` from 3.614.0 to 3.624.0 - [Release notes](https://github.com/aws/aws-sdk-js-v3/releases) - [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-amplify/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.624.0/clients/client-amplify) Updates `@aws-sdk/client-cloudformation` from 3.614.0 to 3.624.0 - [Release notes](https://github.com/aws/aws-sdk-js-v3/releases) - [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-cloudformation/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.624.0/clients/client-cloudformation) Updates `@aws-sdk/client-cognito-identity-provider` from 3.614.0 to 3.625.0 - [Release notes](https://github.com/aws/aws-sdk-js-v3/releases) - [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-cognito-identity-provider/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.625.0/clients/client-cognito-identity-provider) Updates `@aws-sdk/client-dynamodb` from 3.614.0 to 3.624.0 - [Release notes](https://github.com/aws/aws-sdk-js-v3/releases) - [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-dynamodb/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.624.0/clients/client-dynamodb) Updates `@aws-sdk/client-iam` from 3.614.0 to 3.624.0 - [Release notes](https://github.com/aws/aws-sdk-js-v3/releases) - [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-iam/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.624.0/clients/client-iam) Updates `@aws-sdk/client-s3` from 3.614.0 to 3.626.0 - [Release notes](https://github.com/aws/aws-sdk-js-v3/releases) - [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.626.0/clients/client-s3) Updates `@aws-sdk/client-ssm` from 3.614.0 to 3.624.0 - [Release notes](https://github.com/aws/aws-sdk-js-v3/releases) - [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-ssm/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.624.0/clients/client-ssm) --- updated-dependencies: - dependency-name: fast-xml-parser dependency-type: indirect - dependency-name: "@aws-sdk/client-amplify" dependency-type: direct:production - dependency-name: "@aws-sdk/client-cloudformation" dependency-type: direct:production - dependency-name: "@aws-sdk/client-cognito-identity-provider" dependency-type: direct:development - dependency-name: "@aws-sdk/client-dynamodb" dependency-type: direct:development - dependency-name: "@aws-sdk/client-iam" dependency-type: direct:development - dependency-name: "@aws-sdk/client-s3" dependency-type: direct:production - dependency-name: "@aws-sdk/client-ssm" dependency-type: direct:production ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Revert "feat: Multi bucket support" (#1837) * Revert "feat: Multi bucket support (#1742)" This reverts commit d8b43d2. * add changeset * upgrade AWS SDK packages to latest (#1839) * Split sandbox e2e tests (#1841) * Handle nested namespaces in api check (#1842) --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Amplifiyer <[email protected]> Co-authored-by: Roshane Pascual <[email protected]> Co-authored-by: MJ Zhang <[email protected]> Co-authored-by: Edward Foyle <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Make conversation response selection set dynamic (#1848) * Make conversation selection set dynamic * grrr * UI tools (#1853) * add client tools to schema * api * logic and unit tests * e2e * pr feedback * Add `defineConversationHandlerFunction` and `@aws-amplify/backend-ai` package. (#1858) * Add backend-ai * factory * this works * changeset * api * fix that * boop * add unit test * readme * some pr feedback * Serialize tool us blocks (#1866) * stringify tool input * stringify tool input * Adjust API.md generation in backend-ai for api check to work. (#1869) * Adjust API.md generation in backend-ai for api check to work. * changeset * Add main entry point. (#1870) * fix e2e test * Add ability to pass inference configuration (#1878) * Add ability to pass inference configuration * Add ability to pass inference configuration * fix(ai-constructs): support no input graphql query tools (#1907) * fix(ai-constructs): no input graphql query tools * add changeset * empty * fix api diff * fix tool query assertion * lets try this again * Api adjustments for conversation handler (#1938) * accept models from schema def * api updates * api updates * Squash changeset on feature/conversation-handler branch and fix api check (#1949) * squash changeset * fix api check * grrr * handle usage of subnamespaced types in api check (#1952) --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Amplifiyer <[email protected]> Co-authored-by: Roshane Pascual <[email protected]> Co-authored-by: MJ Zhang <[email protected]> Co-authored-by: Edward Foyle <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Ian Saultz <[email protected]>
Problem / Changes
This PR adds
ai-constructs
package which will host CDK components that support AI based use cases.This PR also adds initial implementation of "conversation handler lambda". I.e.:
handleConversationTurnEvent
(i.e. public facing facade to later allow building handlers with programmatically defined tools).Out of scope (in this PR):
defineConversationHandler
(andbackend-ai
package)Issue number, if available:
Corresponding docs PR, if applicable:
Validation
Added tests.
Checklist
run-e2e
label set.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.