Skip to content

Commit fbe752d

Browse files
committed
adding first version.
1 parent 362628b commit fbe752d

20 files changed

+1752
-0
lines changed

+llms/+internal/callOpenAIChatAPI.m

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
function [text, message, response] = callOpenAIChatAPI(messages, functions, nvp)
2+
arguments
3+
messages
4+
functions
5+
nvp.FunctionCall
6+
nvp.ModelName
7+
nvp.Temperature
8+
nvp.TopProbabilityMass
9+
nvp.NumCompletions
10+
nvp.StopSequences
11+
nvp.MaxNumTokens
12+
nvp.PresencePenalty
13+
nvp.FrequencyPenalty
14+
nvp.ApiKey
15+
end
16+
17+
END_POINT = "https://api.openai.com/v1/chat/completions";
18+
19+
parameters = buildParametersCall(messages, functions, nvp);
20+
21+
response = llms.internal.sendRequest(parameters,nvp.ApiKey, END_POINT);
22+
23+
if response.StatusCode=="OK"
24+
message = response.Body.Data.choices(1).message;
25+
if isfield(message, "function_call")
26+
text = "";
27+
message.function_call.arguments = message.function_call.arguments;
28+
else
29+
text = string(message.content);
30+
end
31+
else
32+
text = "";
33+
message = struct();
34+
end
35+
end
36+
37+
function parameters = buildParametersCall(messages, functions, nvp)
38+
parameters = struct();
39+
parameters.messages = messages;
40+
if ~isempty(functions)
41+
parameters.functions = functions;
42+
end
43+
44+
if ~isempty(nvp.FunctionCall)
45+
parameters.function_call = nvp.FunctionCall;
46+
end
47+
48+
parameters.model = nvp.ModelName;
49+
50+
dict = mapNVPToParameters;
51+
52+
nvpOptions = keys(dict);
53+
for i=1:length(nvpOptions)
54+
if isfield(nvp, nvpOptions(i))
55+
parameters.(dict(nvpOptions(i))) = nvp.(nvpOptions(i));
56+
end
57+
end
58+
end
59+
60+
function dict = mapNVPToParameters()
61+
dict = dictionary();
62+
dict("Temperature") = "temperature";
63+
dict("TopProbabilityMass") = "top_p";
64+
dict("NumCompletions") = "n";
65+
dict("StopSequences") = "stop";
66+
dict("MaxNumTokens") = "max_tokens";
67+
dict("PresencePenalty") = "presence_penalty";
68+
dict("FrequencyPenalty ") = "frequency_penalty";
69+
end

+llms/+internal/checkEnvOrNVP.m

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
function key = checkEnvOrNVP(nvp)
2+
if isfield(nvp, "ApiKey")
3+
key = nvp.ApiKey;
4+
else
5+
if isenv("OPENAI_API_KEY")
6+
key = getenv("OPENAI_API_KEY");
7+
else
8+
error("llms:keyMustBeSpecified", llms.utils.errorMessageCatalog.getMessage("llms:keyMustBeSpecified"));
9+
end
10+
end
11+
end

+llms/+internal/sendRequest.m

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
function response = sendRequest(parameters, token, endpoint, consumer)
2+
% Define the headers for the API request
3+
4+
headers = matlab.net.http.HeaderField('Content-Type', 'application/json');
5+
headers(2) = matlab.net.http.HeaderField('Authorization', 'Bearer ' + string(token));
6+
% Define the request message
7+
request = matlab.net.http.RequestMessage('post',headers,parameters);
8+
% Send the request and store the response
9+
if nargin==3
10+
response = send(request, matlab.net.URI(endpoint));
11+
else
12+
response = send(request, matlab.net.URI(endpoint),[],consumer);
13+
end
14+
end
15+

+llms/+utils/errorMessageCatalog.m

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
classdef errorMessageCatalog
2+
properties(Constant)
3+
Catalog = buildErrorMessageCatalog;
4+
end
5+
6+
methods(Static)
7+
function msg = getMessage(messageId, slot)
8+
arguments
9+
messageId {mustBeNonzeroLengthText}
10+
end
11+
arguments(Repeating)
12+
slot {mustBeNonzeroLengthText}
13+
end
14+
msg = llms.utils.errorMessageCatalog.Catalog(messageId);
15+
if ~isempty(slot)
16+
for i=1:numel(slot)
17+
msg = replace(msg,"{"+i+"}", slot{i});
18+
end
19+
end
20+
end
21+
end
22+
end
23+
24+
function catalog = buildErrorMessageCatalog
25+
catalog = dictionary("string", "string");
26+
catalog("llms:mustBeUnique") = "Values must be unique.";
27+
catalog("llms:mustBeVarName") = "Parameter name must begin with a letter and contain not more than namelengthmax characters.";
28+
catalog("llms:parameterMustBeUnique") = "A parameter name equivalent to '{1}' already exists in Parameters. Redefining a parameter is not allowed.";
29+
catalog("llms:mustBeAssistantCall") = "Input struct must contain field 'role' with value 'assistant' and field 'content'.";
30+
catalog("llms:mustBeAssistantWithContent") = "Input struct must contain field 'content' containing text with one or more characters";
31+
catalog("llms:mustBeAssistantWithNameAndArguments") = "Field 'function_call' must be a struct with fields 'name' and 'arguments'";
32+
catalog("llms:assistantMustHaveTextNameAndArguments") = "Fields 'name' and 'arguments' must be text with one or more characters";
33+
catalog("llms:mustBeValidIndex") = "Value is larger than the number of elements in Messages ({0})";
34+
catalog("llms:stopSequencesMustHaveMax4Elements") = "Number of elements must not be larger than 4.";
35+
catalog("llms:keyMustBeSpecified") = "API key not found as enviroment variable OPEN_API_KEY and not specified via ApiKey parameter.";
36+
catalog("llms:mustHaveMessages") = "Value must contain at least one message in Messages";
37+
catalog("llms:mustSetFunctionsForCall") = "When no functions are defined, FunctionCall must not be specified.";
38+
catalog("llms:mustBeMessagesOrTxt") = "Messages must be text with one or more characters or an openAIMessages objects";
39+
end
40+

+llms/+utils/isUnique.m

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
function tf = isUnique(values)
2+
tf = numel(values)==numel(unique(values));
3+
end
4+

+llms/+utils/mustBeTextOrEmpty.m

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
function mustBeTextOrEmpty(value)
2+
if ~isempty(value)
3+
mustBeTextScalar(value)
4+
end
5+
end

SECURITY.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Reporting Security Vulnerabilities
2+
3+
If you believe you have discovered a security vulnerability, please report it to
4+
[security@mathworks.com](mailto:security@mathworks.com). Please see
5+
[MathWorks Vulnerability Disclosure Policy for Security Researchers](https://www.mathworks.com/company/aboutus/policies_statements/vulnerability-disclosure-policy.html)
6+
for additional information.

examples/ExampleAgentCreation.mlx

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
%% Example Title
2+
% Summary of example objective
3+
4+
%% Section 1 Title
5+
% Description of first code block
6+
a = 1;
7+
8+
%% Section 2 Title
9+
% Description of second code block
10+
b = 2;

examples/ExampleBasicUsage.mlx

2.75 KB
Binary file not shown.

examples/ExampleChatBot.mlx

2.75 KB
Binary file not shown.
2.75 KB
Binary file not shown.

examples/ExampleRobotControl.mlx

2.75 KB
Binary file not shown.

examples/ExampleSummarization.mlx

2.76 KB
Binary file not shown.

license.txt

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Copyright (c) 2023, The MathWorks, Inc.
2+
All rights reserved.
3+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
5+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
6+
3. In all cases, the software is, and all modifications and derivatives of the software shall be, licensed to you solely for use in conjunction with MathWorks products and service offerings.
7+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8+
9+
10+
11+

0 commit comments

Comments
 (0)