1+ function [text , message , response ] = callAzureChatAPI(endpoint , deploymentID , messages , functions , nvp )
2+ % This function is undocumented and will change in a future release
3+
4+ % callAzureChatAPI Calls the openAI chat completions API on Azure.
5+ %
6+ % MESSAGES and FUNCTIONS should be structs matching the json format
7+ % required by the OpenAI Chat Completions API.
8+ % Ref: https://platform.openai.com/docs/guides/gpt/chat-completions-api
9+ %
10+ % More details on the parameters: https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/chatgpt
11+ %
12+ % Example
13+ %
14+ % % Create messages struct
15+ % messages = {struct("role", "system",...
16+ % "content", "You are a helpful assistant");
17+ % struct("role", "user", ...
18+ % "content", "What is the edit distance between hi and hello?")};
19+ %
20+ % % Create functions struct
21+ % functions = {struct("name", "editDistance", ...
22+ % "description", "Find edit distance between two strings or documents.", ...
23+ % "parameters", struct( ...
24+ % "type", "object", ...
25+ % "properties", struct(...
26+ % "str1", struct(...
27+ % "description", "Source string.", ...
28+ % "type", "string"),...
29+ % "str2", struct(...
30+ % "description", "Target string.", ...
31+ % "type", "string")),...
32+ % "required", ["str1", "str2"]))};
33+ %
34+ % % Define your API key
35+ % apiKey = "your-api-key-here"
36+ %
37+ % % Send a request
38+ % [text, message] = llms.internal.callAzureChatAPI(messages, functions, APIKey=apiKey)
39+
40+ % Copyright 2023-2024 The MathWorks, Inc.
41+
42+ arguments
43+ endpoint
44+ deploymentID
45+ messages
46+ functions
47+ nvp.ToolChoice
48+ nvp.APIVersion
49+ nvp.Temperature
50+ nvp.TopP
51+ nvp.NumCompletions
52+ nvp.StopSequences
53+ nvp.MaxNumTokens
54+ nvp.PresencePenalty
55+ nvp.FrequencyPenalty
56+ nvp.ResponseFormat
57+ nvp.Seed
58+ nvp.APIKey
59+ nvp.TimeOut
60+ nvp.StreamFun
61+ end
62+
63+ URL = endpoint + " openai/deployments/" + deploymentID + " /chat/completions?api-version=" + nvp .APIVersion ;
64+
65+ parameters = buildParametersCall(messages , functions , nvp );
66+
67+ [response , streamedText ] = llms .internal .sendRequest(parameters ,nvp .APIKey , URL , nvp .TimeOut , nvp .StreamFun );
68+
69+ % If call errors, "choices" will not be part of response.Body.Data, instead
70+ % we get response.Body.Data.error
71+ if response .StatusCode ==" OK"
72+ % Outputs the first generation
73+ if isempty(nvp .StreamFun )
74+ message = response .Body .Data .choices(1 ).message;
75+ else
76+ message = struct(" role" , " assistant" , ...
77+ " content" , streamedText );
78+ end
79+ if isfield(message , " tool_choice" )
80+ text = " " ;
81+ else
82+ text = string(message .content );
83+ end
84+ else
85+ text = " " ;
86+ message = struct();
87+ end
88+ end
89+
90+ function parameters = buildParametersCall(messages , functions , nvp )
91+ % Builds a struct in the format that is expected by the API, combining
92+ % MESSAGES, FUNCTIONS and parameters in NVP.
93+
94+ parameters = struct();
95+ parameters.messages = messages ;
96+
97+ parameters.stream = ~isempty(nvp .StreamFun );
98+
99+ if ~isempty(functions )
100+ parameters.tools = functions ;
101+ end
102+
103+ if ~isempty(nvp .ToolChoice )
104+ parameters.tool_choice = nvp .ToolChoice ;
105+ end
106+
107+ if ~isempty(nvp .Seed )
108+ parameters.seed = nvp .Seed ;
109+ end
110+
111+ dict = mapNVPToParameters ;
112+
113+ nvpOptions = keys(dict );
114+ for opt = nvpOptions .'
115+ if isfield(nvp , opt )
116+ parameters.(dict(opt )) = nvp.(opt );
117+ end
118+ end
119+ end
120+
121+ function dict = mapNVPToParameters()
122+ dict = dictionary();
123+ dict(" Temperature" ) = " temperature" ;
124+ dict(" TopP" ) = " top_p" ;
125+ dict(" NumCompletions" ) = " n" ;
126+ dict(" StopSequences" ) = " stop" ;
127+ dict(" MaxNumTokens" ) = " max_tokens" ;
128+ dict(" PresencePenalty" ) = " presence_penalty" ;
129+ dict(" FrequencyPenalty" ) = " frequency_penalty" ;
130+ end
0 commit comments