diff --git a/README.md b/README.md index a003170..e78af4c 100644 --- a/README.md +++ b/README.md @@ -333,7 +333,7 @@ To learn how to use this in your workflows, see [Examples](/examples/). - [SummarizeLargeDocumentsUsingChatGPTandMATLAB.mlx](/examples/SummarizeLargeDocumentsUsingChatGPTandMATLAB.mlx): Learn to create concise summaries of long texts with ChatGPT. (Requires Text Analytics Toolbox™) - [CreateSimpleChatBot.mlx](/examples/CreateSimpleChatBot.mlx): Build a conversational chatbot capable of handling various dialogue scenarios using ChatGPT. (Requires Text Analytics Toolbox) - [AnalyzeScientificPapersUsingFunctionCalls.mlx](/examples/AnalyzeScientificPapersUsingFunctionCalls.mlx): Learn how to create agents capable of executing MATLAB functions. -- [ExampleParallelFunctionCalls.mlx](/examples/ExampleParallelFunctionCalls.mlx): Learn how to take advantage of parallel function calling. +- [AnalyzeTextDataUsingParallelFunctionCallwithChatGPT.mlx](/examples/AnalyzeTextDataUsingParallelFunctionCallwithChatGPT.mlx): Learn how to take advantage of parallel function calling. - [RetrievalAugmentedGenerationUsingChatGPTandMATLAB.mlx](/examples/RetrievalAugmentedGenerationUsingChatGPTandMATLAB.mlx): Learn about retrieval augmented generation with a simple use case. (Requires Text Analytics Toolbox™) - [DescribeImagesUsingChatGPT.mlx](/examples/DescribeImagesUsingChatGPT.mlx): Learn how to use GPT-4 Turbo with Vision to understand the content of an image. - [AnalyzeSentimentinTextUsingChatGPTinJSONMode.mlx](/examples/AnalyzeSentimentinTextUsingChatGPTinJSONMode.mlx): Learn how to use JSON mode in chat completions diff --git a/examples/AnalyzeTextDataUsingParallelFunctionCallwithChatGPT.mlx b/examples/AnalyzeTextDataUsingParallelFunctionCallwithChatGPT.mlx new file mode 100644 index 0000000..63d6d76 Binary files /dev/null and b/examples/AnalyzeTextDataUsingParallelFunctionCallwithChatGPT.mlx differ diff --git a/examples/ExampleParallelFunctionCalls.mlx b/examples/ExampleParallelFunctionCalls.mlx deleted file mode 100644 index 94f45ba..0000000 Binary files a/examples/ExampleParallelFunctionCalls.mlx and /dev/null differ diff --git a/openAIImages.m b/openAIImages.m index e60aa16..818d17b 100644 --- a/openAIImages.m +++ b/openAIImages.m @@ -86,7 +86,7 @@ arguments this (1,1) openAIImages - prompt {mustBeTextScalar} + prompt {mustBeNonzeroLengthTextScalar} nvp.NumImages (1,1) {mustBePositive, mustBeInteger,... mustBeLessThanOrEqual(nvp.NumImages,10)} = 1 nvp.Size (1,1) string {mustBeMember(nvp.Size, ["256x256", "512x512", ... @@ -176,7 +176,7 @@ arguments this (1,1) openAIImages imagePath {mustBeValidFileType(imagePath)} - prompt {mustBeTextScalar} + prompt {mustBeNonzeroLengthTextScalar} nvp.MaskImagePath {mustBeValidFileType(nvp.MaskImagePath)} nvp.NumImages (1,1) {mustBePositive, mustBeInteger,... mustBeLessThanOrEqual(nvp.NumImages,10)} = 1 @@ -345,7 +345,9 @@ function validatePromptSize(model, prompt) function mustBeValidFileType(filePath) mustBeFile(filePath); s = dir(filePath); - if ~endsWith(s.name, ".png") + imgDetails = imfinfo(filePath); + imgFormat = imgDetails.Format; + if ~(imgFormat=="png") error("llms:pngExpected", ... llms.utils.errorMessageCatalog.getMessage("llms:pngExpected")); end diff --git a/tests/test_files/solar.png b/tests/test_files/solar.png new file mode 100644 index 0000000..fc37277 Binary files /dev/null and b/tests/test_files/solar.png differ diff --git a/tests/topenAIImages.m b/tests/topenAIImages.m index 4e70f9a..2b625e1 100644 --- a/tests/topenAIImages.m +++ b/tests/topenAIImages.m @@ -105,6 +105,12 @@ function constructModelWithAllNVP(testCase) testCase.verifyEqual(mdl.ModelName, modelName); end + function fakePNGImage(testCase) + mdl = openAIImages(ApiKey="this-is-not-a-real-key"); + fakePng = fullfile("test_files", "solar.png"); + testCase.verifyError(@()edit(mdl,fakePng, "bla"), "llms:pngExpected"); + end + function invalidInputsConstructor(testCase, InvalidConstructorInput) testCase.verifyError(@()openAIImages(InvalidConstructorInput.Input{:}), InvalidConstructorInput.Error); end @@ -157,11 +163,15 @@ function invalidInputsVariation(testCase, InvalidVariationInput) invalidGenerateInput = struct( ... "EmptyInput",struct( ... "Input",{{ [] }},... - "Error","MATLAB:validators:mustBeTextScalar"),... + "Error","MATLAB:validators:mustBeNonzeroLengthText"),... ... "InvalidInputType",struct( ... "Input",{{ 123 }},... - "Error","MATLAB:validators:mustBeTextScalar"),... + "Error","MATLAB:validators:mustBeNonzeroLengthText"),... + ... + "InvalidPromptLen",struct( ... + "Input",{{ "" }},... + "Error","MATLAB:validators:mustBeNonzeroLengthText"),... ... "InvalidNumImagesType",struct( ... "Input",{{ "prompt" "NumImages" "2" }},... @@ -233,17 +243,21 @@ function invalidInputsVariation(testCase, InvalidVariationInput) "Input",{{ 123, "prompt" }},... "Error","MATLAB:validators:mustBeNonzeroLengthText"),... ... + "InvalidPromptLen",struct( ... + "Input",{{ validImage, "" }},... + "Error","MATLAB:validators:mustBeNonzeroLengthText"),... + ... "InvalidImageExtension",struct( ... "Input",{{ nonPNGImage, "prompt" }},... "Error","llms:pngExpected"),... ... "EmptyPrompt",struct( ... "Input",{{ validImage, [] }},... - "Error","MATLAB:validators:mustBeTextScalar"),... + "Error","MATLAB:validators:mustBeNonzeroLengthText"),... ... "InvalidPromptType",struct( ... "Input",{{ validImage, 123 }},... - "Error","MATLAB:validators:mustBeTextScalar"),... + "Error","MATLAB:validators:mustBeNonzeroLengthText"),... ... "InvalidMaskImage",struct( ... "Input",{{ validImage, "foo", "MaskImagePath", 123 }},...