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

Add optional streaming feature using Chat API #55

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.3.0] - 2024-08-29
### Added
Add optional streaming response feature.
- New Lambda function queries the Amazon Q Business Chat API and updates the Slack channel in real-time as LLM generates response.
- Can easily switch between ChatSync and Chat response modes by modifying the Slack app's event subscription endpoint.

## [0.2.0] - 2024-05-28
### Added
Add support for Q Business Apps integrated with IdC
Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,19 @@ Let's now add your app into your workspace, this is required to generate the `Bo
4. Choose `Edit`
5. Replace the value of `OidcClientSecret`, you will find the value in the Okta app client settings (step 1.1).

#### 4.4 (Optional) Configure Slack app to use chat stream feature

To enable the streaming response feature, we need to modify the Slack app.

1. Login to your AWS console
2. In your AWS account go to Cloudformation
3. Copy the URL of the stack output ending with name : `SlackStreamEventHandlerApiEndpoint`.
4. Open the Slack app settings (api.slack.com) and go to the Event Subscriptions section.
5. In the Request URL block, select "change" and paste the copied URL into the "New Request URL" field.
6. Save the changes.

To revert to using the ChatSync feature, follow the same steps, but in step 3, copy the stack output with the name `SlackEventHandlerApiEndpoint` instead.

### Say hello
> Time to say Hi!

Expand Down
13 changes: 13 additions & 0 deletions README_DEVELOPERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,19 @@ Let's now add your app into your workspace, this is required to generate the `Bo
4. Choose `Edit`
5. Replace the value of `OidcClientSecret`, you will find those values in the IdP app client configuration.

#### 4.4 (Optional) Configure Slack app to use chat stream feature

To enable the streaming response feature, we need to modify the Slack app.

1. Login to your AWS console
2. In your AWS account go to Cloudformation
3. Copy the URL of the stack output ending with name : `SlackStreamEventHandlerApiEndpoint`.
4. Open the Slack app settings (api.slack.com) and go to the Event Subscriptions section.
5. In the Request URL block, select "change" and paste the copied URL into the "New Request URL" field.
6. Save the changes.

To revert to using the ChatSync feature, follow the same steps, but in step 3, copy the stack output with the name `SlackEventHandlerApiEndpoint` instead.

### Say hello
> Time to say Hi!

Expand Down
6 changes: 6 additions & 0 deletions bin/convert-cfn-template.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,12 @@ function parameterizeTemplate(template, lambdas) {
Type: 'String',
AllowedPattern: '^arn:aws[a-zA-Z-]*:[a-zA-Z0-9-]*:[a-z0-9-]*:[0-9]{12}:[a-zA-Z0-9:/._-]+$',
Description: 'Q Business Slack Gateway IdC App Arn'
},
ChatStreamBufferSize: {
Type: 'Number',
Default: 25,
MinValue: 1,
Description: 'Length of buffer size updates for ChatStream feature'
}
};
for (let lambda of lambdas) {
Expand Down
7 changes: 5 additions & 2 deletions bin/environment.sh
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ ttl_days=$(prompt_for_value "ContextDaysToLive" "Number of days to keep conversa
oidc_idp_name=$(prompt_for_value "OIDCIdPName" "Name of Identity Provider (Okta, Cognito, Other)" "Okta" "^[a-zA-Z]{1,255}$")
oidc_client_id=$(prompt_for_value "OIDCClientId" "OIDC Client ID" "none" "^[a-zA-Z0-9_-]{1,255}$")
oidc_issuer_url=$(prompt_for_value "OIDCIssuerURL" "OIDC Issuer URL" "none" "^https://[a-zA-Z0-9.-]+(:[0-9]+)?(/.*)?$")
gateway_idc_app_arn=$(prompt_for_value "GatewayIdCAppARN" "Q Gateway IdC App Arn" "none" "^arn:aws[a-zA-Z-]*:[a-zA-Z0-9-]*:[a-z0-9-]*:[0-9]{12}:[a-zA-Z0-9:/._-]+$")
gateway_idc_app_arn=$(prompt_for_value "GatewayIdCAppARN" "Q Gateway IdC App Arn" "none" "^arn:aws[a-zA-Z-]*:[a-zA-Z0-9-]*:[a-z0-9-]*:[0-9]{12}:[a-zA-Z0-9:/._-]+$"),
chatstream_buffer_size=$(prompt_for_value "ChatStreamBufferSize" "ChatStream Buffer Size" "25" "^[1-9][0-9]{0,2}$")

# Create or update the JSON file
cp $json_file $json_file.bak 2> /dev/null
Expand All @@ -74,6 +75,7 @@ jq -n \
--arg oidc_client_id "$oidc_client_id" \
--arg oidc_issuer_url "$oidc_issuer_url" \
--arg gateway_idc_app_arn "$gateway_idc_app_arn" \
--arg chatstream_buffer_size "$chatstream_buffer_size" \
'{
StackName: $stack_name,
AmazonQAppId: $app_id,
Expand All @@ -82,7 +84,8 @@ jq -n \
OIDCIdPName: $oidc_idp_name,
OIDCClientId: $oidc_client_id,
OIDCIssuerURL: $oidc_issuer_url,
GatewayIdCAppARN: $gateway_idc_app_arn
GatewayIdCAppARN: $gateway_idc_app_arn,
ChatStreamBufferSize: $chatstream_buffer_size
}' > "$json_file"

echo "Configuration saved to $json_file"
4 changes: 4 additions & 0 deletions bin/my-amazon-q-slack-bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface StackEnvironment {
OIDCClientId: string;
OIDCIssuerURL: string;
GatewayIdCAppARN: string;
ChatStreamBufferSize: string;
}

const app = new cdk.App();
Expand Down Expand Up @@ -46,6 +47,9 @@ if (environment.OIDCIssuerURL === undefined) {
if (environment.GatewayIdCAppARN === undefined) {
throw new Error('GatewayIdCAppARN is required');
}
if (environment.ChatStreamBufferSize === undefined) {
throw new Error('ChatStreamBufferSize is required');
}

new MyAmazonQSlackBotStack(
app,
Expand Down
12 changes: 9 additions & 3 deletions lib/my-amazon-q-slack-bot-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ export class MyAmazonQSlackBotStack extends cdk.Stack {
ChatPolicy: new PolicyDocument({
statements: [
new PolicyStatement({
actions: ['qbusiness:ChatSync', 'qbusiness:PutFeedback'],
actions: ['qbusiness:ChatSync', 'qbusiness:Chat', 'qbusiness:PutFeedback'],
// parametrized
resources: [`arn:aws:qbusiness:*:*:application/${env.AmazonQAppId}`]
})
Expand Down Expand Up @@ -249,7 +249,7 @@ export class MyAmazonQSlackBotStack extends cdk.Stack {
ChatPolicy: new PolicyDocument({
statements: [
new PolicyStatement({
actions: ['qbusiness:ChatSync', 'qbusiness:PutFeedback'],
actions: ['qbusiness:ChatSync', 'qbusiness:Chat', 'qbusiness:PutFeedback'],
resources: ['arn:aws:qbusiness:*:*:application/*']
})
]
Expand Down Expand Up @@ -316,6 +316,11 @@ export class MyAmazonQSlackBotStack extends cdk.Stack {
handler: 'slack-command-handler',
id: 'SlackCommandHandler',
description: 'Handler for Slack commands'
},
{
handler: 'slack-stream-event-handler',
id: 'SlackStreamEventHandler',
description: 'Handler for Slack events - Streams response'
}
].map((p) => {
const prefix = `${props.stackName}-${p.id}`;
Expand Down Expand Up @@ -345,7 +350,8 @@ export class MyAmazonQSlackBotStack extends cdk.Stack {
OIDC_REDIRECT_URL: oidcCallbackApi.url,
KEY_ARN: kmsKey.keyArn,
Q_USER_API_ROLE_ARN: qUserAPIRole.roleArn,
GATEWAY_IDC_APP_ARN: env.GatewayIdCAppARN
GATEWAY_IDC_APP_ARN: env.GatewayIdCAppARN,
CHATSTREAM_BUFFER_SIZE: env.ChatStreamBufferSize
},
role: slackLambdaExecutionRole,
vpc
Expand Down
Loading