Мне нужно интегрировать Amazon lex с Amazon lambda. Я столкнулся с одной проблемой. Я новичок в этом, поэтому, пожалуйста, помогите мне. Я хочу запросить продукт с помощью Lex. «Где я могу найти мясо» и мясо будет храниться в слоте "SearchProduct" Затем он выполнит поиск в базе данных и ответит через lex. Как "я нашел мясо в проходе № 4"
Здесь я могу получить значение Прохода № 4 путем сканирования в Dynamodb, но я не могу отправить ответ.
'use strict';
const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient({ region: "us-east-1" });
var reply = ' ';
// --------------- Helpers to build responses which match the structure of the necessary dialog actions -----------------------
function elicitSlot(sessionAttributes, intentName, slots, slotToElicit, message, responseCard) {
return {
sessionAttributes,
dialogAction: {
type: 'ElicitSlot',
intentName,
slots,
slotToElicit,
message,
responseCard,
},
};
}
function close(sessionAttributes, fulfillmentState, message, responseCard) {
return {
sessionAttributes,
dialogAction: {
type: 'Close',
fulfillmentState,
message,
responseCard,
},
};
}
function delegate(sessionAttributes, slots) {
return {
sessionAttributes,
dialogAction: {
type: 'Delegate',
slots,
},
};
}
// ---------------- Helper Functions --------------------------------------------------
// build a message for Lex responses
function buildMessage(messageContent) {
return {
contentType: 'PlainText',
content: messageContent,
};
}
// --------------- Functions that control the skill's behavior -----------------------
/**
* Performs dialog management and fulfillment for ordering a beverage.
* (we only support ordering a mocha for now)
*/
function ItemSearch(intentRequest, callback) {
const outputSessionAttributes = intentRequest.sessionAttributes;
const source = intentRequest.invocationSource;
if (source === 'FulfillmentCodeHook') {
const slots = intentRequest.currentIntent.slots;
const requestProductName = (slots.SearchProduct ? slots.SearchProduct : null);
var scanningParameters = {
TableName: "my table name",
ProjectionExpression: "#pro, Aisle",
FilterExpression: "contains (#pro, :productname)",
ExpressionAttributeNames: {
"#pro": "ProductName",
},
ExpressionAttributeValues: {
":productname": requestProductName
}
};
docClient.scan(scanningParameters, function(err, data) {
if (err) {
callback(close(outputSessionAttributes, 'Fulfilled', { contentType: 'PlainText', content: 'not found' }));
}
else {
console.info(data);
if (data.Count == 0) {
reply = 'not found';
callback(close(outputSessionAttributes, 'Fulfilled', { contentType: 'PlainText', content: 'not found' }));
}
else {
reply = requestProductName + ' can be found in Aisle No: ' + data.Items[0].Aisle;
callback(close(outputSessionAttributes, 'Fulfilled', { contentType: 'PlainText', content: requestProductName + ' can be found in Aisle No: ' + data.Items[0].Aisle }));
}
}
});
}
callback(close(outputSessionAttributes, 'Fulfilled', {
contentType: 'PlainText',
content: `Thanks for using CoffeeBot! ` // i want the reply from the search here but i always end up with null
}));
}
// --------------- Intents -----------------------
/**
* Called when the user specifies an intent for this skill.
*/
function dispatch(intentRequest, callback) {
console.info(`dispatch userId=${intentRequest.userId}, intent=${intentRequest.currentIntent.name}`);
const name = intentRequest.currentIntent.name;
// dispatch to the intent handlers
if (name.startsWith('Product')) {
return ItemSearch(intentRequest, callback);
}
throw new Error(`Intent with name ${name} not supported`);
}
// --------------- Main handler -----------------------
// Route the incoming request based on intent.
// The JSON body of the request is provided in the event slot.
exports.handler = (event, context, callback) => {
console.info(JSON.stringify(event));
try {
console.info(`event.bot.name=${event.bot.name}`);
// fail if this function is for a different bot
if (!event.bot.name.startsWith('Aowi')) {
callback('Invalid Bot Name');
}
dispatch(event, (response) => callback(null, response));
}
catch (err) {
callback(err);
}
};
Я получаю ответ от поиска, но не могу отправить ответ Лексу. Содержательная часть всегда пуста.
Response:
{
"sessionAttributes": {},
"dialogAction": {
"type": "Close",
"fulfillmentState": "Fulfilled",
"message": {
"contentType": "PlainText",
"content": " "
}
}
}
Лекс отправит слот с именем «SearchProduct» == «мясо».
Я не уверен, в какой части я делаю это неправильно. Благодарю, если кто-нибудь может помочь мне улучшить код. Спасибо





Эта ошибка возникает из-за того, что Amazon Lex ожидает ответов в определенном формате JSON. Судя по всему, вы написали код на Node.js. Я не эксперт по узлам, но могу предоставить вам рабочий пример того, как я отправляю ответ обратно в lex.
Последовательность кода выглядит примерно так:
Intent called -> Lambda function invoked -> (Your lamba code runs and process the data given by lex) -> You generate a response to send back to Lex -> Lex reads the Response json and interprets it based on what you have returned.
def close(fulfillment_state, message):
response = {
'dialogAction': {
'type': 'Close',
'fulfillmentState': fulfillment_state,
'message': message
}
}
return response
response_to_lex = close('Fulfilled',{'contentType': 'PlainText','content': 'Message i want to send to lex'})
Функция close создает событие завершения типа «Close» для lex и генерирует соответствующее ответное сообщение. Примечание: type, fulfullmentState и сообщение - обязательные параметры, которые необходимо передать обратно в lex.
Эта ссылка может быть полезна, чтобы понять это глубже: Lex Docs
Также просматривая документацию для LEX и Node Lambda на здесь, я вижу, что метод вызова функции диспетчеризации отличается. Но здесь я могу ошибаться.
Вы должны отправить ответ в определенном формате. Для Node.js ниже приведен пример
const response = {
dialogAction: {
type: "Close",
fulfillmentState: "Fulfilled",
message: {
contentType: "PlainText",
content: "i have found Meat in Aisle no 4"
}
}
};
callback(null, response);
Можете ли вы принять ответ, если он вам поможет?