How To Build an AI-Driven PowerShell Code Generator (Sample Script)
Discover how to automate the extraction of PowerShell code generated by ChatGPT. After learning about the process, you will have the opportunity to review the complete source code.
November 15, 2023
It’s a well-known fact that ChatGPT can generate PowerShell code. Normally, after the AI-generated code is shown on the screen, users must manually copy and paste the code into a file to then create a PowerShell script. However, what if you could automate this process?
In this article, I will show you a PowerShell script that uses AI to automatically generate other PowerShell scripts.
Before getting started, I strongly recommend reading my article on building ChatGPT-enabled PowerShell scripts. The script that I am going to show you below relies on the ChatGPT integration method explained in that article. I won’t revisit the details of the ChatGPT integration here. Instead, my focus will be explaining how to automatically export PowerShell code generated by ChatGPT.
How the PowerShell Script Works
Building a PowerShell script that uses AI to generate other PowerShell scripts primarily involves string manipulation. The script must process the response generated by ChatGPT, extract only the script code, and then write that code to a script file. To see what I mean, take a look at Figure 1.
Code Generator 1
Figure 1. This is what it looks like when ChatGPT generates code.
While ChatGPT generates the requested code, it also includes extraneous text unrelated to the code. Before we can produce a script file, we must eliminate everything except the actual code.
Here is the portion of the code that handles the string manipulation. The complete code will be provided at the end of this article.
$Code=$aiResponse$IndexValue = $Code.IndexOf("``")$Temp1 = $Code.substring($IndexValue+3)$IndexValue = $Temp1.IndexOf("``")$Temp2 = $Temp1.substring(0, $IndexValue-1)$Code = $Temp2$FinalCode=$Code# Code to remove the word PowerShell from the beginning of the string$PS=$Code.Substring(0,10)Write-host "PS is equal to " $PSIf ($PS -eq 'powershell'){ $FinalCode=$Temp2.Substring(10) }# Output results$File = Read-Host "Please enter a filename (without an extension)"$Filepath = "C:Scripts" + $File + ".ps1"$FinalCode | Out-File -FilePath $Filepath
In the above code block, the first step involves creating a variable named $Code. Initially, the $Code variable contains the entire text generated by ChatGPT.
Referring back to Figure 1, you will notice three characters (```) just before the code block. Therefore, another variable, $IndexValue, is established to store the count of characters before (and including) the first occurrence of the ` character.
The next line of code introduces a new variable, $Temp1. I set $Temp1 equal to $Code.substring($Indexvalue+3). This substring operation instructs PowerShell to delete the first segment of the string up to the specified character. The $IndexValue variable reflects the position of the first ` character. Since there are three consecutive characters, I appended +3 to eliminate all three. At this point, the $Temp1 variable contains the actual code and anything following it. We have successfully removed any descriptive text appearing before the actual code.
We must now get rid of any text that comes after the actual code. To do this, I have declared the $IndexValue variable once again, this time based on the $Temp1 variable, not the $Code variable. This change is made because the only occurrence of the ` characters in $Temp1 is immediately after the code.
Next, I create another variable, $Temp2. Once again, I perform a substring operation, but I handle this one a little differently. My previous substring operation simply told PowerShell how many characters to remove from the beginning of the string. This time, the substring contains two numbers (0 and $IndexValue-1). This instructs PowerShell to retain all characters before the ` and delete everything else. Consequently, $Temp2 contains only the code block.
Before writing the output to a file, there is one more thing to do. Occasionally (though not always), when ChatGPT generates PowerShell code, the first line of the code block simply says “PowerShell.” We need to check for the existence of the word “PowerShell” and, if present, remove it. That is handled by the following block of code:
$PS=$Code.Substring(0,10)Write-host "PS is equal to " $PSIf ($PS -eq 'powershell'){ $FinalCode=$Temp2.Substring(10) }
Here, I have created a variable named $PS, which contains the first 10 characters of our string. In case you are wondering, I have copied $Temp to $Code, hence why we are examining the first 10 characters of $Code. I then use an If statement to check if these 10 characters spell out the word “PowerShell.” If they do, those 10 characters are stripped from the string. The final string is stored in a variable called $FinalCode.
The final step in the script is to generate a script file based on the code extracted from the ChatGPT output. I do that with these three lines of code:
$File = Read-Host "Please enter a filename (without an extension)"$Filepath = "C:Scripts" + $File + ".ps1"$FinalCode | Out-File -FilePath $Filepath
The first line prompts the user to enter a filename, minus the extension. The second line establishes a variable named $Filepath to create the complete path and filename for the script file being generated. The script file is saved with a .ps1 extension in the C:Scripts folder. The third line uses the Out-File cmdlet to export the contents of the $FinalCode variable to the script file.
Complete Source Code
Here is the full source code for my script:
$Key = Get-Content C:ScriptsGPTKey.txt$ApiEndpoint = "https://api.openai.com/v1/chat/completions"$AiSystemMessage = "You are a helpful assistant"[System.Collections.Generic.List[Hashtable]]$MessageHistory = @()Function Initialize-MessageHistory ($message){ $script:MessageHistory.Clear() $script:MessageHistory.Add(@{"role" = "system"; "content" = $message}) | Out-Null}function Invoke-ChatGPT ($MessageHistory) { # Set the request headers $headers = @{ "Content-Type" = "application/json" "Authorization" = "Bearer $Key" } # Form the Request $requestBody = @{ "model" = "gpt-3.5-turbo" "messages" = $MessageHistory "max_tokens" = 1000 # Max amount of tokens the AI will respond with "temperature" = 0.7 # Lower is more coherent, higher is more creative. } # Send the request $response = Invoke-RestMethod -Method POST -Uri $ApiEndpoint -Headers $headers -Body (ConvertTo-Json $requestBody) # Return the message content return $response.choices[0].message.content}#Main BodyInitialize-MessageHistory $AiSystemMessage $userMessage = Read-Host "Enter your query: " $MessageHistory.Add(@{"role"="user"; "content"=$userMessage}) $aiResponse = Invoke-ChatGPT $MessageHistory Write-Host "AI: $aiResponse" -ForegroundColor Yellow# Extract the code$Code=$aiResponse$IndexValue = $Code.IndexOf("``")$Temp1 = $Code.substring($IndexValue+3)$IndexValue = $Temp1.IndexOf("``")$Temp2 = $Temp1.substring(0, $IndexValue-1)$Code = $Temp2$FinalCode=$Code# Code to remove the word PowerShell from the beginning of the string$PS=$Code.Substring(0,10)Write-host "PS is equal to " $PSIf ($PS -eq 'powershell'){ $FinalCode=$Temp2.Substring(10) }# Output results$File = Read-Host "Please enter a filename (without an extension)"$Filepath = "C:Scripts" + $File + ".ps1"$FinalCode | Out-File -FilePath $Filepath
About the Author
You May Also Like