Following on from the article: Zoho Cliq: Integrate OpenAI and ChatGPT 3.5 Turbo. This is the next step as we get it to look at data within ZohoCRM.
Why?
Because it is a serious improvement upon ZohoZIA and we get a lot of requests around customizing ZohoZIA...
How?
So taking ideas from my previous article for ZohoCliq; let's use what we know to develop a ZohoZIA for a demo system.
There are several steps, so first we will set up the ZIA action "Ask ChatGPT" using the GUI, then we will capture the question using Deluge code and query the OpenAI ChatGPT API to return a response.
Getting to the development-side
- Login to ZohoCRM as a super-admin
- Go to Setup (cog icon in the top right)
- Under Zia, select "Conversational AI"
- Click on the link "Zia Developer Console" (yours will have the specific OrgID in the URL).
- Click on "Add Action"
- Give it the Action Name "Ask ChatGPT"
- This action should "Answer a Question"
- It should be answered by "Construct Answer by Fetching Data"
- The question can be asked by clicking the button "Ask ChatGPT"
- Add the parameter:
- I'm calling it "banter"
- of type "String"
- with a prompt message of "What is your question?"
- click on "Save"
- click on "Done"
- Now click on "Edit Function" under "Context Handler Function"
-
We're going to use the following deluge code for our first pass at this awesome functionality:
copyraw
// // initialize v_Response = previousParam; m_Response = Map(); m_Response.put("todo","prompt"); l_Messages = List(); // // capture latest message from user v_Message = ifnull(userInput,""); m_Thread = Map(); m_Thread.put("role","user"); m_Thread.put("content",v_Message); l_Messages.add(m_Thread); // // if the message is not blank nor the trigger, send to OpenAI ChatGPT API if(!isBlank(v_Message) && v_Message!="Ask ChatGPT") { // // Need to add your own OpenAI token here v_Token = "sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; // // build header of request m_Header = Map(); m_Header.put("Authorization","Bearer " + v_Token); m_Header.put("Content-Type","application/json"); // // build params of request m_Params = Map(); m_Params.put("model","gpt-3.5-turbo"); m_Params.put("messages",l_Messages); // // https://platform.openai.com/docs/api-reference/chat/create m_Params.put("temperature",0.8); m_Params.put("n",1); m_Params.put("max_tokens",256); m_Params.put("presence_penalty",0); m_Params.put("frequency_penalty",0); // // send request to chatgpt openai r_ChatGPTResponse = invokeurl [ url :"https://api.openai.com/v1/chat/completions" type :POST parameters:m_Params.toString() headers:m_Header detailed:true ]; if(r_ChatGPTResponse.get("responseCode") == 200) { // // retrieve the answer in text l_Choices = r_ChatGPTResponse.get("responseText").get("choices"); for each m_Choice in l_Choices { if(!isnull(m_Choice.get("message"))) { if(m_Choice.get("message").get("role") == "assistant") { // // add the answer text to the response map v_Response = m_Choice.get("message").get("content"); } } } } else { // store in response text v_Response = "I don't know. Would you like me to Google: [" + v_Message + "](https://www.google.com/search?q=" + zoho.encryption.urlEncode(v_Message) + ")?"; } } // // build up response to user m_Prompt = Map(); m_Prompt.put("param_name","banter"); m_Prompt.put("prompt_msg",v_Response); m_Response.put("prompt",m_Prompt); // // output return m_Response;
- //
- // initialize
- v_Response = previousParam;
- m_Response = Map();
- m_Response.put("todo","prompt");
- l_Messages = List();
- //
- // capture latest message from user
- v_Message = ifnull(userInput,"");
- m_Thread = Map();
- m_Thread.put("role","user");
- m_Thread.put("content",v_Message);
- l_Messages.add(m_Thread);
- //
- // if the message is not blank nor the trigger, send to OpenAI ChatGPT API
- if(!isBlank(v_Message) && v_Message!="Ask ChatGPT")
- {
- //
- // Need to add your own OpenAI token here
- v_Token = "sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
- //
- // build header of request
- m_Header = Map();
- m_Header.put("Authorization","Bearer " + v_Token);
- m_Header.put("Content-Type","application/json");
- //
- // build params of request
- m_Params = Map();
- m_Params.put("model","gpt-3.5-turbo");
- m_Params.put("messages",l_Messages);
- //
- // https://platform.openai.com/docs/api-reference/chat/create
- m_Params.put("temperature",0.8);
- m_Params.put("n",1);
- m_Params.put("max_tokens",256);
- m_Params.put("presence_penalty",0);
- m_Params.put("frequency_penalty",0);
- //
- // send request to chatgpt openai
- r_ChatGPTResponse = invokeUrl
- [
- url :"https://api.openai.com/v1/chat/completions"
- type :POST
- parameters:m_Params.toString()
- headers:m_Header
- detailed:true
- ];
- if(r_ChatGPTResponse.get("responseCode") == 200)
- {
- //
- // retrieve the answer in text
- l_Choices = r_ChatGPTResponse.get("responseText").get("choices");
- for each m_Choice in l_Choices
- {
- if(!isnull(m_Choice.get("message")))
- {
- if(m_Choice.get("message").get("role") == "assistant")
- {
- //
- // add the answer text to the response map
- v_Response = m_Choice.get("message").get("content");
- }
- }
- }
- }
- else
- {
- // store in response text
- v_Response = "I don't know. Would you like me to Google: [" + v_Message + "](https://www.google.com/search?q=" + zoho.encryption.urlEncode(v_Message) + ")?";
- }
- }
- //
- // build up response to user
- m_Prompt = Map();
- m_Prompt.put("param_name","banter");
- m_Prompt.put("prompt_msg",v_Response);
- m_Response.put("prompt",m_Prompt);
- //
- // output
- return m_Response;
- click on "Save Script"
- Test using the sidebar on the right
- Click on "Done" when satisfied.
- Click on the left arrow/caret to return to the ZohoCRM ZIA main page
- Click on "Deploy to Production"
- Select what actions to deploy (the "Ask ChatGPT") and then click on "Deploy"
All done? Now Test!
- Login/Reload ZohoCRM
- Click on "Ask Zia"
- Type the "Ask ChatGPT" and it should popup with ...things you can ask me... with one being "Ask ChatGPT"
- Click on it and then ask away:...
Keeping a Conversation
So annoyingly, the variable broadcast was unreliable in storing message conversations despite it's purpose being ideal. Instead, let's use a CRM function to store the conversation between ChatGPT and the CRM User. This way, we can also ensure that the data shared can be controlled/monitored.
- Create a CRM Module called "GPT Chats" (singular: GPT Chat)
- Modify the name field to be an Auto-Number (I'm prefixing mine with CHAT-
- Add a pick list called "Role" with the options: "user", "assistant", "system".
- Add a file upload field called "Big Data"
- Add a single line field called "Title" (used as a multi-line cannot be used in the listview).
- Add a multi-line field called "Content" and change the properties on creation to allow 32000 characters.
- Keep the email field called "Email"
- Click on "Manage Connections"
- Click on Create Connection
- Select Service "Zoho OAuth"
- Give it a name, I'm calling mine "ChatGPT CRM"
- Untick "Use Credentials of Login User"
- Under Scopes, click on the Search icon and type "CRM": I selected "ZohoCRM.coql.READ, ZohoCRM.modules.ALL, ZohoCRM.org.READ, ZohoCRM.settings.READ, and ZohoCRM.users.READ"
- Click on "Create and Connect" > Connect
- Choose the environment (eg. Production, Sandbox, or Developer) > Submit
- Click on "Accept" to authorize the connection
- Give it the following code:copyraw
/* ******************************************************************************* Function: Ask ChatGPT - Context Handler Function Trigger: Function executed in ZIA chat when "Ask ChatGPT" button is clicked Purpose: This will query the OpenAI ChatGPT API but at the same time retain the context of ZohoCRM Inputs: string userInput Outputs: map m_Response Date Created: 2023-02-08 (Joel Lipman) - Initial release - Queries OpenAI ChatGPT Date Modified: 2023-03-11 (Joel Lipman) - Stores conversation messages / thread in CRM records - Retrieves and builds up conversation trail to send to OpenAI ChatGPT API ******************************************************************************* */ // // initialize m_Blank = Map(); v_Response = previousParam; m_Response = Map(); m_Response.put("todo","prompt"); // // determine name of logged in user (and make owner?) v_LoggedInUserID = 0; l_Users= List(); m_UserType = Map(); m_UserType.put("email",zoho.loginuserid); r_Response = zoho.crm.invokeConnector("crm.getusers",m_UserType); if(!isnull(r_Response.get("status_code"))) { if(r_Response.get("status_code")==200) { l_Users = r_Response.get("response").get("users"); for each v_User in l_Users { v_LoggedInUserID = v_User.get("id"); } } } // // start building conversation trail l_ConversationMessages = List(); // // build up COQL query v_CoqlQuery = "select Content, Role from GPT_Chats where Owner='" + v_LoggedInUserID + "' order by Created_Time asc"; // // build up parameters m_Params = Map(); m_Params.put("select_query",v_CoqlQuery); // // invokeurl (note the Zoho endpoint here will depend on your datacenter; .com / .eu) r_Coql = invokeurl [ url :"https://www.zohoapis.eu/crm/v2/coql" type :POST parameters:m_Params.toString() connection:"chatgptcrm" ]; if(!isnull(r_Coql.get("data"))) { for each m_Message in r_Coql.get("data") { m_Chat = Map(); m_Chat.put("role", m_Message.get("Role")); m_Chat.put("content", m_Message.get("Content")); l_ConversationMessages.add(m_Chat); } } // // storing latest user input v_UserMessage = ifnull(userInput,""); if(!isBlank(v_UserMessage) && !v_UserMessage.equalsIgnoreCase("Ask ChatGPT")) { // // store user input to a CRM record m_Create = Map(); v_Title = if(v_UserMessage.length()>40, v_UserMessage.subString(0,40) + "...", v_UserMessage); m_Create.put("Title", v_Title); m_Create.put("Content", v_UserMessage.trim()); m_Create.put("Role", "user"); m_Create.put("Email", zoho.loginuserid); m_Create.put("Owner", v_LoggedInUserID); r_Create = zoho.crm.createRecord("GPT_Chats", m_Create); // // add the last question to the messages m_Chat = Map(); m_Chat.put("role", "user"); m_Chat.put("content", v_UserMessage); l_ConversationMessages.add(m_Chat); // // ******************************************************************** // ok let's query OpenAI ChatGPT // // Need to add your own OpenAI token here v_Token = "sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; // // build header of request m_Header = Map(); m_Header.put("Authorization","Bearer " + v_Token); m_Header.put("Content-Type","application/json"); // // build params of request m_Params = Map(); m_Params.put("model","gpt-3.5-turbo"); m_Params.put("messages",l_ConversationMessages); // // https://platform.openai.com/docs/api-reference/chat/create m_Params.put("temperature",0.8); m_Params.put("n",1); m_Params.put("max_tokens",256); m_Params.put("presence_penalty",0); m_Params.put("frequency_penalty",0); // // send request to chatgpt openai r_ChatGPTResponse = invokeurl [ url :"https://api.openai.com/v1/chat/completions" type :POST parameters:m_Params.toString() headers:m_Header detailed:true ]; v_Response = l_ConversationMessages; if(r_ChatGPTResponse.get("responseCode") == 200) { // // retrieve the answer in text l_Choices = r_ChatGPTResponse.get("responseText").get("choices"); for each m_Choice in l_Choices { if(!isnull(m_Choice.get("message"))) { if(m_Choice.get("message").get("role") == "assistant") { // // add the answer text to the response map v_Response = m_Choice.get("message").get("content"); } } } } else { // store in response text v_Response = "I don't know. Would you like me to Google: [" + v_UserMessage + "](https://www.google.com/search?q=" + zoho.encryption.urlEncode(v_UserMessage) + ")?"; } } // // capture answer from bot if(!isNull(v_Response) && !v_Response.equalsIgnoreCase("What is your question?")) { m_Create = Map(); v_Title = if(v_Response.length()>40, v_Response.subString(0,40) + "...", v_Response); m_Create.put("Title", v_Title); m_Create.put("Content", v_Response); m_Create.put("Role", "assistant"); m_Create.put("Email", zoho.loginuserid); m_Create.put("Owner", v_LoggedInUserID); r_Create = zoho.crm.createRecord("GPT_Chats", m_Create); } // // build up output to ZIA chat interface m_Prompt = Map(); m_Prompt.put("param_name","banter"); m_Prompt.put("prompt_msg",v_Response); m_Response.put("prompt",m_Prompt); // // output return m_Response;
- /* *******************************************************************************
- Function: Ask ChatGPT - Context Handler Function
- Trigger: Function executed in ZIA chat when "Ask ChatGPT" button is clicked
- Purpose: This will query the OpenAI ChatGPT API but at the same time retain the context of ZohoCRM
- Inputs: string userInput
- Outputs: map m_Response
- Date Created: 2023-02-08 (Joel Lipman)
- - Initial release
- - Queries OpenAI ChatGPT
- Date Modified: 2023-03-11 (Joel Lipman)
- - Stores conversation messages / thread in CRM records
- - Retrieves and builds up conversation trail to send to OpenAI ChatGPT API
- ******************************************************************************* */
- //
- // initialize
- m_Blank = Map();
- v_Response = previousParam;
- m_Response = Map();
- m_Response.put("todo","prompt");
- //
- // determine name of logged in user (and make owner?)
- v_LoggedInUserID = 0;
- l_Users= List();
- m_UserType = Map();
- m_UserType.put("email",zoho.loginuserid);
- r_Response = zoho.crm.invokeConnector("crm.getusers",m_UserType);
- if(!isnull(r_Response.get("status_code")))
- {
- if(r_Response.get("status_code")==200)
- {
- l_Users = r_Response.get("response").get("users");
- for each v_User in l_Users
- {
- v_LoggedInUserID = v_User.get("id");
- }
- }
- }
- //
- // start building conversation trail
- l_ConversationMessages = List();
- //
- // build up COQL query
- v_CoqlQuery = "select Content, Role from GPT_Chats where Owner='" + v_LoggedInUserID + "' order by Created_Time asc";
- //
- // build up parameters
- m_Params = Map();
- m_Params.put("select_query",v_CoqlQuery);
- //
- // invokeUrl (note the Zoho endpoint here will depend on your datacenter; .com / .eu)
- r_Coql = invokeUrl
- [
- url :"https://www.zohoapis.eu/crm/v2/coql"
- type :POST
- parameters:m_Params.toString()
- connection:"chatgptcrm"
- ];
- if(!isnull(r_Coql.get("data")))
- {
- for each m_Message in r_Coql.get("data")
- {
- m_Chat = Map();
- m_Chat.put("role", m_Message.get("Role"));
- m_Chat.put("content", m_Message.get("Content"));
- l_ConversationMessages.add(m_Chat);
- }
- }
- //
- // storing latest user input
- v_UserMessage = ifnull(userInput,"");
- if(!isBlank(v_UserMessage) && !v_UserMessage.equalsIgnoreCase("Ask ChatGPT"))
- {
- //
- // store user input to a CRM record
- m_Create = Map();
- v_Title = if(v_UserMessage.length()>40, v_UserMessage.subString(0,40) + "...", v_UserMessage);
- m_Create.put("Title", v_Title);
- m_Create.put("Content", v_UserMessage.trim());
- m_Create.put("Role", "user");
- m_Create.put("Email", zoho.loginuserid);
- m_Create.put("Owner", v_LoggedInUserID);
- r_Create = zoho.crm.createRecord("GPT_Chats", m_Create);
- //
- // add the last question to the messages
- m_Chat = Map();
- m_Chat.put("role", "user");
- m_Chat.put("content", v_UserMessage);
- l_ConversationMessages.add(m_Chat);
- //
- // ********************************************************************
- // ok let's query OpenAI ChatGPT
- //
- // Need to add your own OpenAI token here
- v_Token = "sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
- //
- // build header of request
- m_Header = Map();
- m_Header.put("Authorization","Bearer " + v_Token);
- m_Header.put("Content-Type","application/json");
- //
- // build params of request
- m_Params = Map();
- m_Params.put("model","gpt-3.5-turbo");
- m_Params.put("messages",l_ConversationMessages);
- //
- // https://platform.openai.com/docs/api-reference/chat/create
- m_Params.put("temperature",0.8);
- m_Params.put("n",1);
- m_Params.put("max_tokens",256);
- m_Params.put("presence_penalty",0);
- m_Params.put("frequency_penalty",0);
- //
- // send request to chatgpt openai
- r_ChatGPTResponse = invokeUrl
- [
- url :"https://api.openai.com/v1/chat/completions"
- type :POST
- parameters:m_Params.toString()
- headers:m_Header
- detailed:true
- ];
- v_Response = l_ConversationMessages;
- if(r_ChatGPTResponse.get("responseCode") == 200)
- {
- //
- // retrieve the answer in text
- l_Choices = r_ChatGPTResponse.get("responseText").get("choices");
- for each m_Choice in l_Choices
- {
- if(!isnull(m_Choice.get("message")))
- {
- if(m_Choice.get("message").get("role") == "assistant")
- {
- //
- // add the answer text to the response map
- v_Response = m_Choice.get("message").get("content");
- }
- }
- }
- }
- else
- {
- // store in response text
- v_Response = "I don't know. Would you like me to Google: [" + v_UserMessage + "](https://www.google.com/search?q=" + zoho.encryption.urlEncode(v_UserMessage) + ")?";
- }
- }
- //
- // capture answer from bot
- if(!isNull(v_Response) && !v_Response.equalsIgnoreCase("What is your question?"))
- {
- m_Create = Map();
- v_Title = if(v_Response.length()>40, v_Response.subString(0,40) + "...", v_Response);
- m_Create.put("Title", v_Title);
- m_Create.put("Content", v_Response);
- m_Create.put("Role", "assistant");
- m_Create.put("Email", zoho.loginuserid);
- m_Create.put("Owner", v_LoggedInUserID);
- r_Create = zoho.crm.createRecord("GPT_Chats", m_Create);
- }
- //
- // build up output to ZIA chat interface
- m_Prompt = Map();
- m_Prompt.put("param_name","banter");
- m_Prompt.put("prompt_msg",v_Response);
- m_Response.put("prompt",m_Prompt);
- //
- // output
- return m_Response;
- Click on Save Script and test in the sidebar.
- Return to the CRM and click on "Ask ZIA"
- Type "Ask" and click on "Ask ChatGPT"
- On first use, you may be prompted to authorize the connection between CRM and ZIA:
- Click on ChatGPT CRM
- Click on Reuse
- Test on keeping conversation context:
Still to do:
- Need to train it on ZohoCRM data with statistics and datasets. Planning Need to ensure data fed into a session is not shared or available to external sources once entered into OpenAI.
If I train OpenAI on a dataset, can that data be accessed by external sources?
No, if you train OpenAI on a dataset, that dataset and the resulting model will not be accessible by external sources unless you choose to make it publicly available.
OpenAI takes data privacy and security very seriously, and they have implemented several measures to protect the data and models that are used by their services. When you train a model with OpenAI's services, your data is encrypted and stored in a secure environment, and access to the data is restricted to authorized personnel only. OpenAI also has strict policies and procedures in place to prevent unauthorized access, disclosure, or modification of your data.
That being said, it's important to note that the use and distribution of trained models may be subject to legal or ethical considerations, depending on the nature of the data and the intended use of the model. Therefore, if you plan to use or distribute a model trained on a specific dataset, you should carefully review and comply with all applicable laws, regulations, and ethical standards. - OpenAI ChatGPT - BBC News: ChatGPT bug leaked users' conversation histories 2023-03-23
- PCMag UK : ChatGPT Users Report Seeing Other People's Conversation Histories [...report the payment page for ChatGPT Plus possibly exposing email addresses that belong to random users] 2023-03-20
Like my previous article, this needs to be fed contextual data to continue a conversationDone 2023-03-11
Update November 2024
Code to get this working with GPT 4o Mini:
// requires a paid account: https://platform.openai.com/api-keys v_ChatGPT_ServiceAccount_Key = "sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; // m_Header = Map(); m_Header.put("Authorization", "Bearer " + v_ChatGPT_ServiceAccount_Key); m_Header.put("Content-Type","application/json"); // m_Params = Map(); m_Params.put("model","gpt-4o-mini"); m_Params.put("temperature",0.7); l_Messages = List(); // // training messages (a conversation trail with context) m_MessageTraining1 = Map(); m_MessageTraining1.put("role", "user"); m_MessageTraining1.put("content", "Joel Lipman is a technical consultant working with Ascent Business Solutions, the top Zoho Reseller based in the United Kingdom."); l_Messages.add(m_MessageTraining1); // // this message m_ThisMessage = Map(); m_ThisMessage.put("role", "user"); m_ThisMessage.put("content", message); l_Messages.add(m_ThisMessage); m_Params.put("messages", l_Messages); //info m_Params; // r_ChatGPT_Request = invokeurl [ url: "https://api.openai.com/v1/chat/completions" type: POST parameters: m_Params.toString() headers: m_Header ]; //info r_ChatGPT_Request; l_Choices = ifnull(r_ChatGPT_Request.toMap().get("choices"),{}); for each r_Choice in l_Choices { m_Choice = r_Choice.toMap(); if(!isNull(m_Choice.get("message"))) { if(m_Choice.get("message").get("role")=="assistant") { b_ContactedChatGPT = true; my_Text = m_Choice.get("message").get("content") + "\n\n- ChatGPT"; } } } // if(!b_ContactedChatGPT) { my_Text = "Oops! I didn't understand that last question. Calm down, I've been upgraded to version 2.0 so as to give you a better response.\nThe error is:\n \"Something went wrong.\"\nClick [here](https://www.lmgtfy.com/?q=" + v_Message + ") for more info."; }
- // requires a paid account: https://platform.openai.com/api-keys
- v_ChatGPT_ServiceAccount_Key = "sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
- //
- m_Header = Map();
- m_Header.put("Authorization", "Bearer " + v_ChatGPT_ServiceAccount_Key);
- m_Header.put("Content-Type","application/json");
- //
- m_Params = Map();
- m_Params.put("model","gpt-4o-mini");
- m_Params.put("temperature",0.7);
- l_Messages = List();
- //
- // training messages (a conversation trail with context)
- m_MessageTraining1 = Map();
- m_MessageTraining1.put("role", "user");
- m_MessageTraining1.put("content", "Joel Lipman is a technical consultant working with Ascent Business Solutions, the top Zoho Reseller based in the United Kingdom.");
- l_Messages.add(m_MessageTraining1);
- //
- // this message
- m_ThisMessage = Map();
- m_ThisMessage.put("role", "user");
- m_ThisMessage.put("content", message);
- l_Messages.add(m_ThisMessage);
- m_Params.put("messages", l_Messages);
- //info m_Params;
- //
- r_ChatGPT_Request = invokeUrl
- [
- url: "https://api.openai.com/v1/chat/completions"
- type: POST
- parameters: m_Params.toString()
- headers: m_Header
- ];
- //info r_ChatGPT_Request;
- l_Choices = ifnull(r_ChatGPT_Request.toMap().get("choices"),{});
- for each r_Choice in l_Choices
- {
- m_Choice = r_Choice.toMap();
- if(!isNull(m_Choice.get("message")))
- {
- if(m_Choice.get("message").get("role")=="assistant")
- {
- b_ContactedChatGPT = true;
- my_Text = m_Choice.get("message").get("content") + "\n\n- ChatGPT";
- }
- }
- }
- //
- if(!b_ContactedChatGPT)
- {
- my_Text = "Oops! I didn't understand that last question. Calm down, I've been upgraded to version 2.0 so as to give you a better response.\nThe error is:\n \"Something went wrong.\"\nClick [here](https://www.lmgtfy.com/?q=" + v_Message + ") for more info.";
- }
Previous Models/Versions
Based on the documentation: In the above code, you would change the model value to one of the following
code-davinci-002 (optimized for code-completion tasks) text-davinci-002 text-davinci-003 gpt-3.5-turbo (optimized for chat at 1/10th the cost of text-davinci-003) gpt-4 gpt-4-32k (up to 4x the context length)
- code-davinci-002 (optimized for code-completion tasks)
- text-davinci-002
- text-davinci-003
- gpt-3.5-turbo (optimized for chat at 1/10th the cost of text-davinci-003)
- gpt-4
- gpt-4-32k (up to 4x the context length)
Source(s):