proactive agent proxy now runs models for responses
This commit is contained in:
parent
166cded7da
commit
27d7474354
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"user": {
|
||||||
|
"name": "Proactive Agent",
|
||||||
|
"avatar": "https://storage.googleapis.com/speakeasyai-agent-desktop/img/verint-logo.png",
|
||||||
|
"userId": "d4de56b5-3fac-4a42-892f-ebec914b6aa3",
|
||||||
|
"type": "bot"
|
||||||
|
},
|
||||||
|
"modelName": "proactiveAgent"
|
||||||
|
}
|
||||||
@ -0,0 +1,289 @@
|
|||||||
|
console.log({ query: req.query, params: req.params, body: req.body });
|
||||||
|
|
||||||
|
const msgrSettings = settings_667ef98d3ee8930a5debcbdb;
|
||||||
|
const paSettings = proactive_agent_settings;
|
||||||
|
const studioToken = msgrSettings
|
||||||
|
? {
|
||||||
|
Authorization: `Bearer ${msgrSettings.messenger.token}`,
|
||||||
|
}
|
||||||
|
: {};
|
||||||
|
|
||||||
|
let bot_user = {
|
||||||
|
...paSettings.user,
|
||||||
|
};
|
||||||
|
|
||||||
|
const app = {
|
||||||
|
routes: [],
|
||||||
|
route: function (regexp, fn) {
|
||||||
|
this.routes.push({ regexp: new RegExp(regexp), function: fn });
|
||||||
|
},
|
||||||
|
run: function (req, res) {
|
||||||
|
const path =
|
||||||
|
req.params[0].split(
|
||||||
|
`/ProxyScript/run/${req.params.workspaceId}/${req.params.branch}/${req.params.route}`
|
||||||
|
)[1] || "/";
|
||||||
|
|
||||||
|
for (var route of this.routes) {
|
||||||
|
console.log(`Checking route: ${route.regexp}`);
|
||||||
|
console.log(`Against path: ${path}`);
|
||||||
|
if (route.regexp.test(path)) {
|
||||||
|
console.log(`Running route: ${route.regexp}`);
|
||||||
|
console.log(`Path: ${path}`);
|
||||||
|
console.log(`Function: ${route.function.name}`);
|
||||||
|
route.function(req, res, route.regexp.exec(path));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If no route matches, return a 404 status
|
||||||
|
const status = { path: req.params[0], status: 404 };
|
||||||
|
res.status(404).send(status);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const redisKey = (userId) => {
|
||||||
|
return `user-map-${userId}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const axioshelper = (message, config, callback, retries = 3, delay = 100) => {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
for (let i = 0; i < retries; i++) {
|
||||||
|
try {
|
||||||
|
const response = await axios(config);
|
||||||
|
console.log({ response: response });
|
||||||
|
if (response.status < 200 || response.status > 299) {
|
||||||
|
if (callback) {
|
||||||
|
await callback();
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
`Axios Request failed! ${JSON.stringify(response)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolve(response);
|
||||||
|
break;
|
||||||
|
} catch (error) {
|
||||||
|
if (error.response) {
|
||||||
|
// The request was made and the server responded with a status code
|
||||||
|
// that falls out of the range of 2xx
|
||||||
|
console.log(error.response.data);
|
||||||
|
console.log(error.response.status);
|
||||||
|
console.log(error.response.headers);
|
||||||
|
} else if (error.request) {
|
||||||
|
// The request was made but no response was received
|
||||||
|
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
||||||
|
// http.ClientRequest in node.js
|
||||||
|
console.log(error.request);
|
||||||
|
} else {
|
||||||
|
// Something happened in setting up the request that triggered an Error
|
||||||
|
console.log("Error", error.message);
|
||||||
|
}
|
||||||
|
console.log(error.config);
|
||||||
|
if (i === retries - 1) {
|
||||||
|
if (callback) {
|
||||||
|
await callback();
|
||||||
|
}
|
||||||
|
console.log({
|
||||||
|
retry: i + 1,
|
||||||
|
error: "out of retries",
|
||||||
|
message,
|
||||||
|
url: config.url,
|
||||||
|
});
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
console.log({
|
||||||
|
level: "warn",
|
||||||
|
message: `Attempt ${i + 1} failed.`,
|
||||||
|
url: config.url,
|
||||||
|
});
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
app.route("^(?:/userId/([^/]+))(?:/$)?$", async (req, res, match) => {
|
||||||
|
try {
|
||||||
|
console.log("Received request for userId:", match[1]);
|
||||||
|
const modelName =
|
||||||
|
req.params?.modelName || proactive_agent_settings.modelName;
|
||||||
|
if (match.length > 1) {
|
||||||
|
const userId = match[1];
|
||||||
|
const smStr = redisKey(userId);
|
||||||
|
const sessionMap = await redis.hGetAll(smStr);
|
||||||
|
const metadata = {
|
||||||
|
userId: bot_user.userId,
|
||||||
|
};
|
||||||
|
|
||||||
|
const recognizedData = await axios
|
||||||
|
.post(
|
||||||
|
`${settings_667ef98d3ee8930a5debcbdb.nlu.apiBaseURL}Model/run/${req.params.workspaceId}/${req.params.branch}/${modelName}`,
|
||||||
|
{
|
||||||
|
input: req.body.input,
|
||||||
|
conversationId: sessionMap.conversationId,
|
||||||
|
settings: settings_667ef98d3ee8930a5debcbdb.nlu.settings,
|
||||||
|
metadata: metadata,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
return response.data;
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
//If we have error handling turned off, don't record the error
|
||||||
|
if (settings_667ef98d3ee8930a5debcbdb.errorHandling === false) {
|
||||||
|
throw error;
|
||||||
|
} else {
|
||||||
|
// Conversation ID is generated by the NLU
|
||||||
|
// Must make sure Conversation ID is created properly for an error transaction
|
||||||
|
// Get it from session map if it exists, or generate it if we got the error at the very first transaction.
|
||||||
|
const conversationId = sessionMap.conversationId || uuidv4();
|
||||||
|
let errorPayload = {
|
||||||
|
id: uuidv4(),
|
||||||
|
workspaceId: req.params.workspaceId,
|
||||||
|
errorInfo: {
|
||||||
|
name: error.name,
|
||||||
|
message: error.message,
|
||||||
|
stack: error.stack,
|
||||||
|
},
|
||||||
|
conversationId,
|
||||||
|
input: req.body.input,
|
||||||
|
answers: [settings_667ef98d3ee8930a5debcbdb.responses.modelError],
|
||||||
|
req: {
|
||||||
|
params: req.params,
|
||||||
|
query: req.query,
|
||||||
|
body: req.body,
|
||||||
|
headers: req.headers,
|
||||||
|
},
|
||||||
|
metadata,
|
||||||
|
classificationResults: [
|
||||||
|
{
|
||||||
|
label: "Model Error",
|
||||||
|
value: 0.0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
nerResults: {
|
||||||
|
entities: [],
|
||||||
|
sourceEntities: [],
|
||||||
|
},
|
||||||
|
// Reporting tags to match GlobalSupport function reporting
|
||||||
|
tag: "ERROR",
|
||||||
|
reporting: {
|
||||||
|
tag: "ERROR",
|
||||||
|
modelResponse: "ERROR",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add model name
|
||||||
|
errorPayload.req.params.route = modelName;
|
||||||
|
|
||||||
|
//add any other details you wish to see in transaction data
|
||||||
|
|
||||||
|
return errorPayload;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// console.log(recognizedData);
|
||||||
|
if (recognizedData.conversationId) {
|
||||||
|
await redis.hSet(
|
||||||
|
smStr,
|
||||||
|
"conversationId",
|
||||||
|
recognizedData.conversationId
|
||||||
|
);
|
||||||
|
await redis.expire(smStr, 3600);
|
||||||
|
if (sessionMap.conversationId) {
|
||||||
|
} else {
|
||||||
|
db.analytics.addConversation({
|
||||||
|
id: recognizedData.conversationId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
recognizedData._id = (
|
||||||
|
await db.analytics.addTransaction(recognizedData)
|
||||||
|
).insertedId;
|
||||||
|
|
||||||
|
// Send Answers to Messenger
|
||||||
|
new Promise(async (resolve) => {
|
||||||
|
for (const [index, answer] of recognizedData.answers.entries()) {
|
||||||
|
try {
|
||||||
|
await axios.post(
|
||||||
|
`${settings_667ef98d3ee8930a5debcbdb.messenger.apiBaseURL}Event/create`,
|
||||||
|
{
|
||||||
|
conversationId: sessionMap.sessionId,
|
||||||
|
metadata: {
|
||||||
|
channel: "web",
|
||||||
|
},
|
||||||
|
input: answer,
|
||||||
|
sentBy: bot_user,
|
||||||
|
ping: nanoid(),
|
||||||
|
sentAt: Date.now(),
|
||||||
|
options: recognizedData?.options,
|
||||||
|
metadata: {
|
||||||
|
outputs:
|
||||||
|
recognizedData.answers.length == index + 1
|
||||||
|
? recognizedData?.outputs
|
||||||
|
: {},
|
||||||
|
transactionId: recognizedData._id,
|
||||||
|
feedbackable: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${settings_667ef98d3ee8930a5debcbdb.messenger.token}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
resolve(true);
|
||||||
|
});
|
||||||
|
res.send(recognizedData);
|
||||||
|
} else {
|
||||||
|
res.status(400).send({ error: "Bad Request" });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return res.status(500).send({
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.route("/", async (req, res) => {
|
||||||
|
const sessionId = req.body.event?.conversationId;
|
||||||
|
const params = req.body.event?.params || {};
|
||||||
|
const modelName =
|
||||||
|
params?.modelName || settings_667ef98d3ee8930a5debcbdb.nlu.modelName;
|
||||||
|
const env = params?.env;
|
||||||
|
const postBack = req.body.event?.postBack;
|
||||||
|
const metadata = {
|
||||||
|
...req.body.event?.metadata,
|
||||||
|
userId: req.body.event?.sentBy?.userId,
|
||||||
|
};
|
||||||
|
const configuration = req.body.event?.configuration;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const umStr = redisKey(metadata.userId);
|
||||||
|
|
||||||
|
await redis.hSet(umStr, "sessionId", sessionId);
|
||||||
|
await redis.expire(umStr, 3600);
|
||||||
|
|
||||||
|
await axioshelper("messenger join", {
|
||||||
|
method: "post",
|
||||||
|
url: `${msgrSettings.messenger.apiBaseURL}Conversation/join`,
|
||||||
|
headers: studioToken,
|
||||||
|
data: {
|
||||||
|
_id: sessionId,
|
||||||
|
participant: bot_user,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
res.send();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error.message);
|
||||||
|
res.send({
|
||||||
|
answers: ["Something went wrong. Please try again."],
|
||||||
|
outputs: {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.run(req, res);
|
||||||
25
proactiveAgent/snippets/DigitalWelcomeEvent.js
Normal file
25
proactiveAgent/snippets/DigitalWelcomeEvent.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Add this code to the Messenger's 'On Engagement Load' block
|
||||||
|
window.askIVA = (input, postBack, metadata, configuration) => {
|
||||||
|
// store.main.showMessenger();
|
||||||
|
// store.main.setView("chat");
|
||||||
|
// store.main.setNcPing(crypto.randomUUID());
|
||||||
|
store.conversationEvent.sendMessage({
|
||||||
|
input,
|
||||||
|
postBack,
|
||||||
|
metadata,
|
||||||
|
configuration,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set form when messenger is opened
|
||||||
|
vm.$watch(
|
||||||
|
() => store.main.newConversation,
|
||||||
|
async (value) => {
|
||||||
|
if (value) {
|
||||||
|
console.log("Starting New Conversation...");
|
||||||
|
setTimeout(() => {
|
||||||
|
window.askIVA("Digital Wecome Event");
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
17
proactiveAgent/snippets/join.js
Normal file
17
proactiveAgent/snippets/join.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
(async () => {
|
||||||
|
proactive_agent.joinConversation(conversationData.id);
|
||||||
|
})()
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error.message);
|
||||||
|
recognizedObject.answers.push("");
|
||||||
|
recognizedObject.errorInfo = {
|
||||||
|
...recognizedObject.errorInfo,
|
||||||
|
label: {
|
||||||
|
data: error.toJSON ? error.toJSON() : {},
|
||||||
|
message: error.message,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
next();
|
||||||
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user