From ed5d5b3ce5794f3b6cede64b4c2a39948494f431 Mon Sep 17 00:00:00 2001 From: lpm0073 Date: Sat, 27 Jan 2024 17:41:30 -0600 Subject: [PATCH 1/4] test: add unit tests for new classes --- .coverage | Bin 53248 -> 53248 bytes .../tests/test_custom_config.py | 35 ++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/.coverage b/.coverage index 336b0d6a422bbe90ece09e46d8b31d83a1ccbd53..dc1ac23de5c3f98c4a5bd5e9983793bb1c480bc4 100644 GIT binary patch delta 629 zcmZozz}&Eac>{|BvnYGdWOfHRURTbuoIV^kIFi_ZvG;5i6o_JH$`PH+=#k4PGCAKP zomH5Hp)q%Ipl9r4eJ{?*4v}1JMM6NKOt8>$FTu&)o|AR(dT(&Cc*-1y}D zytK@8y@JXdKA>R{ll470H%oiJWP#WlAj`+)#(9n-iQ@*R58UF(|HE?`MJMM*q_c{Y zvH)$p7?}>TkyW^u1!&>L$hgTs3)zGk8CaT_!Q6F`(^-mGfHni=1kr8g2bvcNu{ipr zik>JRI|Khu{*U~}_~ZCJ_^tWH`C0h>@O|NX#rKHsFyC&zTD~m4C_Z~Wbv}7Mc3?aQ0vn6-1H1eE-@nJa|5(h($0rDsk`vt0Qt$QurAHKtpa77sBH*Ha zAb-+*CHap3!i+ZjK%pxBj_;;E{^{DBueH{k=4-yD^*U?n-EVn}yWhsP2OPMy>yA|N z+70=+_jf8Z>^-0VPX1cNY8`{twbz9v@9kSGn#RJ)$l2(_!ol$2v*hzHo(v2(&)82c z?bi)_vzB*5WcJ&&H>dsm|Gs?w?XPX5?0%q+^EKbd`kCKG=? VFyw6c+1Y^F8AU}mm(A}o0008c+kpT8 delta 542 zcmZozz}&Eac>{|Bvk3eD$?Oht+%BAFIK4Tpa^$lA-z+F_o}DR2WOAQ-E~_vLLu26N ziQ(ab@$s2?nI-Y@dIgmwLO{`6plHbC`Cgop4S@KZ2iIgD&!22X{6MKpxRkZ0AX5$> z(4+{E%FWW=FIgZ~2FUVop5?g8H3m<4DVNDycdD}OFaV=RcbSvvZqijD}M69fNG{*U~}_!IcO_-*+m`PumX z@qOca!}o;mDBoVb#e7|SReVW&QG8B7KMV2Ii;1u>a_Wf)FfbfQbTDA4tKQE51P2(| zgn{CG!i-`> z3o9dMqX!EI!-vn3&%bywFx)&de{ylZuK${?HP@o5v$v)G|Nr}L@$EHNvv?zzzujJI zmUCk*kbDys=I^b^474DGd5UCqy=eX4SIxhwzs`HpBqjZ0ZG!`c0MnJ1@fU;zc1caR h8qGBMW4|!72!GjR_6eFm@4N9&&Y#b^xq5!90RY}ey3YUr 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 8522142b..e4631776 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 @@ -23,8 +23,11 @@ from openai_api.lambda_openai_function.custom_config import ( AdditionalInformation, CustomConfig, + FunctionCalling, + Prompting, SearchTerms, SystemPrompt, + validate_required_keys, ) # our stuff @@ -42,6 +45,19 @@ def setUp(self): self.everlasting_gobbstopper = get_test_file_yaml("config/everlasting-gobbstopper.yaml") self.everlasting_gobbstopper_invalid = get_test_file_yaml("config/everlasting-gobbstopper-invalid.yaml") + def test_validate_required_keys(self): + """Test validate_required_keys.""" + required_keys = ["meta_data", "prompting", "function_calling"] + validate_required_keys( + class_name="CustomConfig", config_json=self.everlasting_gobbstopper, required_keys=required_keys + ) + + with self.assertRaises(ValueError): + required_keys = ["meta_data", "prompting", "some_other_key"] + validate_required_keys( + class_name="CustomConfig", config_json=self.everlasting_gobbstopper_invalid, required_keys=required_keys + ) + def test_system_prompt(self): """Test system_prompt.""" prompt = self.everlasting_gobbstopper["prompting"]["system_prompt"] @@ -53,6 +69,7 @@ def test_system_prompt(self): ) self.assertIsInstance(system_prompt, SystemPrompt) self.assertIsInstance(system_prompt.system_prompt, str) + self.assertTrue(isinstance(system_prompt.to_json(), dict)) def test_system_prompt_invalid(self): """Test system_prompt.""" @@ -132,3 +149,21 @@ def test_refers_to(self): self.assertListEqual( additional_information.keys, ["contact", "biographical", "sales_promotions", "coupon_codes"] ) + + def test_prompting(self): + """Test prompting.""" + custom_config = CustomConfig(config_json=self.everlasting_gobbstopper) + prompting_config_json = custom_config.prompting.to_json() + Prompting(config_json=prompting_config_json) + + with self.assertRaises(ValueError): + Prompting(config_json={}) + + def test_function_calling(self): + """Test function_calling.""" + custom_config = CustomConfig(config_json=self.everlasting_gobbstopper) + function_calling_config_json = custom_config.function_calling.to_json() + FunctionCalling(config_json=function_calling_config_json) + + with self.assertRaises(ValueError): + FunctionCalling(config_json={}) From 963273434207d89082a00a4e7435db4f697b566a Mon Sep 17 00:00:00 2001 From: lpm0073 Date: Sun, 28 Jan 2024 08:21:49 -0600 Subject: [PATCH 2/4] test: fix system_prompt type test --- .../lambda_openai_function/tests/test_custom_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 e4631776..9137bab5 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 @@ -69,7 +69,7 @@ def test_system_prompt(self): ) self.assertIsInstance(system_prompt, SystemPrompt) self.assertIsInstance(system_prompt.system_prompt, str) - self.assertTrue(isinstance(system_prompt.to_json(), dict)) + self.assertTrue(isinstance(system_prompt.to_json(), str)) def test_system_prompt_invalid(self): """Test system_prompt.""" From b93a39d5b4a180c413125ad657395d95f9827833 Mon Sep 17 00:00:00 2001 From: lpm0073 Date: Sun, 28 Jan 2024 09:02:51 -0600 Subject: [PATCH 3/4] docs: update main readme --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3ad857ff..64675a03 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,11 @@ A [React](https://react.dev/) + [AWS Serverless](https://aws.amazon.com/serverless/) full stack implementation of the [30 example applications](https://platform.openai.com/examples) found in the official OpenAI API documentation. This repository is used as an instructional tool for the YouTube channel "[Full Stack With Lawrence](https://youtube.com/@FullStackWithLawrence)" as well as for University of British Columbia course, "[Artificial Intelligence Cloud Technology Implementation](https://extendedlearning.ubc.ca/courses/artificial-intelligence-cloud-technology-implementation/mg202)" taught by Lawrence McDaniel. -_New in v0.10: A new chat app named "OpenAI Function Calling". See [lambda_openai_function](./api/terraform/python/openai_api/lambda_openai_function/) for examples including the fully implemented "[get_current_weather()](https://platform.openai.com/docs/guides/function-calling)" from The official OpenAI API documentation, and also check out these example [custom configurations](./api/terraform/python/openai_api/lambda_openai_function/config/) that demonstrate some of the amazing things that you can quickly implement with this new feature!_ +Features: + +- **Prompting**: Uses [Terraform templates](./api/terraform/apigateway_endpoints.tf) to create 30 different ChatBots, each with its own customized UX and api endpoint. + +- **Function Calling**: Uses [Yaml template](./api/terraform/python/openai_api/lambda_openai_function/config/) to easily configure highly customized ChatGPT prompting behavior that uses both dynamic prompting as well as [OpenAI Python Function Calling](https://platform.openai.com/docs/guides/function-calling) to integrate your own custom Python functions into chat response processing. Refer to the [Python source code](./api/terraform/python/openai_api/lambda_openai_function/) for examples including the fully implemented "[get_current_weather()](https://platform.openai.com/docs/guides/function-calling)" from The official OpenAI API documentation, and also [get_additional_info()](./api/terraform/python/openai_api/lambda_openai_function/function_refers_to.py) which implements your yaml templates. Additional documentation is available in this [README](./api/terraform/python/openai_api/lambda_openai_function/README.md) ![Marv](https://cdn.lawrencemcdaniel.com/marv.gif) From 0bc247d3bda3c2222c0bab8ce7fc9ec8fe62c1db Mon Sep 17 00:00:00 2001 From: lpm0073 Date: Sun, 28 Jan 2024 09:03:06 -0600 Subject: [PATCH 4/4] test: add tests for aws s3 bucket --- .../tests/test_custom_config.py | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) 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 9137bab5..8fe349be 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 @@ -10,6 +10,7 @@ from pathlib import Path import yaml +from botocore.exceptions import ClientError HERE = os.path.abspath(os.path.dirname(__file__)) @@ -19,6 +20,8 @@ sys.path.append(PYTHON_ROOT) # noqa: E402 +from openai_api.common.conf import settings + # pylint: disable=no-name-in-module from openai_api.lambda_openai_function.custom_config import ( AdditionalInformation, @@ -29,8 +32,6 @@ SystemPrompt, validate_required_keys, ) - -# our stuff from openai_api.lambda_openai_function.tests.test_setup import ( # noqa: E402 get_test_file_path, get_test_file_yaml, @@ -167,3 +168,26 @@ def test_function_calling(self): with self.assertRaises(ValueError): FunctionCalling(config_json={}) + + def test_aws_s3_bucket(self): + """Test aws_s3_bucket.""" + aws_s3_bucket_name = settings.aws_s3_bucket_name + s3 = settings.aws_s3_client + + folder_name = "test_folder/" + file_name = folder_name + "test_file" + + # Connect to the aws_s3_bucket_name + try: + s3.head_bucket(Bucket=aws_s3_bucket_name) + except ClientError: + self.fail("Couldn't connect to the aws_s3_bucket_name.") + + # Create a folder + s3.put_object(Bucket=aws_s3_bucket_name, Key=folder_name) + + # Write a file to the folder + s3.put_object(Bucket=aws_s3_bucket_name, Key=file_name, Body=b"Test data") + + # Delete the file and the folder + s3.delete_objects(Bucket=aws_s3_bucket_name, Delete={"Objects": [{"Key": file_name}, {"Key": folder_name}]})