Skip to content

Commit

Permalink
Handler for chat feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
kdid committed Jul 1, 2024
1 parent 24161e1 commit 0fb5f72
Show file tree
Hide file tree
Showing 10 changed files with 8,645 additions and 16,503 deletions.
572 changes: 558 additions & 14 deletions layers/api_dependencies/package-lock.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion layers/api_dependencies/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,18 @@
"dependencies": {
"@aws-crypto/sha256-browser": "^2.0.1",
"@aws-sdk/client-sfn": "^3.563.0",
"@aws-sdk/client-sns": "^3.606.0",
"@aws-sdk/credential-provider-node": "^3.563.0",
"@honeybadger-io/js": "^4.9.3",
"@smithy/node-http-handler": "^2.5.0",
"@smithy/protocol-http": "^3.3.0",
"@smithy/signature-v4": "^2.3.0",
"@honeybadger-io/js": "^4.9.3",
"axios": ">=0.21.1",
"cookie": "^0.5.0",
"debug": "^4.3.4",
"http-status-codes": "^2.2.0",
"iiif-builder": "^1.0.7",
"jsonschema": "^1.4.1",
"jsonwebtoken": "^8.5.1",
"lodash": "^4.17.21",
"lz-string": "^1.4.4",
Expand Down
17,640 changes: 5,530 additions & 12,110 deletions node/package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
},
"devDependencies": {
"@openapitools/openapi-generator-cli": "^2.5.2",
"aws-sdk-client-mock": "^4.0.1",
"chai": "^4.2.0",
"chai-http": "^4.3.0",
"choma": "^1.2.1",
Expand Down
122 changes: 122 additions & 0 deletions node/src/handlers/post-chat-feedback.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
const { wrap } = require("./middleware");
const { PutObjectCommand, S3Client } = require("@aws-sdk/client-s3");
const { SNSClient, PublishCommand } = require("@aws-sdk/client-sns");

const Validator = require("jsonschema").Validator;

const feedbackSchema = {
type: "object",
properties: {
sentiment: { enum: ["positive", "negative"] },
context: {
type: "object",
properties: {
ref: { type: "string" },
question: { type: "string" },
answer: { type: "string" },
source_documents: {
type: "array",
items: { type: "string" },
},
required: ["ref", "question", "answer", "source_documents"],
},
feedback: {
type: "object",
properties: {
options: { type: "array", items: { type: "string" } },
text: { type: "string" },
email: { type: "string" },
},
required: ["options", "text"],
},
},
required: ["sentiment", "context", "feedback"],
},
};

const handler = wrap(async (event, context) => {
if (!event.userToken.isLoggedIn()) {
return {
statusCode: 401,
headers: { "Content-Type": "text/plain" },
body: "Authorization Required",
};
}

// Pass in the S3 and SNS clients if they are injected
// to workound an issue with the mocking library
// https://github.com/m-radzikowski/aws-sdk-client-mock
const s3Client = context?.injections?.s3Client
? context.injections.s3Client
: new S3Client({});
const snsClient = context?.injections?.snsClient
? context.injections.snsClient
: new SNSClient({});

try {
const content = JSON.parse(event.body);
const v = new Validator();
var result = v.validate(content, feedbackSchema);

const errors = result.errors.map((e) => e.stack.replace("instance.", ""));
if (errors.length > 0) {
return {
statusCode: 400,
headers: { "Content-Type": "text/plain" },
body: JSON.stringify(errors.join(", ")),
};
}
await uploadToS3(
s3Client,
`${content.sentiment}/${content.context.ref}`,
content
);

await sendNotification(
snsClient,
`Chat feedback: ${content.sentiment} response (${
process.env.HONEYBADGER_ENV || process.env.DEV_PREFIX || "dev"
})`,
JSON.stringify(content, null, 2)
);

return {
statusCode: 200,
headers: { "content-type": "text/plain" },
body: JSON.stringify({
message: `Feedback received. Thank you.`,
}),
};
} catch (err) {
console.error(err);
return {
statusCode: 500,
headers: { "content-type": "text/plain" },
body: "Internal Server Error",
};
}
});

const uploadToS3 = async (s3Client, key, body) => {
const command = new PutObjectCommand({
Bucket: process.env.CHAT_FEEDBACK_BUCKET,
Key: key,
Body: JSON.stringify(body, null, 2),
ContentType: "application/json",
});

return await s3Client.send(command);
};

const sendNotification = async (snsClient, subject, message) => {
const command = new PublishCommand({
TopicArn: process.env.CHAT_FEEDBACK_TOPIC_ARN,
Subject: subject,
Message: message,
});
const response = await snsClient.send(command);
console.log(response);
return response;
};

module.exports = { handler };
Loading

0 comments on commit 0fb5f72

Please sign in to comment.