Skip to content

Instantly share code, notes, and snippets.

@adamgins
Last active June 19, 2024 05:26
Show Gist options
  • Save adamgins/83bbdd026f730c29f6839e7852af7f76 to your computer and use it in GitHub Desktop.
Save adamgins/83bbdd026f730c29f6839e7852af7f76 to your computer and use it in GitHub Desktop.
Example AWS Lambda Function for the app.aistrategyplan.com to create orgs, teams, generate recomemndations
import axios from "axios";
import _ from "lodash";
import Bottleneck from "bottleneck";
import {
getUserID,
insertMicroAppRow,
getMicroAppDataRow,
getMicroAppData,
updateMicroAppDataRow,
errorResponse,
insertOrganization,
insertTeam,
insertTeamMembers,
} from "buzzy-api-nodejs";
const BUZZY_DEBUG = process.env.BUZZY_DEBUG;
const BUZZY_API_CHECK = process.env.BUZZY_API_CHECK;
const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
const BUZZY_API_USERID = process.env.BUZZY_API_USERID;
const BUZZY_API_TOKEN = process.env.BUZZY_API_TOKEN;
const USER_MICROAPPID = process.env.USER_MICROAPPID;
const ORGANIZATION_MICROAPPID = process.env.ORGANIZATION_MICROAPPID;
const ORGANIZATION_MEMBERS_MICROAPPID =
process.env.ORGANIZATION_MEMBERS_MICROAPPID;
const BUZZY_STRATGARDEN_ORGID = process.env.BUZZY_STRATGARDEN_ORGID;
const STRATEGY_MICROAPPID = process.env.STRATEGY_MICROAPPID;
const PROJECT_MICROAPPID = process.env.PROJECT_MICROAPPID;
const TASK_MICROAPPID = process.env.TASK_MICROAPPID;
const BUZZY_URL = process.env.BUZZY_URL;
const STRATEGY_APP_ID = process.env.STRATEGY_APP_ID;
const STRATEGY_APP_INITALSCREEN_ID = process.env.STRATEGY_APP_INITALSCREEN_ID;
const RECOMMENDATIONS_MICROAPPID = process.env.RECOMMENDATIONS_MICROAPPID;
const RECOMMENDATIONS_STRATEGY_MICROAPPID =
process.env.RECOMMENDATIONS_STRATEGY_MICROAPPID;
const RECOMMENDATIONS_PROJECT_MICROAPPID =
process.env.RECOMMENDATIONS_PROJECT_MICROAPPID;
const RECOMMENDATIONS_TASK_MICROAPPID =
process.env.RECOMMENDATIONS_TASK_MICROAPPID;
const MARKETPLACE_LISTINGS_MICROAPPID =
process.env.MARKETPLACE_LISTINGS_MICROAPPID;
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
export const handler = async (event) => {
// Make a request for a user with a given ID
let currentOrgID = null;
let result;
try {
const { body } = event;
if (!body) {
result = errorResponse("invalid params");
throw new Error("invalid params");
}
const parsedBody = typeof body === "object" ? body : JSON.parse(body);
const {
debug = true,
url = BUZZY_URL,
buzzyAdminToken,
type,
userID,
} = parsedBody || {};
if (!buzzyAdminToken || buzzyAdminToken !== BUZZY_API_CHECK) {
console.log("invalid API request");
result = errorResponse("invalid buzzyAdminToken", buzzyAdminToken);
throw new Error("invalid buzzyAdminToken");
}
const generateRecommendations = async ({
targetMicroApp,
parentRowID,
vectorQuery,
}) => {
const recommendations = await getMicroAppData({
microAppID: MARKETPLACE_LISTINGS_MICROAPPID,
authToken: BUZZY_API_TOKEN,
userId: BUZZY_API_USERID,
url: BUZZY_URL,
optIsVectorSearch: true,
optVectorSearchString: vectorQuery,
optLimit: 5,
});
debug && console.log("recommendations:", recommendations);
if (Array.isArray(recommendations)) {
for (let i = 0; i < recommendations.length; i++) {
const recommendation = recommendations[i];
const { _id: recommendationRowID, listingName } =
recommendation || {};
const insertedRecommendation = await insertMicroAppRow({
microAppID: targetMicroApp,
authToken: BUZZY_API_TOKEN,
userId: BUZZY_API_USERID,
url: BUZZY_URL,
embeddingRowID: parentRowID,
rowData: {
marketplaceListing: {
crossAppRowID: recommendationRowID,
value: {
label: "listingName",
value: listingName,
},
},
},
userID,
});
debug &&
console.log("insertedRecommendation:", insertedRecommendation);
}
}
console.log("recommendations:", recommendations);
};
switch (type) {
case "generate_strategy":
{
debug && console.log("generate_strategy [1]");
const { orgRowID } = parsedBody || {};
currentOrgID = orgRowID;
const currentOrganization = await getMicroAppDataRow({
rowID: orgRowID,
authToken: BUZZY_API_TOKEN,
userId: BUZZY_API_USERID,
url: BUZZY_URL,
});
debug &&
console.log("generate_strategy [2]", { currentOrganization });
const currentUserArray = await getMicroAppData({
microAppID: USER_MICROAPPID,
authToken: BUZZY_API_TOKEN,
userId: BUZZY_API_USERID,
url: BUZZY_URL,
optViewFilters: [
{
userID,
},
],
});
debug && console.log("generate_strategy [2.1]", { currentUserArray });
let currentUser;
if (Array.isArray(currentUserArray) && currentUserArray.length > 0) {
currentUser = currentUserArray[0];
}
debug && console.log("generate_strategy [3]", { currentUser });
if (!currentUser) {
result = errorResponse("User not found");
throw new Error("User not found");
}
debug && console.log("generate_strategy [3.0.0.1] setup");
const teamInfo = {
name: currentOrganization.name || `Team ${currentUser.name}`,
organizationID: BUZZY_STRATGARDEN_ORGID,
};
debug && console.log("generate_strategy [3.0.1]", { teamInfo });
const insertBuzzyTeamResponse = await insertTeam({
authToken: BUZZY_API_TOKEN,
userId: BUZZY_API_USERID,
url: BUZZY_URL,
teamInfo,
});
const { newTeamID: buzzyTeamID } = insertBuzzyTeamResponse || {};
debug &&
console.log("generate_strategy [3.01] teamInsertResponse", {
insertBuzzyTeamResponse,
buzzyTeamID,
});
const newTeamMember = await insertTeamMembers({
authToken: BUZZY_API_TOKEN,
userId: BUZZY_API_USERID,
url: BUZZY_URL,
teamIDs: [buzzyTeamID],
emails: [],
userIDs: [userID],
targetInitialApp: STRATEGY_APP_ID,
targetInitialScreen: STRATEGY_APP_INITALSCREEN_ID,
targetRoute: "app",
});
const updateOrgRow = await updateMicroAppDataRow({
microAppID: ORGANIZATION_MICROAPPID,
authToken: BUZZY_API_TOKEN,
userId: BUZZY_API_USERID,
url: BUZZY_URL,
rowID: orgRowID,
rowData: {
generatingStatus: "Generating",
teamViewers: [buzzyTeamID],
},
});
debug && console.log("generate_strategy [3]", { updateOrgRow });
const {
numberOfEmployees,
challenges: challenges,
description: organizationDescription,
intensiveProcesses,
aiExperience,
} = currentOrganization || {};
const strategyRow = await insertMicroAppRow({
microAppID: ORGANIZATION_MEMBERS_MICROAPPID,
authToken: BUZZY_API_TOKEN,
userId: BUZZY_API_USERID,
url: BUZZY_URL,
embeddingRowID: orgRowID,
rowData: {
role: "Admin",
user: {
crossAppRowID: currentUser._id,
value: { label: "name", value: currentUser.name },
},
},
userID,
});
debug && console.log("generate_strategy [3]", { strategyRow });
// Construct the prompt
const prompt = `Generate an AI business strategy for a company with the following details:
Number of Employees or members: ${numberOfEmployees}
Objectives and Challenges: ${challenges}
Intensive Processes: ${intensiveProcesses}
Existing AI Experience: ${aiExperience}
Take on the role of an AI expert consultant that is experienced with the company above. Assume the company does not know how ot use AI and needs a strategy to get started.
They may not know about cool capabilities like chatGPT and tools like Buzzy (www.buzzy.buzz) and AI powered no code platform. Give them ideas on how they can incorporate AI into their business highlighting potential benerfits.
Organize the recommendations into Strategies, Projects and Tasks that will be helpful for the organization to implement AI in their business.
Take into account the Intensive Processes and Existing AI Experience/Usage of the company provided. If they did not provide these, make some assumptions based on the type of company.
Use the information, including organization size, Objective & Challenges, Intensive (time consuming) Processes and their Existing AI Experience about the company to create a strategies, projects and tasks that are relevant and valuable to them.
If they are using existing AI tools, suggest how they can improve or expand their usage. If they are not using AI, suggest how they can get started.
For each "summary" give 10 - 15 line response in Strategy, Projects and Tasks give enough details for a novice to understand and implement, really take effort as a well communicating AI consultant to explain what the strategy or project is, it's value and where to find more info, assuming the reader has little/no AI knowledge.
Assume an organization will ONLY have the following departments Management, Sales and Marketing, Human Resources, Operations, Finance, IT, Product Development, Services, Administration, Other.
For some inspiration, here are some common AI use cases for businesses:
Process Automation: Identify repetitive, manual tasks that can be automated using AI-powered tools. This can help reduce costs, improve efficiency, and free up human resources for more strategic tasks.
Predictive Analytics: Implement AI-powered predictive analytics to gain insights from large datasets, identify patterns, and make data-driven decisions.
Customer Service: Leverage AI-powered chatbots and virtual assistants to provide 24/7 customer support, improve response times, and enhance the overall customer experience.
Marketing and Sales: Use AI-powered marketing and sales tools to personalize customer interactions, predict customer behavior, and optimize marketing campaigns.
Supply Chain Optimization: Implement AI-powered supply chain management to optimize inventory levels, reduce costs, and improve delivery times.
Cybersecurity: Utilize AI-powered cybersecurity tools to detect and prevent cyber threats, improve incident response, and reduce the risk of data breaches.
HR and Recruitment: Leverage AI-powered HR and recruitment tools to streamline hiring processes, improve candidate matching, and reduce turnover rates.
Product Development: Use AI-powered product development tools to optimize product design, improve quality, and reduce development time.
Financial Analysis: Implement AI-powered financial analysis tools to improve forecasting, budgeting, and financial planning.
Data Management: Utilize AI-powered data management tools to improve data quality, reduce data silos, and enhance data-driven decision-making.
For each "description" in Strategy, Projects and Tasks give enough details, upto 10 paragraphs, for a novice to understand and implement, really take effort as a well communicating AI consultant to explain what the strategy or project is, it's value and where to find more info, assuming the reader has little/no AI knowledge.
Additionally for each Strategy, Projects and Tasks provide a "vectorQuery" that will be used to do a vector search to find experts, tools, events & courses from a marketplace database.
For example, if the task is to "Implement a chatbot for customer support", the vectorQuery could be "chatbot customer support implementation", be sure to include specific context of the strategy, project or task so it's context sensitive, for example "sales strategy for chatbot customer support implementation".
Also create tasks to help fill an expected knowledge gap.
As example tasks for implementing Generative AI to "help with customer support", tasks could be:
1) "Research and select a chatbot platform that can be integrated with the company's website."
2) "Create a list of common customer queries and responses to train the chatbot."
3) "Implement the chatbot on the company's website and test it with a small group of customers."
4) "Analyze the chatbot's performance and make improvements based on feedback."
As an example of creating a project for "Automating repetitive tasks", tasks could be:
1) "Identify the most time-consuming and repetitive tasks in the company."
2) "Research and select automation tools that can help with these tasks."
3) "Create a plan to implement automation for these tasks and estimate the time and cost savings."
4) "Implement the automation tools and train employees on how to use them."
As an exmaple of creaitng a new application to automate/digitize some process using Buzzy, tasks could be:
1) "Identify the process that needs to be automated or digitized."
2) "Create a list of requirements for the new application."
3) "Start with a prompt at www.buzzy.buzz and generate the first app in minutes."
4) "Test the application with a small group of users and gather feedback for improvements."
5) if needed, pull the applicaiton into a Figma for further nocode cusomtization
6) if needed, extend with AI co-pilot code widgets for more complex logic and intergation with APIs
7) Deploy the application to the company's website or intranet and train employees on how to use it.
Each Task Description should have enough detail for a novice to understand and implement, really take effort as a well communicating AI consultant to explain what the task is, it's value and where to find more info, assuming the reader has little/no AI knowledge.
Include recommended AI tools or combinations of AI tools to help achieve a goal. For example, if the task is to "Automate repetitive tasks", you could recommend using a combination of RPA and chatbots.
For the "Task Department", ONLY use the predefined list above.
Please format the response as follows:
{
"strategies": [
{
"name": "<strategy name>",
"summary": "<strategy summary>",
"description": "<strategy description>",
"vectorQuery": "<vectorQuery>",
"projects": [
{
"name": "<project name>",
"summary": "<project summary>",
"description": "<project description>",
"vectorQuery": "<vectorQuery>",
"tasks": [
{
"name": "<task name>",
"description": "<task description>",
"department": "<department>",
"vectorQuery": "<vectorQuery>"
}
]
}
]
}
]
}`;
debug && console.log("About to call chatGPT with prompt:", prompt);
// Axios configuration for POST request
const config = {
method: "post",
url: "https://api.openai.com/v1/chat/completions",
headers: {
Authorization: `Bearer ${OPENAI_API_KEY}`, // Replace with your actual API key
"Content-Type": "application/json",
},
data: {
model: "gpt-4o",
messages: [
{
role: "system",
content:
"You are a helpful assistant who understands AI strategies for businesses. You must respond in JSON only.",
},
{
role: "user",
content: prompt,
},
],
response_format: { type: "json_object" },
},
};
console.log("config:", config);
// Making the POST request
const response = await axios(config);
debug && console.log("response after axios openai", response.data);
const { choices } = response.data || {};
const { message } = choices[0] || {};
debug && console.log("message:", message);
const { content } = message || {};
const parsedContent = content && JSON.parse(content);
debug && console.log("content:", parsedContent);
if (parsedContent) {
const { strategies } = parsedContent || {};
debug && console.log("strategies:", strategies);
if (Array.isArray(strategies)) {
for (let i = 0; i < strategies.length; i++) {
debug && console.log("about to insert strategy");
const strategy = strategies[i];
const {
name: strategyName,
summary: strategySummary,
description: strategyDescription,
projects,
vectorQuery,
} = strategy;
const strategyRow = await insertMicroAppRow({
microAppID: STRATEGY_MICROAPPID,
authToken: BUZZY_API_TOKEN,
userId: BUZZY_API_USERID,
url: BUZZY_URL,
embeddingRowID: orgRowID,
rowData: {
name: strategyName,
summary: strategySummary,
description: strategyDescription,
vectorQuery,
},
userID,
});
debug && console.log("strategyRow:", strategyRow);
if (strategyRow?.rowID) {
debug &&
console.log("about to generate recommendations", {
strategyRowID: strategyRow?.rowID,
vectorQuery,
});
generateRecommendations({
targetMicroApp: RECOMMENDATIONS_STRATEGY_MICROAPPID,
parentRowID: strategyRow?.rowID,
vectorQuery: `${vectorQuery}, ${strategyName}, ${strategySummary}`,
});
}
if (Array.isArray(projects)) {
for (let j = 0; j < projects.length; j++) {
const project = projects[j];
const {
name: projectName,
summary: projectSummary,
description: projectDescription,
tasks,
} = project;
const projectRow = await insertMicroAppRow({
microAppID: PROJECT_MICROAPPID,
authToken: BUZZY_API_TOKEN,
userId: BUZZY_API_USERID,
url: BUZZY_URL,
embeddingRowID: strategyRow.rowID,
rowData: {
name: projectName,
summary: projectSummary,
description: projectDescription,
},
userID,
});
debug && console.log("projectRow:", projectRow);
if (projectRow?.rowID) {
debug &&
console.log("about to generate recommendations", {
projectRowID: projectRow?.rowID,
vectorQuery,
});
generateRecommendations({
targetMicroApp: RECOMMENDATIONS_PROJECT_MICROAPPID,
parentRowID: projectRow?.rowID,
vectorQuery: `${vectorQuery}, ${strategyName}, ${projectName}, ${projectSummary}`,
});
}
if (Array.isArray(tasks)) {
for (let k = 0; k < tasks.length; k++) {
const task = tasks[k];
const { name: taskName, description: taskDescription } =
task;
const taskRow = await insertMicroAppRow({
microAppID: TASK_MICROAPPID,
authToken: BUZZY_API_TOKEN,
userId: BUZZY_API_USERID,
url: BUZZY_URL,
embeddingRowID: projectRow.rowID,
rowData: {
name: taskName,
description: taskDescription,
status: "Not started",
},
userID,
});
debug && console.log("taskRow:", taskRow);
if (taskRow?.rowID) {
debug &&
console.log("about to generate recommendations", {
taskRowID: taskRow?.rowID,
vectorQuery,
});
generateRecommendations({
targetMicroApp: RECOMMENDATIONS_TASK_MICROAPPID,
parentRowID: taskRow?.rowID,
vectorQuery: `${vectorQuery}, ${strategyName}, ${projectName}, ${taskName}, ${taskDescription}`,
});
}
}
}
}
}
}
}
}
await updateMicroAppDataRow({
authToken: BUZZY_API_TOKEN,
userId: BUZZY_API_USERID,
url: BUZZY_URL,
rowID: orgRowID,
rowData: {
generatingStatus: "complete",
},
});
}
break;
case "add_user_to_organization": {
// create a new AI Strategy User
// add the user the Buzzy team
// add the user to the organization members
// invite the user to the organization
const { newOrgMemberRowID } = parsedBody || {};
if (!newOrgMemberRowID) {
debug &&
console.log("add_user_to_organization [0]", {
newOrgMemberRowID,
});
result = errorResponse("invalid params");
throw new Error("invalid params");
}
debug && console.log("add_user_to_organization [1]");
sleep(2000);
const currentOrgMember = await getMicroAppDataRow({
rowID: newOrgMemberRowID,
authToken: BUZZY_API_TOKEN,
userId: BUZZY_API_USERID,
url: BUZZY_URL,
});
debug &&
console.log("add_user_to_organization [2]", { currentOrgMember });
if (!currentOrgMember) {
result = errorResponse("Org member not found");
throw new Error("Org member not found");
}
const { inviteEmail } = currentOrgMember || {};
let currentUserRowID = null;
const existingUser = await getMicroAppData({
microAppID: USER_MICROAPPID,
authToken: BUZZY_API_TOKEN,
userId: BUZZY_API_USERID,
url: BUZZY_URL,
optViewFilters: [
{
sortVal2: inviteEmail,
},
],
});
if (Array.isArray(existingUser) && existingUser.length > 0) {
currentUserRowID = existingUser[0]._id;
} else {
const { rowID: newUserID } =
(await insertMicroAppRow({
microAppID: USER_MICROAPPID,
authToken: BUZZY_API_TOKEN,
userId: BUZZY_API_USERID,
url: BUZZY_URL,
rowData: {
name: "",
emailAddress: inviteEmail,
},
})) || {};
debug && console.log("add_user_to_organization [3]", { newUserID });
currentUserRowID = newUserID;
}
debug &&
console.log("add_user_to_organization [3.1]", { currentUserRowID });
debug &&
console.log(
"add_user_to_organization [3.1.1] about to insert Team member",
{
teamIDs: currentOrgMember.teamViewers,
emails: [inviteEmail],
userIDs: [],
targetInitialApp: STRATEGY_APP_ID,
targetInitialScreen: STRATEGY_APP_INITALSCREEN_ID,
targetRoute: "app",
}
);
const newTeamMember = await insertTeamMembers({
authToken: BUZZY_API_TOKEN,
userId: BUZZY_API_USERID,
url: BUZZY_URL,
teamIDs: currentOrgMember.teamViewers,
emails: [inviteEmail],
userIDs: [],
targetInitialApp: STRATEGY_APP_ID,
targetInitialScreen: STRATEGY_APP_INITALSCREEN_ID,
targetRoute: "app",
});
debug &&
console.log("add_user_to_organization [3.2]", { newTeamMember });
const invitedBuzzyUserIDResponse = await getUserID({
authToken: BUZZY_API_TOKEN,
userId: BUZZY_API_USERID,
url: BUZZY_URL,
email: inviteEmail,
});
debug &&
console.log("add_user_to_organization [3.3]", {
invitedBuzzyUserIDResponse,
});
const { userID: creatorID } = invitedBuzzyUserIDResponse || {};
if (!invitedBuzzyUserIDResponse || !creatorID) {
result = errorResponse("User not found");
throw new Error("User not found");
}
debug &&
console.log("add_user_to_organization [4.0] about to udpate", {
rowID: newOrgMemberRowID,
rowData: {
user: {
crossAppRowID: currentUserRowID,
value: { label: "name", value: inviteEmail },
},
},
creatorID,
});
const updatedOrgMember = await updateMicroAppDataRow({
authToken: BUZZY_API_TOKEN,
userId: BUZZY_API_USERID,
url: BUZZY_URL,
rowID: newOrgMemberRowID,
rowData: {
user: {
crossAppRowID: currentUserRowID,
value: { label: "name", value: inviteEmail },
},
},
creatorID,
});
debug &&
console.log("add_user_to_organization [4]", { updatedOrgMember });
const updatedNewUser = await updateMicroAppDataRow({
authToken: BUZZY_API_TOKEN,
userId: BUZZY_API_USERID,
url: BUZZY_URL,
rowID: currentUserRowID,
rowData: {},
creatorID,
});
debug &&
console.log("add_user_to_organization [5]", { updatedNewUser });
break;
}
default:
break;
}
} catch (error) {
console.log("Lambda error[0]", { error, currentOrgID });
const updateOrgRow =
currentOrgID &&
(await updateMicroAppDataRow({
authToken: BUZZY_API_TOKEN,
userId: BUZZY_API_USERID,
url: BUZZY_URL,
rowID: currentOrgID,
rowData: {
generatingStatus: "Error",
error: JSON.stringify(error),
},
}));
return errorResponse(error);
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment