ChatGPT Integration in PowerShell (Scripting Demo)

Watch this video to learn how to integrate ChatGPT capabilities into your PowerShell scripts.

Brien Posey

September 28, 2023

In this video tutorial, Brien Posey explains a PowerShell script that allows you to interact with ChatGPT. The functions and structure of the script make it easy to integrate ChatGPT capabilities into your own PowerShell scripts.

The transcript below has been lightly edited for clarity and length.

Transcript:

Brien Posey: Hello, greetings, and welcome. I'm Brien Posey. In this video, I want to show you how to use PowerShell to interact with ChatGPT.

So, what I've done is found a script on GitHub that allows you to carry on a ChatGPT conversation from PowerShell. I took that script, and I broke it down to its most basic components. I want to show you what those components are. Knowing what those components are will make it much easier to integrate ChatGPT capabilities into your own scripts.

Let's go ahead and get started by looking at what my script does.

<span style="background-color:white"><span style="color:black">$Key = "Get-Content C:ScriptsGPTKey.txt"</span></span><span style="background-color:white"><span style="color:black">$ApiEndpoint = "https://api.openai.com/v1/chat/completions"</span></span><span style="background-color:white"><span style="color:black">$AiSystemMessage = "You are a helpful assistant"</span></span><span style="background-color:white"><span style="color:black">[System.Collections.Generic.List[Hashtable]]$MessageHistory = @()</span></span>
<span style="background-color:white"><span style="color:black">Function Initialize-MessageHistory ($message){</span></span><span style="background-color:white"><span style="color:black">    $script:MessageHistory.Clear()</span></span><span style="background-color:white"><span style="color:black">    $script:MessageHistory.Add(@{"role" = "system"; "content" = $message}) | Out-Null</span></span><span style="background-color:white"><span style="color:black">}</span></span>
<span style="background-color:white"><span style="color:black">function Invoke-ChatGPT ($MessageHistory) {</span></span><span style="background-color:white"><span style="color:black">    # Set the request headers</span></span><span style="background-color:white"><span style="color:black">    $headers = @{</span></span><span style="background-color:white"><span style="color:black">    "Content-Type" = "application/json"</span></span><span style="background-color:white"><span style="color:black">    "Authorization" = "Bearer $ApiKey"</span></span><span style="background-color:white"><span style="color:black">    }  </span></span>

 

<span style="background-color:white"><span style="color:black"># Form the Request</span></span><span style="background-color:white"><span style="color:black">    $requestBody = @{</span></span><span style="background-color:white"><span style="color:black">        "model" = "gpt-3.5-turbo"</span></span><span style="background-color:white"><span style="color:black">        "messages" = $MessageHistory</span></span><span style="background-color:white"><span style="color:black">        "max_tokens" = 1000 # Max amount of tokens the AI will respond with</span></span><span style="background-color:white"><span style="color:black">        "temperature" = 0.7 # Lower is more coherent and conservative, higher is more creative and diverse.</span></span><span style="background-color:white"><span style="color:black">    }</span></span>
<span style="background-color:white"><span style="color:black">    # Send the request</span></span><span style="background-color:white"><span style="color:black">    $response = Invoke-RestMethod -Method POST -Uri $ApiEndpoint -Headers $headers -Body (ConvertTo-Json $requestBody)</span></span>
<span style="background-color:white"><span style="color:black">    # Return the message content</span></span><span style="background-color:white"><span style="color:black">    return $response.choices[0].message.content</span></span><span style="background-color:white"><span style="color:black">}</span></span>
<span style="background-color:white"><span style="color:black">#Main Body</span></span><span style="background-color:white"><span style="color:black">Initialize-MessageHistory $AiSystemMessage</span></span><span style="background-color:white"><span style="color:black">    $userMessage = Read-Host "`Enter your query: "</span></span><span style="background-color:white"><span style="color:black">    $MessageHistory.Add(@{"role"="user"; "content"=$userMessage})</span></span><span style="background-color:white"><span style="color:black">    $aiResponse = Invoke-ChatGPT $MessageHistory</span></span><span style="background-color:white"><span style="color:black">    Write-Host "AI: $aiResponse" -ForegroundColor Yellow</span></span><span style="background-color:white"><span style="color:black">    $MessageHistory.Add(@{"role"="assistant"; "content"=$aiResponse})</span></span>

When I read the script, I'm prompted to enter my query. I'm just going to type, “Hello,” and press Enter. My query goes up to ChatGPT and then a response is returned. I'm then dropped back down to the PowerShell command prompt. That's the entire thing. That's what this script does.

Now that I've shown you what this does, let's go ahead and look at the code behind the script.

And as I mentioned, this is an adaptation of some code that I found on GitHub.

First Block of Code

To use ChatGPT programmatically, you're going to need an API key. The API key is something that you can get from ChatGPT. There is a small fee associated with using an API key.

The very first line of code simply reads my key from a text file:

$Key = Get-Content C:ScriptsGPTKey.txt

I didn't want to include the key in clear text within the script for obvious reasons.

So, we're reading the key, and we're saving it to a variable called $Key.

The next thing that we have to do is define the ChatGPT endpoint. That's simply the URI that's used for sending queries up to ChatGPT. You can see that in the second line of code:

$APIEndpoint = “https://api.openai.com/v1/chat/completions”

Then the next thing that we have is a declaration of $AISystemMessage. You can see that on the third line:

$AISystemMessage = “You are a helpful assistant”

Right now, the system message is, “You are a helpful assistant.” Now, technically, we don't need this line. But what we're doing right here is we're setting the ChatGPT personality. Later on, when I show you how we go about initializing ChatGPT, we're going to want to have some kind of text in there. For the initialization process, what we're using in this case, is, “You are a helpful assistant.” Now, you'll notice the variable name – $AISystemMessage. We're going to be using the variable $AISystemMessage throughout the script when we want to send something up to ChatGPT. So, anytime you see the variable $AISystemMessage, that's what that is. It represents the query that the user has typed in, which is being sent to ChatGPT.

Then in the fourth line right here, we're creating a hash table:

[System.Collections.Generic.List[Hashtable]]$MessageHistory = @()

This hash table was called Message History. Now, the message history is essentially just a list of all the queries that we've sent up to ChatGPT and the responses that we've received from ChatGPT. In this particular case, the message history isn't all that important, because we're only sending a single query and we're receiving a single response. However, because of the way that the ChatGPT API works, we have to send this message history hash table anytime that we query ChatGPT. So, that's our basic initialization.

Initialize-MessageHistory Function

From there, we have a couple of functions.

We have one function called Initialize-MessageHistory:

<span style="background-color:white"><span style="color:black">Function Initialize-MessageHistory ($message){</span></span><span style="background-color:white"><span style="color:black">    $script:MessageHistory.Clear()</span></span><span style="background-color:white"><span style="color:black">    $script:MessageHistory.Add(@{"role" = "system"; "content" = $message}) | Out-Null</span></span><span style="background-color:white"><span style="color:black">}</span></span>

Then we have another function called Invoke-ChatGPT:

<span style="background-color:white"><span style="color:black">function Invoke-ChatGPT ($MessageHistory) {</span></span><span style="background-color:white"><span style="color:black">    # Set the request headers</span></span><span style="background-color:white"><span style="color:black">    $headers = @{</span></span><span style="background-color:white"><span style="color:black">    "Content-Type" = "application/json"</span></span><span style="background-color:white"><span style="color:black">    "Authorization" = "Bearer $ApiKey"</span></span><span style="background-color:white"><span style="color:black">    }  </span></span>

I'll come back to these in just a moment.

What I want to do for right now is skip down to the main body:

<span style="background-color:white"><span style="color:black">Initialize-MessageHistory $AiSystemMessage</span></span><span style="background-color:white"><span style="color:black">    $userMessage = Read-Host “`nYou”</span></span><span style="background-color:white"><span style="color:black">    $MessageHistory.Add(@{“role”=”user”; “content”=$userMessage})</span></span><span style="background-color:white"><span style="color:black">    $aiResponse = Invoke-ChatGPT $MessageHistory</span></span><span style="background-color:white"><span style="color:black">    Write-Host “AI: $aiResponse” -ForegroundColor Yellow</span></span><span style="background-color:white"><span style="color:black">    $MessageHistory.Add(@{“role”=”assistant”; “content”=$aiResponse})</span></span>

So, the very first thing that we're doing within the main body of our script is calling the Initialize-MessageHistory function that I pointed out just a second ago.

You'll notice that we're passing a parameter up to that function, and that parameter is $AISystemMessage. Remember what I said about this variable earlier: $AISystemMessage represents anything that the user has typed in that's being sent up to ChatGPT. Well, the user hasn't typed in anything yet, but we pre-populated this variable earlier, during the initialization portion of the script, with the phrase, “You are a helpful assistant.”

So, we're taking the text, “You are a helpful assistant,” and we're sending that to the Initialized-MessageHistory function.

Let's take a look at that function. You can see that it receives a parameter called $message. The $message is the $AISystemMessage variable. So, what are we doing here? Well, the very first line within that function goes ahead and clears out the hash table. That way, if you run the script more than once and there's already something in that hash table, this will go ahead and clear it just to prevent any confusion.

The next thing we have is a line that populates the message history:

$script:MessageHistory.Add(@{“role” = “system”; “content” = $message}) | Out-Null

What we're doing is we're using “role” to define who it was that put a message in the message history. The role was either going to be “system” if it was something that was generated on this end, or it was going to be AI if it was something that was generated by ChatGPT. Then we have “content.” The content is whatever query or response is going into the message history in this case. Because we're initializing ChatGPT, the content is going to be that initial message, “You are a helpful assistant.” So, that's what's going to be contained in the $message variable. Then we have Out-Null, and that just suppresses any output.

So, we've called the function. We've initialized ChatGPT by clearing out our message history and then adding the message, “You are a helpful assistant,” to the message history hash table.

Main Body

Then we drop back down to our main body. The next line of code is:

$userMessage = Read-Host “Enter your query”: “

So, this is the prompt that you saw earlier that displays the message, “Enter your query,” on the screen. Whatever the user types in goes to a variable called $userMessage.

Then we have the next line:

$MessageHistory.Add(@{“role” = “user”; “content” = $userMessage})

Once again, we're adding something to the message history. Anytime that we add to the message history, we have to specify the role and we have to specify the content. So, the role in this case is “user,” indicating that this is something that was typed in by the end user. The “content” is going to be whatever is stored in that $userMessage variable that we defined on the previous line of code. So, we're adding the message that was typed into the message history.

The next thing that happens is, we're defining a variable $aiResponse:

<span style="color:black">$aiResponse = Invoke-ChatGPT $MessageHistory</span>

Now, remember what I said earlier: Anytime that we send something up to ChatGPT, we have to include the entire message history. So, what we're doing right here is we're calling a function called Invoke-ChatGPT and passing the entire message history up to that function.

Invoke-ChatGPT Function

If we look back at the Invoke-ChatGPT function, this function is designed to receive the message history. So, what are we really doing within this function? Well, there's a couple of things going on here.

Form a header

The first thing that we have to do is we have to form a header. You can see that we've declared a variable called $header:

<span style="background-color:white"><span style="color:black">$headers = @{</span></span><span style="background-color:white"><span style="color:black">    "Content-Type" = "application/json"</span></span><span style="background-color:white"><span style="color:black">    "Authorization" = "Bearer $ApiKey"</span></span><span style="background-color:white"><span style="color:black">    }  </span></span>

This is also going to be a hash table. We're defining “Content-Type,” and then we have to define the “Authorization.” And we're using key-based authorization.

Remember, in the very first line of code in the script, we set up a variable called $Key and set that equal to our API key that we read in from a text file:

$Key = Get-Content C:ScriptsGPTKey.txt

That's where this $Key variable comes into play.

So, we formed our header.

Form the request

The next thing that this function has to do is to form the request. So, what we're doing is we're setting up a variable called $requestBody. And once again, this is going to be a hash table.

<span style="background-color:white"><span style="color:black">$requestBody = @{</span></span><span style="background-color:white"><span style="color:black">        "model" = "gpt-3.5-turbo"</span></span><span style="background-color:white"><span style="color:black">        "messages" = $MessageHistory</span></span><span style="background-color:white"><span style="color:black">        "max_tokens" = 1000 # Max amount of tokens the AI will respond with</span></span><span style="background-color:white"><span style="color:black">        "temperature" = 0.7 # Lower is more coherent and conservative, higher is more creative and diverse.</span></span><span style="background-color:white"><span style="color:black">    }</span></span>

Then we're defining a few things. First, “model.” The model is going to be the AI model that gets used to process the request. In this case, we're using GPT-3.5-turbo.

The next thing that we have to include in the request body is the message. The message is going to be contained in that $MessageHistory variable that I talked about a moment ago.

Next, we have something called “max_tokens.” Now, the “max_tokens” indicates the maximum length of the response that ChatGPT can give you.

The reason why this “max_tokens” is important is because, as I mentioned, there is a small charge associated with using ChatGPT programmatically. You're charged based on the length of the response. So, you don't want to have a response that's lengthier than what you need, because it will cost you more money. That's where “max_tokens” comes into play.

And then we have “temperature.” Temperature essentially sets the tone of the response. By default, the temperature is set to 0.7, but if you reduce this number, then the response is going to be more businesslike, more no-nonsense, whereas a higher value tends to be a bit more creative, perhaps in some instances even a little bit humorous.

So, at this point, we've set the request header, and we formed the request.

Send the request

From there, what we have to do is send all of this up to ChatGPT. You can see that we're creating a variable called $response:

<span style="background-color:white"><span style="color:black">$response = Invoke-RestMethod -Method POST -Uri $ApiEndpoint -Headers $headers -Body (ConvertTo-Json $requestBody)</span></span>

All this information within the request body started in the form of a hash table. But we're converting that to JSON format and then passing that up to ChatGPT.

Return the message content

So, then we've got a return statement, followed by $response.choices:

<span style="background-color:white"><span style="color:black">return $response.choices[0].message.content</span></span>

ChatGPT will sometimes generate multiple responses. So, this number zero simply indicates that we want the first response. And then we have .message.content so we're returning the response that was generated by ChatGPT. And then our function ends.

Remaining Lines of Main Body

So then if we drop back down to our main body, you can see that the next line of code is this:

<span style="background-color:white"><span style="color:black">Write-Host “AI: $aiResponse” -ForegroundColor Yellow</span></span>

We just set the foreground color to yellow. That's not something that you have to do. But sometimes it can make it a little bit easier to tell which part of the conversation was generated by ChatGPT versus user input.

So, we're simply displaying the $aiResponse variable. That's the response from ChatGPT.

And then the very last line of code is adding that response to the message history:

<span style="background-color:white"><span style="color:black">$MessageHistory.Add(@{“role”=”assistant”; “content”=$aiResponse})</span></span>

Again, we don't have to worry about that so much in this case, because we're only going to have a single query and a single response. But if you created a script where there were going to be multiple queries and multiple responses, then you would absolutely want to add the responses to the message history.

So, that's just a really quick overview of how you can use PowerShell to interact with ChatGPT.

About the Author

Brien Posey

Brien Posey is a bestselling technology author, a speaker, and a 20X Microsoft MVP. In addition to his ongoing work in IT, Posey has spent the last several years training as a commercial astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space.

http://brienposey.com/

Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like