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