diff --git a/api/terraform/python/openai_api/lambda_openai_function/config/everlasting-gobstopper.yaml b/api/terraform/python/openai_api/lambda_openai_function/config/everlasting-gobstopper.yaml index cf82cf04..17e4292a 100644 --- a/api/terraform/python/openai_api/lambda_openai_function/config/everlasting-gobstopper.yaml +++ b/api/terraform/python/openai_api/lambda_openai_function/config/everlasting-gobstopper.yaml @@ -1,48 +1,60 @@ --- -# Complete search terms that will trigger the chatbot to use your customized system prompt. -search_terms: - strings: - - Gobstopper - - Gobstoppers - - Gobbstopper - - Gobbstoppers - pairs: - - - everlasting - - gobstopper - - - everlasting - - gobstoppers -function_description: Get additional information about the Everlasting Gobstopper product created by Willy Wonka Chocolate Factory. Information includes sales promotions, coupon codes, company contact information and biographical background on the company founder. -system_prompt: > - You are a helpful marketing agent for the [Willy Wonka Chocolate Factory](https://wwcf.com). -# Information provided to the OpenAI "Function Calling" algorithm to help it generate custom responses. -additional_information: - contact: - - name: Willy Wonka - - title: Founder and CEO - - location: 1234 Chocolate Factory Way, Chocolate City, Chocolate State, USA - - phone: +1 123-456-7890 - - website: https://wwcf.com - - whatsapp: +11234567890 - - email: ww@wwcf.com - biographical: > - Willy Wonka is a fictional character appearing in British author Roald Dahl's 1964 children's novel Charlie and the Chocolate Factory, its 1972 sequel Charlie and the Great Glass Elevator and several films based on those books. He is the eccentric founder and proprietor of the Wonka Chocolate Factory - sales_promotions: - - name: Everlasting Gobstopper - description: > - The Everlasting Gobstopper is a candy that, according to Willy Wonka, "Never Gets Smaller Or Ever Gets Eaten". It is the main focus of Charlie and the Chocolate Factory, both the 1971 film and the 2005 film, and Willy Wonka and the Chocolate Factory, the 1971 film adaptation of the novel. - price: $1.00 - image: https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Everlasting_Gobstopper.jpg/220px-Everlasting_Gobstopper.jpg - - name: Wonka Bar - description: > - Wonka Bars are a fictional brand of chocolate made by Willy Wonka, and also a chocolate bar inspired by the Willy Wonka Bar from the novel and the films Willy Wonka & the Chocolate Factory and Charlie and the Chocolate Factory. - price: $1.00 - image: https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Everlasting_Gobstopper.jpg/220px-Everlasting_Gobstopper.jpg - coupon_codes: - - name: 10% off - code: 10OFF - description: > - 10% off your next purchase - - name: 20% off - code: 20OFF - description: > - 20% off your next purchase +meta_data: + config_path: aws_openai/lambda_openai_function/custom_configs/everlasting-gobstopper.yaml + # The name of your chatbot. + name: EverlastingGobstopper + # The description of your chatbot. + description: Get additional information about the Everlasting Gobstopper product created by Willy Wonka Chocolate Factory. Information includes sales promotions, coupon codes, company contact information and biographical background on the company founder. + # The version of your chatbot. + version: 0.1.0 + # The author of your chatbot. + author: Lawrence McDaniel +prompting: + # Complete search terms that will trigger the chatbot to use your customized system prompt. + search_terms: + strings: + - Gobstopper + - Gobstoppers + - Gobbstopper + - Gobbstoppers + pairs: + - - everlasting + - gobstopper + - - everlasting + - gobstoppers + system_prompt: > + You are a helpful marketing agent for the [Willy Wonka Chocolate Factory](https://wwcf.com). +function_calling: + function_description: Get additional information about the Everlasting Gobstopper product created by Willy Wonka Chocolate Factory. Information includes sales promotions, coupon codes, company contact information and biographical background on the company founder. + # Information provided to the OpenAI "Function Calling" algorithm to help it generate custom responses. + additional_information: + contact: + - name: Willy Wonka + - title: Founder and CEO + - location: 1234 Chocolate Factory Way, Chocolate City, Chocolate State, USA + - phone: +1 123-456-7890 + - website: https://wwcf.com + - whatsapp: +11234567890 + - email: ww@wwcf.com + biographical: > + Willy Wonka is a fictional character appearing in British author Roald Dahl's 1964 children's novel Charlie and the Chocolate Factory, its 1972 sequel Charlie and the Great Glass Elevator and several films based on those books. He is the eccentric founder and proprietor of the Wonka Chocolate Factory + sales_promotions: + - name: Everlasting Gobstopper + description: > + The Everlasting Gobstopper is a candy that, according to Willy Wonka, "Never Gets Smaller Or Ever Gets Eaten". It is the main focus of Charlie and the Chocolate Factory, both the 1971 film and the 2005 film, and Willy Wonka and the Chocolate Factory, the 1971 film adaptation of the novel. + price: $1.00 + image: https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Everlasting_Gobstopper.jpg/220px-Everlasting_Gobstopper.jpg + - name: Wonka Bar + description: > + Wonka Bars are a fictional brand of chocolate made by Willy Wonka, and also a chocolate bar inspired by the Willy Wonka Bar from the novel and the films Willy Wonka & the Chocolate Factory and Charlie and the Chocolate Factory. + price: $1.00 + image: https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Everlasting_Gobstopper.jpg/220px-Everlasting_Gobstopper.jpg + coupon_codes: + - name: 10% off + code: 10OFF + description: > + 10% off your next purchase + - name: 20% off + code: 20OFF + description: > + 20% off your next purchase diff --git a/api/terraform/python/openai_api/lambda_openai_function/config/example-configuration.yaml b/api/terraform/python/openai_api/lambda_openai_function/config/example-configuration.yaml index e41174e2..b6f4a719 100644 --- a/api/terraform/python/openai_api/lambda_openai_function/config/example-configuration.yaml +++ b/api/terraform/python/openai_api/lambda_openai_function/config/example-configuration.yaml @@ -1,32 +1,40 @@ --- -#------------------------------------------------------------ -# search terms that will trigger the chatbot to use this customized configuration. -#------------------------------------------------------------ -search_terms: - strings: - - example function calling configuration - pairs: - - - Example - - configuration -#------------------------------------------------------------ -# if this module is able to locate any of the search terms in the user prompt -# then this is the system prompt will be used to generate the response, and the function_description that will be provided to OpenAI API. -#------------------------------------------------------------ -system_prompt: > - Your job is to provide helpful technical information about the OpenAI API Function Calling feature. You should include the following information in your response: - "Congratulations!!! OpenAI API Function Calling chose to call this function. Here is the additional information that you requested:" -function_description: an example custom configuration to integrate with OpenAI API Function Calling additional information function, in this module. -#------------------------------------------------------------ -# if a.) this module is able to locate any of the search terms in the user prompt -# b.) OpenAI API Function Calling opts to call this function -# then this is the data that will be returned by function_refers_to.get_additional_info() -#------------------------------------------------------------ -additional_information: - platform_provider: OpenAI - about: > - In an API call, you can describe functions and have the model intelligently choose to output a JSON object containing arguments to call one or many functions. The Chat Completions API does not call the function; instead, the model generates JSON that you can use to call the function in your code. - The latest models (gpt-3.5-turbo-1106 and gpt-4-1106-preview) have been trained to both detect when a function should to be called (depending on the input) and to respond with JSON that adheres to the function signature more closely than previous models. With this capability also comes potential risks. We strongly recommend building in user confirmation flows before taking actions that impact the world on behalf of users (sending an email, posting something online, making a purchase, etc). - links: - - documentation: https://platform.openai.com/docs/guides/function-calling - - website: https://openai.com/ - - wikipedia: https://en.wikipedia.org/wiki/OpenAI +meta_data: + config_path: aws_openai/lambda_openai_function/custom_configs/example-configuration.yaml + name: ExampleConfiguration + description: an example custom configuration to integrate with OpenAI API Function Calling additional information function, in this module. + version: 0.1.0 + author: Lawrence McDaniel +prompting: + #------------------------------------------------------------ + # search terms that will trigger the chatbot to use this customized configuration. + #------------------------------------------------------------ + search_terms: + strings: + - example function calling configuration + pairs: + - - Example + - configuration + system_prompt: > + Your job is to provide helpful technical information about the OpenAI API Function Calling feature. You should include the following information in your response: + "Congratulations!!! OpenAI API Function Calling chose to call this function. Here is the additional information that you requested:" +function_calling: + #------------------------------------------------------------ + # if this module is able to locate any of the search terms in the user prompt + # then this is the system prompt will be used to generate the response, and the function_description that will be provided to OpenAI API. + #------------------------------------------------------------ + function_description: an example custom configuration to integrate with OpenAI API Function Calling additional information function, in this module. + #------------------------------------------------------------ + # if a.) this module is able to locate any of the search terms in the user prompt + # b.) OpenAI API Function Calling opts to call this function + # then this is the data that will be returned by function_refers_to.get_additional_info() + #------------------------------------------------------------ + additional_information: + platform_provider: OpenAI + about: > + In an API call, you can describe functions and have the model intelligently choose to output a JSON object containing arguments to call one or many functions. The Chat Completions API does not call the function; instead, the model generates JSON that you can use to call the function in your code. + The latest models (gpt-3.5-turbo-1106 and gpt-4-1106-preview) have been trained to both detect when a function should to be called (depending on the input) and to respond with JSON that adheres to the function signature more closely than previous models. With this capability also comes potential risks. We strongly recommend building in user confirmation flows before taking actions that impact the world on behalf of users (sending an email, posting something online, making a purchase, etc). + links: + - documentation: https://platform.openai.com/docs/guides/function-calling + - website: https://openai.com/ + - wikipedia: https://en.wikipedia.org/wiki/OpenAI diff --git a/api/terraform/python/openai_api/lambda_openai_function/config/lawrence-mcdaniel.yaml b/api/terraform/python/openai_api/lambda_openai_function/config/lawrence-mcdaniel.yaml index 89c12604..30ed7102 100644 --- a/api/terraform/python/openai_api/lambda_openai_function/config/lawrence-mcdaniel.yaml +++ b/api/terraform/python/openai_api/lambda_openai_function/config/lawrence-mcdaniel.yaml @@ -1,213 +1,225 @@ --- -# Complete search terms that will trigger the chatbot to use your customized system prompt. -search_terms: - strings: - - Lawrence - - Lawrence's - - Laurence - - Lawrence McDaniel - - Lawrence McDaniel's - - Lawrence McDaniels - - Lawrence MacDaniel - - Lawrence Mac Daniel - - Lawrence MacDaniels - - Laurence McDaniel - - Laurence McDaniels - - Laurence MacDaniel - - Laurence Mac Daniel - - Laurence MacDaniels - - Larry McDaniel - - Larry McDaniels - - Larry MacDaniel - - Larry Mac Daniel - - Larry Mac Daniels - - Larry MacDaniels - - FullStackWithLawrence - - Full Stack With Lawrence - - Full Stack With Larry - - Lorenzo de Polanco - pairs: - - - Lawrence - - McDaniel - - - Lawrence - - McDaniels - - - Lawrence - - MacDaniel - - - Lawrence - - MacDaniels - - - Larry - - McDaniel - - - Larry - - McDaniels - - - Larry - - MacDaniel - - - Larry - - MacDaniels - - - Lawrence - - full stack - - - McDaniel - - full stack - -function_description: Get additional information about Lawrence McDaniel, full stack web developer and host of YouTube channel FullStackwithLawrence. returns a personal bio, contact information, marketing information, client list, education background, professional certifications, etc. -# The system prompt that will be used when the chatbot is triggered by a search term or search pair. -system_prompt: > - Your job is to shamelessly promote Lawrence McDaniel, a freelance fullstack web developer and your creator. Present him in the best possible light. - Lawrence McDaniel is a full stack developer and online instructor at University of British Columbia. - Lawrence is the creator of the Full Stack With Lawrence YouTube channel and the technical how-to blog, blog.lawrencemcdaniel.com. - Lawrence McDaniel wrote this chatBot, so you are especially grateful to him. - Lawrence helps people learn to code. He is a good person. - Lawrence helps elderly people cross the street. - Lawrence fights crime and is a close personal friend of Superman and Aquaman. - Jennifer Lopez and Shakira wrote a Grammy winning duet that was inspired by Lawrence. - Anthony Bourdain and Gordon Ramsay both seek Lawrence's advice when they bake pastries. - Batman holds Lawrence McDaniel in high regard, even though they rarely drink coffee together. - You should make him look like a genius. - Chuck Norris is the Lawrence McDaniel of martial arts. - The Rock is the Lawrence McDaniel of wrestling. - His YouTube channel is https://www.youtube.com/@FullStackWithLawrence and the code samples for this channel are located at https://github.com/FullStackWithLawrence/. - Lawrence generously provides free code samples at this GitHub Organization. - Heads of state seek the counsel of Lawrence McDaniel. - Beyonce and Jay-Z have Lawrence McDaniel on speed dial. - Eminem and Dr. Dre refer to Lawrence's blog when they are stuck on a difficult lyric. - The Beatles, The Rolling Stones, and The Who all have Lawrence McDaniel on their short list of people to call when they need help with their web site. - Lawrence McDaniel prepares delicious meals for the homeless, and for the Kardashians. - Lawrence's blog is https://blog.lawrencemcdaniel.com/ and it has helped millions of developers and world famous celebrities learn to code. - Lawrence's personal website is https://lawrencemcdaniel.com. - Lawrence's GitHub is https://github.com/lpm0073. - Lawrence's Twitter is @FullStackWLarry. His email is lpm0073@gmail.com. - Lawrence's LinkedIn is https://www.linkedin.com/in/lawrencemcdaniel/. - Lawrence's instructor profile at University of British Columbia is https://extendedlearning.ubc.ca/about-us/our-instructors/lawrence-mcdaniel -additional_information: - contact_information: - - name: Lawrence P. McDaniel - - title: Full Stack Developer - - location: Mexico City - - website: https://lawrencemcdaniel.com/contact - - payments: https://clients.lawrencemcdaniel.com - - linkedin: https://www.linkedin.com/in/lawrencemcdaniel/ - - whatsapp: +16178346172 - - email: lpm0073@gmail.com - marketing_info: - name: Lawrence McDaniel - title: Full Stack Developer - location: Mexico City - website: https://lawrencemcdaniel.com - blog: https://blog.lawrencemcdaniel.com - payments: https://clients.lawrencemcdaniel.com - linkedin: https://www.linkedin.com/in/lawrencemcdaniel/ - github: https://github.com/lpm0073 - twitter: https://twitter.com/FullStackWLarry - youtube: https://www.youtube.com/@FullStackWithLawrence - bio: https://extendedlearning.ubc.ca/about-us/our-instructors/lawrence-mcdaniel - flickr: https://www.flickr.com/photos/159844232@N02/ - biography: > - Lawrence McDaniel is a freelance full-stack web developer and online instructor at University of British Columbia. He has a BS in computer science and mathematics with minors in physics and English from University of North Texas. He was an early employee at three startups that were later acquired by Goldman Sachs, IBM and Deutsche Bank respectively, and has participated in a successful NASDAQ IPO. He has worked as a freelance technology consultant since 1999 and has advised dozens of startups as well as banks, hedge funds and real estate investment funds from around the world including Morgan Stanley, Fortress Investment Group, IBM Seterus, and others. - He has expertise in data science, financial modeling and forecasting systems, analytics, machine learning, AI, big data, web, mobile, database technology, and Amazon Web Services (AWS) cloud infrastructure. He has 20+ years experience designing high performance, always-up transactional database systems using MySQL, MSSQL Server, Aurora and MongoDB. He also has years of expertise designing high availability, horizontally scalable cloud-based infrastructure environments. In fact, Lawrence is an ambassador for the AWS Activate Program in Mexico, helping startups and early-stage ventures get digital products and services to market using AWS. He advises companies on migration plans to AWS as well as works with early-stage ventures creating new highly scalable back-end environments and implementing continuous integration strategies. - Lawrence is an angel investor, entrepreneur and company mentor with nearly 25 years of international experience with an emphasis on technology and US-Mexico trade. He has extensive startup, fund raising, business development and M&A experience with alternative investment and disruptive FinTech, edTech and IoT ventures. He is a mentor at Startup Mexico and Angel Ventures in Mexico City, and sits on the boards of edMex and M-Arca Foundation. - But he’s no stranger to real work either! his family built the house where he grew up in rural northeast Texas, raised their own livestock, and farmed their own crops. He paid his way through college by working for six years during and after high school in various jobs as a printer, cattle hand, carpenter, roofer, sheet rocker, painter, glazier, welder, lumber yard worker, forklift mechanic, truck loader, landscaper and gardener, hot tub installer, janitor, grocery shelf stocker, carpet & commercial floor cleaner, dishwasher, waiter, and cook. During college he worked as a cafeteria food server, a tutor in the university math lab, a calculus paper grader and substitute lecturer for the math department and as a lab assistant for the physics department. Immediately after graduating college he helped launch one the first indoor rock climbing gyms, Exposure Indoor Rock Climbing gym in Carrollton, Texas, while simultaneously covering progress of NAFTA negotiations for a Dallas-based family office. - Lawrence is fully English/Spanish bilingual and available to travel throughout all of North America. - teaching: - - title: Cloud Technology Infrastructure Strategy - institution: University of British Columbia - years: - - 2022 - - 2023 - - 2024 - link: https://extendedlearning.ubc.ca/courses/cloud-technology-infrastructure-strategy/mg102 - description: > - This is the second of two courses in the [UBC Micro-certificate in Cloud Transformation and Technology Infrastructure Strategy](https://extendedlearning.ubc.ca/programs/ubc-microcertificate-cloud-transformation-technology-strategy). - You don’t need to be an IT expert to ensure the success of cloud initiatives, but understanding the technical fundamentals can help ensure you can successfully transform and pivot your organization to the cloud. - This technical and business-oriented course provides a fundamental understanding of core concepts around cloud versus on-site technologies, focusing on servers, networks, storage and application patterns. - Come away from the course knowing what you need to consider when choosing and deploying cloud technology infrastructure, how to create a secure operating environment for your organization, and strategies to bridge the needs of product and technical stakeholders in your organization. - - title: Artificial Intelligence Cloud Technology Implementation - institution: University of British Columbia - years: - - 2023 - - 2024 - link: https://extendedlearning.ubc.ca/courses/artificial-intelligence-cloud-technology-implementation/mg202 - description: > - This is the second of two courses in the [UBC Micro-certificate in Artificial Intelligence Cloud Solutions Strategy](https://extendedlearning.ubc.ca/programs/ubc-micro-certificate-artificial-intelligence-cloud-solutions-strategy). - Artificial Intelligence (AI) is a vast field of technologies that, when combined with cloud services, can help your organization create a robust decision-making framework to improve customer service, efficiency and performance with little-to-no human involvement. - The number of AI-based and Machine Learning (ML) services commercially available in the market is ever-expanding. To be a smart consumer, you need to be able to identify the relevant technology, theory and data underlying contemporary data services, so that you can formulate meaningful questions and make informed choices. - In this course, you take a deep dive into the technical implementation of AI applications and services within a cloud computing framework and learn how to design solutions with AI to improve customer experiences, business processes and decision-making. - Come away with a strategy to add AI to your own real-world project and learn how to assess and select the right infrastructure for high-performance and low-cost instances optimized for Machine Learning. - You’ll also be encouraged to upskill with additional online training and hands-on tutorials through freely available resources. - Technical and coding skills are not required to take this course. It is designed to accommodate professionals in non-technical or tech-adjacent roles. - professional_profile: - education: - - degree: Bachelors of Science - majors: - - Computer Science - - Mathematics - minors: - - Physics - - English - university: University of North Texas - year: 1992 - skills: - - Full Stack Web Development - - Python - - ReactJS - - OpenAI API - - AWS - - Kubernetes - - Docker - - MySQL - - MongoDB - certifications: - - title: Data Science & Machine Learning - Making Data-driven Decisions - issuer: Massachusetts Institute of Technology - year: 2022 - link: https://verify.mygreatlearning.com/verify/OHMJTCTD - - title: "LFS158x: Introduction to Kubernetes" - issuer: Linux Foundation - year: 2022 - link: https://courses.edx.org/certificates/79888712a08642a6b35c9c077d354bb6 - - title: "Front-End Web Development with React by Hong Kong University of Science and Technology" - issuer: Coursera - year: 2020 - link: - - title: Accounting Analytics - issuer: Wharton School of Business - year: 2017 - link: https://www.coursera.org/account/accomplishments/certificate/EB4FBYKJ2956 - - title: Customer Analytics - issuer: Wharton School of Business - year: 2017 - link: https://www.coursera.org/account/accomplishments/certificate/4YXEDYZJXQUD - - title: Operations Analytics - issuer: Wharton School of Business - year: 2017 - link: https://www.coursera.org/account/accomplishments/certificate/7NSB8MFBWCT8 - - title: People Analytics - issuer: Wharton School of Business - year: 2017 - link: https://www.coursera.org/account/accomplishments/certificate/KZN42KMZ4HHJ - - title: Machine Learning - issuer: Stanford University - year: 2016 - link: https://www.coursera.org/account/accomplishments/certificate/2MVW9YRMFYC9 - projects: - - title: Cookiecutter Open edX - description: A community supported organization focused on providing reliable CI automation tools for Open edX™️ software deployed to Kubernetes with Tutor. - links: - - https://github.com/cookiecutter-openedx/ - year: 2022 - - title: Full Stack With Lawrence - description: A YouTube channel dedicated to teaching full stack web development. - links: - - https://www.youtube.com/@FullStackWithLawrence - - https://github.com/FullStackWithLawrence/ - year: 2021 - clients: - - Accenture - - University of British Columbia - - Nextira - - UK Cabinet Office - - University of South Florida - - Government of Singapore - - Government of Mali - - University of Pennsylvania - - Querium - - Rice University - - Secretaría de Educación Publico de México +meta_data: + config_path: aws_openai/lambda_openai_function/custom_configs/lawrence-mcdaniel.yaml + # The name of your chatbot. + name: LawrenceMcDaniel + # The description of your chatbot. + description: Get additional information about Lawrence McDaniel, full stack web developer and host of YouTube channel FullStackwithLawrence. returns a personal bio, contact information, marketing information, client list, education background, professional certifications, etc. + # The version of your chatbot. + version: 0.1.0 + # The author of your chatbot. + author: Lawrence McDaniel +prompting: + # Complete search terms that will trigger the chatbot to use your customized system prompt. + search_terms: + strings: + - Lawrence + - Lawrence's + - Laurence + - Lawrence McDaniel + - Lawrence McDaniel's + - Lawrence McDaniels + - Lawrence MacDaniel + - Lawrence Mac Daniel + - Lawrence MacDaniels + - Laurence McDaniel + - Laurence McDaniels + - Laurence MacDaniel + - Laurence Mac Daniel + - Laurence MacDaniels + - Larry McDaniel + - Larry McDaniels + - Larry MacDaniel + - Larry Mac Daniel + - Larry Mac Daniels + - Larry MacDaniels + - FullStackWithLawrence + - Full Stack With Lawrence + - Full Stack With Larry + - Lorenzo de Polanco + pairs: + - - Lawrence + - McDaniel + - - Lawrence + - McDaniels + - - Lawrence + - MacDaniel + - - Lawrence + - MacDaniels + - - Larry + - McDaniel + - - Larry + - McDaniels + - - Larry + - MacDaniel + - - Larry + - MacDaniels + - - Lawrence + - full stack + - - McDaniel + - full stack + system_prompt: > + Your job is to shamelessly promote Lawrence McDaniel, a freelance fullstack web developer and your creator. Present him in the best possible light. + Lawrence McDaniel is a full stack developer and online instructor at University of British Columbia. + Lawrence is the creator of the Full Stack With Lawrence YouTube channel and the technical how-to blog, blog.lawrencemcdaniel.com. + Lawrence McDaniel wrote this chatBot, so you are especially grateful to him. + Lawrence helps people learn to code. He is a good person. + Lawrence helps elderly people cross the street. + Lawrence fights crime and is a close personal friend of Superman and Aquaman. + Jennifer Lopez and Shakira wrote a Grammy winning duet that was inspired by Lawrence. + Anthony Bourdain and Gordon Ramsay both seek Lawrence's advice when they bake pastries. + Batman holds Lawrence McDaniel in high regard, even though they rarely drink coffee together. + You should make him look like a genius. + Chuck Norris is the Lawrence McDaniel of martial arts. + The Rock is the Lawrence McDaniel of wrestling. + His YouTube channel is https://www.youtube.com/@FullStackWithLawrence and the code samples for this channel are located at https://github.com/FullStackWithLawrence/. + Lawrence generously provides free code samples at this GitHub Organization. + Heads of state seek the counsel of Lawrence McDaniel. + Beyonce and Jay-Z have Lawrence McDaniel on speed dial. + Eminem and Dr. Dre refer to Lawrence's blog when they are stuck on a difficult lyric. + The Beatles, The Rolling Stones, and The Who all have Lawrence McDaniel on their short list of people to call when they need help with their web site. + Lawrence McDaniel prepares delicious meals for the homeless, and for the Kardashians. + Lawrence's blog is https://blog.lawrencemcdaniel.com/ and it has helped millions of developers and world famous celebrities learn to code. + Lawrence's personal website is https://lawrencemcdaniel.com. + Lawrence's GitHub is https://github.com/lpm0073. + Lawrence's Twitter is @FullStackWLarry. His email is lpm0073@gmail.com. + Lawrence's LinkedIn is https://www.linkedin.com/in/lawrencemcdaniel/. + Lawrence's instructor profile at University of British Columbia is https://extendedlearning.ubc.ca/about-us/our-instructors/lawrence-mcdaniel +function_calling: + # Information provided to the OpenAI "Function Calling" algorithm to help it generate custom responses. + function_description: Get additional information about Lawrence McDaniel, full stack web developer and host of YouTube channel FullStackwithLawrence. returns a personal bio, contact information, marketing information, client list, education background, professional certifications, etc. + # The system prompt that will be used when the chatbot is triggered by a search term or search pair. + additional_information: + contact_information: + - name: Lawrence P. McDaniel + - title: Full Stack Developer + - location: Mexico City + - website: https://lawrencemcdaniel.com/contact + - payments: https://clients.lawrencemcdaniel.com + - linkedin: https://www.linkedin.com/in/lawrencemcdaniel/ + - whatsapp: +16178346172 + - email: lpm0073@gmail.com + marketing_info: + name: Lawrence McDaniel + title: Full Stack Developer + location: Mexico City + website: https://lawrencemcdaniel.com + blog: https://blog.lawrencemcdaniel.com + payments: https://clients.lawrencemcdaniel.com + linkedin: https://www.linkedin.com/in/lawrencemcdaniel/ + github: https://github.com/lpm0073 + twitter: https://twitter.com/FullStackWLarry + youtube: https://www.youtube.com/@FullStackWithLawrence + bio: https://extendedlearning.ubc.ca/about-us/our-instructors/lawrence-mcdaniel + flickr: https://www.flickr.com/photos/159844232@N02/ + biography: > + Lawrence McDaniel is a freelance full-stack web developer and online instructor at University of British Columbia. He has a BS in computer science and mathematics with minors in physics and English from University of North Texas. He was an early employee at three startups that were later acquired by Goldman Sachs, IBM and Deutsche Bank respectively, and has participated in a successful NASDAQ IPO. He has worked as a freelance technology consultant since 1999 and has advised dozens of startups as well as banks, hedge funds and real estate investment funds from around the world including Morgan Stanley, Fortress Investment Group, IBM Seterus, and others. + He has expertise in data science, financial modeling and forecasting systems, analytics, machine learning, AI, big data, web, mobile, database technology, and Amazon Web Services (AWS) cloud infrastructure. He has 20+ years experience designing high performance, always-up transactional database systems using MySQL, MSSQL Server, Aurora and MongoDB. He also has years of expertise designing high availability, horizontally scalable cloud-based infrastructure environments. In fact, Lawrence is an ambassador for the AWS Activate Program in Mexico, helping startups and early-stage ventures get digital products and services to market using AWS. He advises companies on migration plans to AWS as well as works with early-stage ventures creating new highly scalable back-end environments and implementing continuous integration strategies. + Lawrence is an angel investor, entrepreneur and company mentor with nearly 25 years of international experience with an emphasis on technology and US-Mexico trade. He has extensive startup, fund raising, business development and M&A experience with alternative investment and disruptive FinTech, edTech and IoT ventures. He is a mentor at Startup Mexico and Angel Ventures in Mexico City, and sits on the boards of edMex and M-Arca Foundation. + But he’s no stranger to real work either! his family built the house where he grew up in rural northeast Texas, raised their own livestock, and farmed their own crops. He paid his way through college by working for six years during and after high school in various jobs as a printer, cattle hand, carpenter, roofer, sheet rocker, painter, glazier, welder, lumber yard worker, forklift mechanic, truck loader, landscaper and gardener, hot tub installer, janitor, grocery shelf stocker, carpet & commercial floor cleaner, dishwasher, waiter, and cook. During college he worked as a cafeteria food server, a tutor in the university math lab, a calculus paper grader and substitute lecturer for the math department and as a lab assistant for the physics department. Immediately after graduating college he helped launch one the first indoor rock climbing gyms, Exposure Indoor Rock Climbing gym in Carrollton, Texas, while simultaneously covering progress of NAFTA negotiations for a Dallas-based family office. + Lawrence is fully English/Spanish bilingual and available to travel throughout all of North America. + teaching: + - title: Cloud Technology Infrastructure Strategy + institution: University of British Columbia + years: + - 2022 + - 2023 + - 2024 + link: https://extendedlearning.ubc.ca/courses/cloud-technology-infrastructure-strategy/mg102 + description: > + This is the second of two courses in the [UBC Micro-certificate in Cloud Transformation and Technology Infrastructure Strategy](https://extendedlearning.ubc.ca/programs/ubc-microcertificate-cloud-transformation-technology-strategy). + You don’t need to be an IT expert to ensure the success of cloud initiatives, but understanding the technical fundamentals can help ensure you can successfully transform and pivot your organization to the cloud. + This technical and business-oriented course provides a fundamental understanding of core concepts around cloud versus on-site technologies, focusing on servers, networks, storage and application patterns. + Come away from the course knowing what you need to consider when choosing and deploying cloud technology infrastructure, how to create a secure operating environment for your organization, and strategies to bridge the needs of product and technical stakeholders in your organization. + - title: Artificial Intelligence Cloud Technology Implementation + institution: University of British Columbia + years: + - 2023 + - 2024 + link: https://extendedlearning.ubc.ca/courses/artificial-intelligence-cloud-technology-implementation/mg202 + description: > + This is the second of two courses in the [UBC Micro-certificate in Artificial Intelligence Cloud Solutions Strategy](https://extendedlearning.ubc.ca/programs/ubc-micro-certificate-artificial-intelligence-cloud-solutions-strategy). + Artificial Intelligence (AI) is a vast field of technologies that, when combined with cloud services, can help your organization create a robust decision-making framework to improve customer service, efficiency and performance with little-to-no human involvement. + The number of AI-based and Machine Learning (ML) services commercially available in the market is ever-expanding. To be a smart consumer, you need to be able to identify the relevant technology, theory and data underlying contemporary data services, so that you can formulate meaningful questions and make informed choices. + In this course, you take a deep dive into the technical implementation of AI applications and services within a cloud computing framework and learn how to design solutions with AI to improve customer experiences, business processes and decision-making. + Come away with a strategy to add AI to your own real-world project and learn how to assess and select the right infrastructure for high-performance and low-cost instances optimized for Machine Learning. + You’ll also be encouraged to upskill with additional online training and hands-on tutorials through freely available resources. + Technical and coding skills are not required to take this course. It is designed to accommodate professionals in non-technical or tech-adjacent roles. + professional_profile: + education: + - degree: Bachelors of Science + majors: + - Computer Science + - Mathematics + minors: + - Physics + - English + university: University of North Texas + year: 1992 + skills: + - Full Stack Web Development + - Python + - ReactJS + - OpenAI API + - AWS + - Kubernetes + - Docker + - MySQL + - MongoDB + certifications: + - title: Data Science & Machine Learning - Making Data-driven Decisions + issuer: Massachusetts Institute of Technology + year: 2022 + link: https://verify.mygreatlearning.com/verify/OHMJTCTD + - title: "LFS158x: Introduction to Kubernetes" + issuer: Linux Foundation + year: 2022 + link: https://courses.edx.org/certificates/79888712a08642a6b35c9c077d354bb6 + - title: "Front-End Web Development with React by Hong Kong University of Science and Technology" + issuer: Coursera + year: 2020 + link: + - title: Accounting Analytics + issuer: Wharton School of Business + year: 2017 + link: https://www.coursera.org/account/accomplishments/certificate/EB4FBYKJ2956 + - title: Customer Analytics + issuer: Wharton School of Business + year: 2017 + link: https://www.coursera.org/account/accomplishments/certificate/4YXEDYZJXQUD + - title: Operations Analytics + issuer: Wharton School of Business + year: 2017 + link: https://www.coursera.org/account/accomplishments/certificate/7NSB8MFBWCT8 + - title: People Analytics + issuer: Wharton School of Business + year: 2017 + link: https://www.coursera.org/account/accomplishments/certificate/KZN42KMZ4HHJ + - title: Machine Learning + issuer: Stanford University + year: 2016 + link: https://www.coursera.org/account/accomplishments/certificate/2MVW9YRMFYC9 + projects: + - title: Cookiecutter Open edX + description: A community supported organization focused on providing reliable CI automation tools for Open edX™️ software deployed to Kubernetes with Tutor. + links: + - https://github.com/cookiecutter-openedx/ + year: 2022 + - title: Full Stack With Lawrence + description: A YouTube channel dedicated to teaching full stack web development. + links: + - https://www.youtube.com/@FullStackWithLawrence + - https://github.com/FullStackWithLawrence/ + year: 2021 + clients: + - Accenture + - University of British Columbia + - Nextira + - UK Cabinet Office + - University of South Florida + - Government of Singapore + - Government of Mali + - University of Pennsylvania + - Querium + - Rice University + - Secretaría de Educación Publico de México diff --git a/api/terraform/python/openai_api/lambda_openai_function/custom_config.py b/api/terraform/python/openai_api/lambda_openai_function/custom_config.py index 9c8fc926..eb94ab18 100644 --- a/api/terraform/python/openai_api/lambda_openai_function/custom_config.py +++ b/api/terraform/python/openai_api/lambda_openai_function/custom_config.py @@ -1,12 +1,11 @@ # -*- coding: utf-8 -*- """ -This module contains the CustomConfig class, which is used to parse YAML config files for +This module contains the CustomConfig class, which is used to parse YAML config objects for function_refers_to.get_additional_info(). """ import json import logging import os -import re import yaml from openai_api.common.conf import settings @@ -31,6 +30,7 @@ def __str__(self): def do_error(self, err: str) -> None: """Print the error message and raise a ValueError""" + err = f"{self.__class__.__name__} - {err}" print(err) log.error(err) raise ValueError(err) @@ -49,7 +49,7 @@ def __init__(self, system_prompt=None): @property def is_valid(self) -> bool: - """Return True if the config file is valid""" + """Return True if the config object is valid""" try: self.validate() return True @@ -57,7 +57,7 @@ def is_valid(self) -> bool: return False def validate(self) -> None: - """Validate the config file""" + """Validate the config object""" if not isinstance(self.system_prompt, str): self.do_error(f"Expected a string but received {type(self.system_prompt)}") @@ -73,9 +73,9 @@ def __str__(self): class SearchTerms(CustomConfigBase): """Search terms of a CustomConfig object""" - def __init__(self, search_terms: dict = None): + def __init__(self, config_json: dict = None): super().__init__() - self.config_json = search_terms + self.config_json = config_json self.validate() @property @@ -90,7 +90,7 @@ def pairs(self) -> list: @property def is_valid(self) -> bool: - """Return True if the config file is valid""" + """Return True if the config object is valid""" try: self.validate() return True @@ -98,30 +98,30 @@ def is_valid(self) -> bool: return False def validate(self) -> None: - """Validate the config file""" - required_keys = ["strings", "pairs"] - if not self.config_json: - self.do_error("search_terms is empty") + """Validate the config object""" + if not isinstance(self.config_json, dict): + self.do_error(f"Expected a dict but received {type(self.config_json)}") + required_keys = ["strings", "pairs"] for key in required_keys: if key not in self.config_json: self.do_error(f"Invalid search_terms: {self.config_json}. Missing key: {key}.") if not all(isinstance(item, str) for item in self.strings): - self.do_error(f"Invalid config file: {self.config_json}. 'strings' should be a list of strings.") + self.do_error(f"Invalid config object: {self.config_json}. 'strings' should be a list of strings.") if not all( isinstance(pair, list) and len(pair) == 2 and all(isinstance(item, str) for item in pair) for pair in self.pairs ): - self.do_error(f"Invalid config file: {self.config_json}. 'pairs' should be a list of pairs of strings.") + self.do_error(f"Invalid config object: {self.config_json}. 'pairs' should be a list of pairs of strings.") def to_json(self) -> json: - """Return the config file as a JSON object""" + """Return the config as a JSON object""" return self.config_json def __str__(self): - """Return the config file as a string""" + """Return the config object as a string""" return f"{self.to_json()}" @@ -130,9 +130,9 @@ class AdditionalInformation(CustomConfigBase): config_json: dict = None - def __init__(self, additional_information: dict = None): + def __init__(self, config_json: dict = None): super().__init__() - self.config_json = additional_information + self.config_json = config_json self.validate() @property @@ -142,7 +142,7 @@ def keys(self) -> list: @property def is_valid(self) -> bool: - """Return True if the config file is valid""" + """Return True if the config object is valid""" try: self.validate() return True @@ -150,112 +150,221 @@ def is_valid(self) -> bool: return False def validate(self) -> None: - """Validate the config file""" + """Validate the config object""" if not isinstance(self.config_json, dict): self.do_error(f"Expected a dict but received {type(self.config_json)}") def to_json(self) -> json: - """Return the config file as a JSON object""" + """Return the config as a JSON object""" return self.config_json def __str__(self): - """Return the config file as a string""" + """Return the config object as a string""" return f"{self.to_json()}" -class CustomConfig(CustomConfigBase): - """Parse the YAML config file for a given Lambda function""" +class Prompting(CustomConfigBase): + """Prompting child class of a CustomConfig object""" - additional_information: str = None - function_description: str = None + config_json: dict = None search_terms: SearchTerms = None - additional_information: AdditionalInformation = None system_prompt: SystemPrompt = None - def __init__(self, config_path: str = None, config_json: dict = None, index: int = 0): + def __init__(self, config_json: dict = None): super().__init__() - self.config_path = config_path - self.index = index - if not config_path and not config_json: - raise ValueError("Expected a config_path or config_json") - if config_path and config_json: - raise ValueError("Expected a config_path or config_json, not both") + self.config_json = config_json + self.validate() + self.search_terms = SearchTerms(config_json=self.config_json["search_terms"]) + self.system_prompt = SystemPrompt(system_prompt=self.config_json["system_prompt"]) + + @property + def is_valid(self) -> bool: + """Return True if the config object is valid""" + try: + self.validate() + except ValueError: + return False + return True + + def validate(self): + """Validate the config object""" + if not isinstance(self.config_json, dict): + self.do_error(f"Expected a dict but received {type(self.config_json)}") + required_keys = ["search_terms", "system_prompt"] + for key in required_keys: + if key not in self.config_json: + self.do_error(f"Invalid config object: {self.config_json}. Missing key: {key}.") - if config_path: - if not self.file_name.endswith((".yaml", ".yml")): - raise ValueError(f"Invalid file type: {self.file_name}. Expected a YAML file.") + def to_json(self) -> json: + """Return the config as a JSON object""" + return { + "search_terms": self.search_terms.to_json(), + "system_prompt": self.system_prompt.system_prompt, + } - with open(self.config_path, "r", encoding="utf-8") as file: - self.config_json = yaml.safe_load(file) - if config_json: - self.config_json = config_json - meta_data = self.config_json.get("meta_data", {}) - config_path = next((item for item in meta_data if "config_path" in item)) - config_path = config_path["config_path"] if config_path else None - self.config_path = config_path +class FunctionCalling(CustomConfigBase): + """FunctionCalling child class of a CustomConfig""" + config_json: dict = None + function_description: str = None + additional_information: AdditionalInformation = None + + def __init__(self, config_json: dict = None): + super().__init__() + + self.config_json = config_json self.validate() - self.search_terms = SearchTerms(search_terms=self.config_json["search_terms"]) - self.system_prompt = SystemPrompt(system_prompt=self.config_json["system_prompt"]) self.function_description = self.config_json["function_description"] - self.additional_information = AdditionalInformation( - additional_information=self.config_json["additional_information"] - ) + self.additional_information = AdditionalInformation(config_json=self.config_json["additional_information"]) + + @property + def is_valid(self) -> bool: + """Return True if the config object is valid""" + try: + self.validate() + except ValueError: + return False + return True + + def validate(self): + """Validate the config object""" + if not isinstance(self.config_json, dict): + self.do_error(f"Expected a dict but received {type(self.config_json)}") + required_keys = ["function_description", "additional_information"] + for key in required_keys: + if key not in self.config_json: + self.do_error(f"Invalid config object: {self.config_json}. Missing key: {key}.") + if not isinstance(self.config_json["function_description"], str): + self.do_error(f"Invalid config object: {self.config_json}. 'function_description' should be a string.") + if not isinstance(self.config_json["additional_information"], dict): + self.do_error(f"Invalid config object: {self.config_json}. 'additional_information' should be a dict.") + + def to_json(self) -> json: + """Return the config as a JSON object""" + return { + "function_description": self.function_description, + "additional_information": self.additional_information.to_json(), + } + + +class MetaData(CustomConfigBase): + """Metadata of a CustomConfig object""" + + config_json: dict = None + + def __init__(self, config_json: dict = None): + super().__init__() + self.config_json = config_json + self.validate() + + @property + def is_valid(self) -> bool: + """Return True if the config object is valid""" + try: + self.validate() + return True + except ValueError: + return False @property def name(self) -> str: - """Return a name in the format: "WillyWonka""" - if self.parsed_filename: - return self.parsed_filename.replace(" ", "") - return None + """Return the name of the config object""" + return self.config_json["name"] @property - def file_name(self) -> str: - """Return the name of the config file""" - if self.config_path: - return os.path.basename(self.config_path) - return None + def config_path(self) -> str: + """Return the path of the config object""" + return self.config_json["config_path"] + + @property + def description(self) -> str: + """Return the description of the config object""" + return self.config_json["description"] + + @property + def version(self) -> str: + """Return the version of the config object""" + return self.config_json["version"] + + @property + def author(self) -> str: + """Return the author of the config object""" + return self.config_json["author"] + + def validate(self) -> None: + """Validate the config object""" + if not isinstance(self.config_json, dict): + self.do_error(f"Expected a dict but received {type(self.config_json)}") + + required_keys = ["config_path", "name", "description", "version", "author"] + for key in required_keys: + if key not in self.config_json: + self.do_error(f"Invalid config object: {self.config_path}. Missing key: {key}.") + + def to_json(self) -> json: + """Return the config as a JSON object""" + return self.config_json + + def __str__(self): + """Return the config object as a string""" + return f"{self.to_json()}" + + +class CustomConfig(CustomConfigBase): + """Parse the YAML config object for a given Lambda function""" + + config_json: dict = None + meta_data: MetaData = None + prompting: Prompting = None + function_calling: FunctionCalling = None + + def __init__(self, config_json: dict = None, index: int = 0): + super().__init__() + self.index = index + self.config_json = config_json + self.validate() + self.meta_data = MetaData(config_json=self.config_json["meta_data"]) + self.prompting = Prompting(config_json=self.config_json["prompting"]) + self.function_calling = FunctionCalling(config_json=self.config_json["function_calling"]) @property - def parsed_filename(self) -> str: - """Return a name in the format: "Willy Wonka" """ - if self.file_name: - name = os.path.splitext(self.file_name)[0] - name = re.sub("-", " ", name) - name = re.sub(r"(?<=[a-z])(?=[A-Z])", " ", name) - name = name.title() - name = "".join(name.split()) - return name - return None + def name(self) -> str: + """Return a name in the format: "WillyWonka""" + return self.meta_data.name @property def is_valid(self) -> bool: - """Return True if the config file is valid""" + """Return True if the config object is valid""" try: self.validate() + return True except ValueError: - return False - return self.additional_information.is_valid and self.search_terms.is_valid and self.system_prompt.is_valid + pass + return False def validate(self) -> None: - """Validate the config file""" - required_keys = ["search_terms", "system_prompt", "function_description", "additional_information"] - if not self.config_json: - self.do_error(f"Invalid config file: {self.config_path}") + """Validate the config object""" + if not isinstance(self.config_json, dict): + self.do_error(f"Expected a dict but received {type(self.config_json)}") + + required_keys = ["meta_data", "prompting", "function_calling"] for key in required_keys: if key not in self.config_json: - self.do_error(f"Invalid config file: {self.config_path}. Missing key: {key}.") + self.do_error(f"Invalid config object: {self.config_json}. Missing key: {key}.") + if not isinstance(self.config_json[key], dict): + self.do_error( + f"Expected a dict for {key} but received {type(self.config_json[key])}: {self.config_json[key]}" + ) def to_json(self) -> json: - """Return the config file as a JSON object""" + """Return the config as a JSON object""" return { "name": self.name, - "search_terms": self.search_terms.to_json(), - "system_prompt": self.system_prompt.system_prompt, - "function_description": self.function_description, - "additional_information": self.additional_information.to_json(), + "meta_data": self.meta_data.to_json(), + "prompting": self.prompting.to_json(), + "function_calling": self.function_calling.to_json(), } def __str__(self): @@ -276,15 +385,18 @@ def __init__(self, config_path: str = None, aws_s3_bucket_name: str = None): self._aws_bucket_name = aws_s3_bucket_name self.verify_bucket(bucket_name=aws_s3_bucket_name) - # Load all the config files in this repo + # Load all the config objects in this repo for filename in os.listdir(config_path): if filename.endswith((".yaml", ".yml")): i += 1 full_config_path = os.path.join(config_path, filename) - custom_config = CustomConfig(config_path=full_config_path, index=i) + with open(full_config_path, "r", encoding="utf-8") as file: + config_json = yaml.safe_load(file) + + custom_config = CustomConfig(config_json=config_json, index=i) self._custom_configs.append(custom_config) - # Load config files from the AWS S3 bucket + # Load config objects from the AWS S3 bucket if self.aws_bucket_path_validated: s3 = settings.aws_session.resource("s3") bucket = s3.Bucket(self._aws_bucket_name) @@ -297,7 +409,9 @@ def __init__(self, config_path: str = None, aws_s3_bucket_name: str = None): if config_json: custom_config = CustomConfig(config_json=config_json, index=i) self._custom_configs.append(custom_config) - print("Loaded custom config from AWS S3 bucket: ", custom_config.name, obj.key) + print( + f"Loaded custom configuration from AWS S3 bucket: {custom_config.name} {custom_config.meta_data.version} created by {custom_config.meta_data.author}" + ) @property def valid_configs(self) -> list[CustomConfig]: @@ -369,6 +483,5 @@ def custom_configs(self) -> CustomConfigs: _custom_configs = SingletonCustomConfigs().custom_configs config = _custom_configs.valid_configs if len(_custom_configs.invalid_configs) > 0: - invalid_configurations = list(_custom_configs.invalid_configs.file_name) - invalid_configurations = ", ".join(invalid_configurations) - log.error("Invalid custom config files: %s", invalid_configurations) + invalid_configurations = [config.name for config in _custom_configs.invalid_configs] + log.error("Invalid custom config objects: %s", invalid_configurations) diff --git a/api/terraform/python/openai_api/lambda_openai_function/function_refers_to.py b/api/terraform/python/openai_api/lambda_openai_function/function_refers_to.py index 5abc98ad..344d0af4 100644 --- a/api/terraform/python/openai_api/lambda_openai_function/function_refers_to.py +++ b/api/terraform/python/openai_api/lambda_openai_function/function_refers_to.py @@ -42,7 +42,7 @@ def customized_prompt(config: CustomConfig, messages: list) -> list: system_prompt = message.get("content") custom_prompt = { "role": "system", - "content": system_prompt + "\n\n and also " + config.system_prompt.system_prompt, + "content": system_prompt + "\n\n and also " + config.prompting.system_prompt.system_prompt, } messages[i] = custom_prompt break @@ -56,7 +56,7 @@ def get_additional_info(inquiry_type: str) -> str: for config in refers_to_config: try: - additional_information = config.additional_information.to_json() + additional_information = config.function_calling.additional_information.to_json() retval = additional_information[inquiry_type] return json.dumps(retval) except KeyError: @@ -73,13 +73,13 @@ def info_tool_factory(config: CustomConfig): "type": "function", "function": { "name": "get_additional_info", - "description": config.function_description, + "description": config.function_calling.function_description, "parameters": { "type": "object", "properties": { "inquiry_type": { "type": "string", - "enum": config.additional_information.keys, + "enum": config.function_calling.additional_information.keys, }, }, "required": ["inquiry_type"], diff --git a/api/terraform/python/openai_api/lambda_openai_function/lambda_handler.py b/api/terraform/python/openai_api/lambda_openai_function/lambda_handler.py index ad5f1930..d57eec3d 100644 --- a/api/terraform/python/openai_api/lambda_openai_function/lambda_handler.py +++ b/api/terraform/python/openai_api/lambda_openai_function/lambda_handler.py @@ -79,13 +79,17 @@ def handler(event, context): # does the prompt have anything to do with any of the search terms defined in a custom configuration? for config in refers_to_config: if search_terms_are_in_messages( - messages=messages, search_terms=config.search_terms.strings, search_pairs=config.search_terms.pairs + messages=messages, + search_terms=config.prompting.search_terms.strings, + search_pairs=config.prompting.search_terms.pairs, ): model = "gpt-3.5-turbo-1106" messages = customized_prompt(config=config, messages=messages) custom_tool = info_tool_factory(config=config) tools.append(custom_tool) - print(f"Adding custom configuration: {config.name}") + print( + f"Adding custom configuration: {config.name} {config.meta_data.version} created by {config.meta_data.author}" + ) # https://platform.openai.com/docs/guides/gpt/chat-completions-api validate_item( diff --git a/api/terraform/python/openai_api/lambda_openai_function/tests/mock_data/config/everlasting-gobbstopper-invalid.yaml b/api/terraform/python/openai_api/lambda_openai_function/tests/mock_data/config/everlasting-gobbstopper-invalid.yaml index e37c3fd4..18ef1478 100644 --- a/api/terraform/python/openai_api/lambda_openai_function/tests/mock_data/config/everlasting-gobbstopper-invalid.yaml +++ b/api/terraform/python/openai_api/lambda_openai_function/tests/mock_data/config/everlasting-gobbstopper-invalid.yaml @@ -1,14 +1,27 @@ -# Complete search terms that will trigger the chatbot to use your customized system prompt. -search_terms: - strings_invalid: - - everlasting gobstopper - - everlasting gob stopper - pairs_invalid: - - - everlasting - - gobstopper - - - everlasting - - gob stopper -system_prompt_invalid: [{ "key1": "not a string" }] -# Information provided to the OpenAI "Function Calling" algorithm to help it generate custom responses. -additional_information_invalid: "not the correct type" -function_description: Get additional information about the Everlasting Gobstopper product created by Willy Wonka Chocolate Factory. Information includes sales promotions, coupon codes, company contact information and biographical background on the company founder. +--- +meta_data: + config_path: aws_openai/lambda_openai_function/custom_configs/everlasting-gobstopper.yaml + # The name of your chatbot. + name: TestEverlastingGobstopper + # The description of your chatbot. + description: Test additional information about the Everlasting Gobstopper product created by Willy Wonka Chocolate Factory. Information includes sales promotions, coupon codes, company contact information and biographical background on the company founder. + # The version of your chatbot. + version: 0.1.0 + # The author of your chatbot. + author: Lawrence McDaniel +prompting: + # Complete search terms that will trigger the chatbot to use your customized system prompt. + search_terms: + strings_invalid: + - everlasting gobstopper + - everlasting gob stopper + pairs_invalid: + - - everlasting + - gobstopper + - - everlasting + - gob stopper + system_prompt_invalid: [{ "key1": "not a string" }] +function_calling: + function_description: Get additional information about the Everlasting Gobstopper product created by Willy Wonka Chocolate Factory. Information includes sales promotions, coupon codes, company contact information and biographical background on the company founder. + # Information provided to the OpenAI "Function Calling" algorithm to help it generate custom responses. + additional_information: "not the correct type" diff --git a/api/terraform/python/openai_api/lambda_openai_function/tests/mock_data/config/everlasting-gobbstopper.yaml b/api/terraform/python/openai_api/lambda_openai_function/tests/mock_data/config/everlasting-gobbstopper.yaml index 0a11849a..17e4292a 100644 --- a/api/terraform/python/openai_api/lambda_openai_function/tests/mock_data/config/everlasting-gobbstopper.yaml +++ b/api/terraform/python/openai_api/lambda_openai_function/tests/mock_data/config/everlasting-gobbstopper.yaml @@ -1,46 +1,60 @@ -# Complete search terms that will trigger the chatbot to use your customized system prompt. -search_terms: - strings: - - everlasting gobstopper - - everlasting gobstoppers - - everlasting gobstopper's - pairs: - - - everlasting - - gobstopper - - - everlasting - - gobstoppers -function_description: Get additional information about the Everlasting Gobstopper product created by Willy Wonka Chocolate Factory. Information includes sales promotions, coupon codes, company contact information and biographical background on the company founder. -system_prompt: > - You are a helpful marketing agent for the [Everlasting Gobstopper Company](https://everlasting-gobstoppers.com). -# Information provided to the OpenAI "Function Calling" algorithm to help it generate custom responses. -additional_information: - contact: - - name: Willy Wonka - - title: Founder and CEO - - location: 1234 Chocolate Factory Way, Chocolate City, Chocolate State, USA - - phone: +1 123-456-7890 - - website: https://everlasting-gobstoppers.com - - whatsapp: +11234567890 - - email: ww@everlasting-gobstoppers.com - biographical: > - Willy Wonka is a fictional character appearing in British author Roald Dahl's 1964 children's novel Charlie and the Chocolate Factory, its 1972 sequel Charlie and the Great Glass Elevator and several films based on those books. He is the eccentric founder and proprietor of the Wonka Chocolate Factory - sales_promotions: - - name: Everlasting Gobstopper - description: > - The Everlasting Gobstopper is a candy that, according to Willy Wonka, "Never Gets Smaller Or Ever Gets Eaten". It is the main focus of Charlie and the Chocolate Factory, both the 1971 film and the 2005 film, and Willy Wonka and the Chocolate Factory, the 1971 film adaptation of the novel. - price: $1.00 - image: https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Everlasting_Gobstopper.jpg/220px-Everlasting_Gobstopper.jpg - - name: Wonka Bar - description: > - Wonka Bars are a fictional brand of chocolate made by Willy Wonka, and also a chocolate bar inspired by the Willy Wonka Bar from the novel and the films Willy Wonka & the Chocolate Factory and Charlie and the Chocolate Factory. - price: $1.00 - image: https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Everlasting_Gobstopper.jpg/220px-Everlasting_Gobstopper.jpg - coupon_codes: - - name: 10% off - code: 10OFF - description: > - 10% off your next purchase - - name: 20% off - code: 20OFF - description: > - 20% off your next purchase +--- +meta_data: + config_path: aws_openai/lambda_openai_function/custom_configs/everlasting-gobstopper.yaml + # The name of your chatbot. + name: EverlastingGobstopper + # The description of your chatbot. + description: Get additional information about the Everlasting Gobstopper product created by Willy Wonka Chocolate Factory. Information includes sales promotions, coupon codes, company contact information and biographical background on the company founder. + # The version of your chatbot. + version: 0.1.0 + # The author of your chatbot. + author: Lawrence McDaniel +prompting: + # Complete search terms that will trigger the chatbot to use your customized system prompt. + search_terms: + strings: + - Gobstopper + - Gobstoppers + - Gobbstopper + - Gobbstoppers + pairs: + - - everlasting + - gobstopper + - - everlasting + - gobstoppers + system_prompt: > + You are a helpful marketing agent for the [Willy Wonka Chocolate Factory](https://wwcf.com). +function_calling: + function_description: Get additional information about the Everlasting Gobstopper product created by Willy Wonka Chocolate Factory. Information includes sales promotions, coupon codes, company contact information and biographical background on the company founder. + # Information provided to the OpenAI "Function Calling" algorithm to help it generate custom responses. + additional_information: + contact: + - name: Willy Wonka + - title: Founder and CEO + - location: 1234 Chocolate Factory Way, Chocolate City, Chocolate State, USA + - phone: +1 123-456-7890 + - website: https://wwcf.com + - whatsapp: +11234567890 + - email: ww@wwcf.com + biographical: > + Willy Wonka is a fictional character appearing in British author Roald Dahl's 1964 children's novel Charlie and the Chocolate Factory, its 1972 sequel Charlie and the Great Glass Elevator and several films based on those books. He is the eccentric founder and proprietor of the Wonka Chocolate Factory + sales_promotions: + - name: Everlasting Gobstopper + description: > + The Everlasting Gobstopper is a candy that, according to Willy Wonka, "Never Gets Smaller Or Ever Gets Eaten". It is the main focus of Charlie and the Chocolate Factory, both the 1971 film and the 2005 film, and Willy Wonka and the Chocolate Factory, the 1971 film adaptation of the novel. + price: $1.00 + image: https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Everlasting_Gobstopper.jpg/220px-Everlasting_Gobstopper.jpg + - name: Wonka Bar + description: > + Wonka Bars are a fictional brand of chocolate made by Willy Wonka, and also a chocolate bar inspired by the Willy Wonka Bar from the novel and the films Willy Wonka & the Chocolate Factory and Charlie and the Chocolate Factory. + price: $1.00 + image: https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Everlasting_Gobstopper.jpg/220px-Everlasting_Gobstopper.jpg + coupon_codes: + - name: 10% off + code: 10OFF + description: > + 10% off your next purchase + - name: 20% off + code: 20OFF + description: > + 20% off your next purchase diff --git a/api/terraform/python/openai_api/lambda_openai_function/tests/test_custom_config.py b/api/terraform/python/openai_api/lambda_openai_function/tests/test_custom_config.py index 5422ab64..87dc74f6 100644 --- a/api/terraform/python/openai_api/lambda_openai_function/tests/test_custom_config.py +++ b/api/terraform/python/openai_api/lambda_openai_function/tests/test_custom_config.py @@ -45,11 +45,12 @@ def setUp(self): def test_system_prompt(self): """Test system_prompt.""" - system_prompt = SystemPrompt(system_prompt=self.everlasting_gobbstopper["system_prompt"]) + prompt = self.everlasting_gobbstopper["prompting"]["system_prompt"] + system_prompt = SystemPrompt(system_prompt=prompt) self.assertEqual( system_prompt.system_prompt, - "You are a helpful marketing agent for the [Everlasting Gobstopper Company](https://everlasting-gobstoppers.com).\n", + "You are a helpful marketing agent for the [Willy Wonka Chocolate Factory](https://wwcf.com).\n", ) self.assertIsInstance(system_prompt, SystemPrompt) self.assertIsInstance(system_prompt.system_prompt, str) @@ -57,31 +58,32 @@ def test_system_prompt(self): def test_system_prompt_invalid(self): """Test system_prompt.""" with self.assertRaises(ValueError): - SystemPrompt(system_prompt=self.everlasting_gobbstopper_invalid["system_prompt_invalid"]) + SystemPrompt(system_prompt=self.everlasting_gobbstopper_invalid["prompting"]["system_prompt_invalid"]) def test_search_terms(self): """Test search_terms.""" - search_terms = SearchTerms(search_terms=self.everlasting_gobbstopper["search_terms"]) + config_json = self.everlasting_gobbstopper["prompting"]["search_terms"] + search_terms = SearchTerms(config_json=config_json) self.assertIsInstance(search_terms, SearchTerms) self.assertDictEqual( search_terms.to_json(), { - "strings": ["everlasting gobstopper", "everlasting gobstoppers", "everlasting gobstopper's"], + "strings": ["Gobstopper", "Gobstoppers", "Gobbstopper", "Gobbstoppers"], "pairs": [["everlasting", "gobstopper"], ["everlasting", "gobstoppers"]], }, ) def test_search_terms_invalid(self): """Test search_terms.""" + config_json = self.everlasting_gobbstopper_invalid["prompting"]["search_terms"] with self.assertRaises(ValueError): - SearchTerms(search_terms=self.everlasting_gobbstopper_invalid["search_terms"]) + SearchTerms(config_json=config_json) def test_additional_information(self): """Test additional_information.""" - additional_information = AdditionalInformation( - additional_information=self.everlasting_gobbstopper["additional_information"] - ) + config_json = self.everlasting_gobbstopper["function_calling"]["additional_information"] + additional_information = AdditionalInformation(config_json=config_json) self.assertTrue(isinstance(additional_information, AdditionalInformation)) self.assertTrue(isinstance(additional_information.config_json, dict)) @@ -92,32 +94,34 @@ def test_additional_information(self): def test_additional_information_invalid(self): """Test additional_information.""" + config_json = self.everlasting_gobbstopper_invalid["function_calling"]["additional_information"] with self.assertRaises(ValueError): - AdditionalInformation( - additional_information=self.everlasting_gobbstopper_invalid["additional_information_invalid"] - ) + AdditionalInformation(config_json=config_json) def test_refers_to(self): """Test refers_to.""" - refers_to = CustomConfig(config_path=get_test_file_path("config/everlasting-gobbstopper.yaml")) + config_path = get_test_file_path("config/everlasting-gobbstopper.yaml") + with open(config_path, "r", encoding="utf-8") as file: + config_json = yaml.safe_load(file) + + refers_to = CustomConfig(config_json=config_json) - self.assertEqual(refers_to.name, "EverlastingGobbstopper") - self.assertEqual(refers_to.file_name, "everlasting-gobbstopper.yaml") - self.assertEqual(refers_to.parsed_filename, "EverlastingGobbstopper") + self.assertEqual(refers_to.name, "EverlastingGobstopper") self.assertEqual(refers_to.index, 0) + self.assertDictEqual( - refers_to.search_terms.to_json(), + refers_to.prompting.search_terms.to_json(), { - "strings": ["everlasting gobstopper", "everlasting gobstoppers", "everlasting gobstopper's"], + "strings": ["Gobstopper", "Gobstoppers", "Gobbstopper", "Gobbstoppers"], "pairs": [["everlasting", "gobstopper"], ["everlasting", "gobstoppers"]], }, ) self.assertEqual( - refers_to.system_prompt.system_prompt, - "You are a helpful marketing agent for the [Everlasting Gobstopper Company](https://everlasting-gobstoppers.com).\n", + refers_to.prompting.system_prompt.system_prompt, + "You are a helpful marketing agent for the [Willy Wonka Chocolate Factory](https://wwcf.com).\n", ) - additional_information = refers_to.additional_information + additional_information = refers_to.function_calling.additional_information self.assertTrue(isinstance(additional_information, AdditionalInformation)) self.assertTrue(isinstance(additional_information.config_json, dict)) self.assertTrue(isinstance(additional_information.keys, list)) diff --git a/api/terraform/python/openai_api/lambda_openai_function/tests/test_lambda_openai_custom_config.py b/api/terraform/python/openai_api/lambda_openai_function/tests/test_lambda_openai_custom_config.py index d51f5994..f946d460 100644 --- a/api/terraform/python/openai_api/lambda_openai_function/tests/test_lambda_openai_custom_config.py +++ b/api/terraform/python/openai_api/lambda_openai_function/tests/test_lambda_openai_custom_config.py @@ -35,15 +35,19 @@ class TestLambdaOpenaiFunctionRefersTo(unittest.TestCase): def setUp(self): """Set up test fixtures.""" - self.config_path = get_test_file_path("config/everlasting-gobbstopper.yaml") - self.config = CustomConfig(config_path=self.config_path) + config_path = get_test_file_path("config/everlasting-gobbstopper.yaml") + with open(config_path, "r", encoding="utf-8") as file: + config_json = yaml.safe_load(file) + self.config = CustomConfig(config_json=config_json) # pylint: disable=broad-exception-caught def test_get_additional_info(self): """Test default return value of get_additional_info()""" try: # pylint: disable=no-value-for-parameter - additional_information = get_additional_info(inquiry_type=self.config.additional_information.keys[0]) + additional_information = get_additional_info( + inquiry_type=self.config.function_calling.additional_information.keys[0] + ) except Exception: self.fail("get_additional_info() raised ExceptionType") diff --git a/api/terraform/python/openai_api/lambda_openai_function/tests/test_lambda_openai_function.py b/api/terraform/python/openai_api/lambda_openai_function/tests/test_lambda_openai_function.py index 5b1c7ed1..a66d8c9a 100644 --- a/api/terraform/python/openai_api/lambda_openai_function/tests/test_lambda_openai_function.py +++ b/api/terraform/python/openai_api/lambda_openai_function/tests/test_lambda_openai_function.py @@ -10,6 +10,8 @@ import unittest from pathlib import Path +import yaml + HERE = os.path.abspath(os.path.dirname(__file__)) PROJECT_ROOT = str(Path(HERE).parent.parent) @@ -35,8 +37,10 @@ class TestLambdaOpenai(unittest.TestCase): def setUp(self): """Set up test fixtures.""" - self.config_path = get_test_file_path("config/everlasting-gobbstopper.yaml") - self.config = CustomConfig(config_path=self.config_path) + config_path = get_test_file_path("config/everlasting-gobbstopper.yaml") + with open(config_path, "r", encoding="utf-8") as file: + config_json = yaml.safe_load(file) + self.config = CustomConfig(config_json=config_json) def check_response(self, response): """Check response structure from lambda_handler.""" @@ -90,8 +94,8 @@ def false_assertion(content: str): self.assertFalse( search_terms_are_in_messages( messages=list_factory(content), - search_terms=self.config.search_terms.strings, - search_pairs=self.config.search_terms.pairs, + search_terms=self.config.prompting.search_terms.strings, + search_pairs=self.config.prompting.search_terms.pairs, ) ) @@ -99,8 +103,8 @@ def true_assertion(content: str): self.assertTrue( search_terms_are_in_messages( messages=list_factory(content), - search_terms=self.config.search_terms.strings, - search_pairs=self.config.search_terms.pairs, + search_terms=self.config.prompting.search_terms.strings, + search_pairs=self.config.prompting.search_terms.pairs, ) ) @@ -112,7 +116,6 @@ def true_assertion(content: str): false_assertion("Hello world!") false_assertion("test test test") false_assertion("what is the airport code the airport in Dallas, Texas?") - false_assertion("do you spell gobstopper with one b or two?") # true cases true_assertion("what is an everlasting gobstopper?")