Posey's Tips & Tricks
Do-It-Yourself AI, Part 4: Building the Bot
It's time to put everything in the previous lessons together to build your very own chat bot.
So far in this blog series, I have shown you how to set up DeepSeek-R1 to run on your own hardware, independently of the cloud, and I have demonstrated a technique for using PowerShell to filter the clutter from the output. Now, I want to wrap up this series by showing you how to use PowerShell to build a full-blown AI chatbot based on what you have already done. You can see what my chatbot looks like in Figure 1.
[Click on image for larger view.] Figure 1. This is the PowerShell chatbot that I have created.
As you can see in the figure, the chatbot features an input pane where you can enter your query. Upon doing so, your query is displayed in blue within the outbox, followed by Deepseek-R1's filtered output, which is displayed in black. Once you have finished typing your query, you can click the Submit button, but pressing the Enter key has the same effect as clicking Submit. Clicking the Save Conversation button exports the conversation to a text file and clicking Exit closes the script.
Given the script's length and the amount of space that I have to work with in this blog post, I won't be able to give you a line-by-line walkthrough of how the script works. However, I do want to give you a high level overview and I will provide you with the full source code at the end.
Although PowerShell has a reputation for being a text only environment, you can create a GUI interface by using Windows forms. A form is essentially just a window. In this script, I created a form and then created a series of additional GUI objects, which I attached to the form. These objects included text boxes and buttons. The script's final line of code ($Form.ShowDialog() | Out-Null) causes the form to be displayed on screen.
The GUI related code used within the script is relatively straightforward. For each GUI object, the script defines things such as the object's position on the screen, as well as the colors and fonts used. What's a lot more interesting are the event handlers.
Whenever you create a button object, you need to define a click action. This click action defines what is going to happen when the button is clicked. In the case of the Exit button for example, the click action is $Form.Close(), which instructs PowerShell to close the window. Similarly when you click on the Save Conversation button, the click action takes all of the text that exists within the output box and then uses the Set-Content cmdlet to open the Save File Dialog Box. As you can see in Figure 2, this dialog box is configured to save the conversation as a text file. You can name the file anything that you want, but by default the dialog box will attempt to save the file in the Documents folder.
[Click on image for larger view.] Figure 2. This is the dialog box used to save the conversation to a text file.
So with that said, let's talk about the Submit button and its event handler. Here is the block of code associated with the Submit button:
# Function to handle output text color
Function Add-To-Chat {
Param($Text, $Color)
# Set the color to the text being appended
$OutputBox.SelectionStart = $OutputBox.TextLength
$OutputBox.SelectionLength = 0
# Ensure color is correctly assigned using System.Drawing.Color
$OutputBox.SelectionColor = $Color
# Append the text with the desired color
$OutputBox.AppendText("$Text`r`n")
# Reset color to default (black) after appending
$OutputBox.SelectionColor = "#FF000000"
}
# Event Handler for Submit Button
$SubmitButton.Add_Click({
$UserInput = $InputBox.Text
if ($UserInput -ne "") {
# Blue for user input
Add-To-Chat -Text "You: $UserInput" -Color "#FF0000FF"
#Send query to DeepSeek-R1
$Query = $UserInput
# Get response and filter it
$Response = & ollama run deepseek-r1 $Query
$ResponseString = $Response -Join "`n"
$Filter = "(?s)<think>.*?</think>\r?\n?"
$FilteredText = [regex]::replace($ResponseString, $Filter, "")
# Black for bot response
Add-To-Chat -Text "DeepSeek-R1: $FilteredText " -Color "#FF000000"
# Clear the input box
$InputBox.Clear()
}
})
A lot of this code should look familiar based on my previous blog post. As you may recall, I used a filter to get rid of DeepSeek-R1's reasoning text. However, there is more going on here than just the filtering of text.
When the user clicks the Submit button, the script looks at the user's input, which is stored in $InputBox.Text, and checks to make sure that the input box is not empty. After that, the script passes the input query and a color code (which is represents blue) to a function called Add-To-Chat.
The Add-To-Chat function performs a text selection, though it does not actually select anything. It does this because one of the limitations associated with the type of text box that I am using is that the only way to change the text color without changing the color of any pre-existing text is to perform a test selection and then change the color of the selected text.
Once the color has been set to blue, the user's query is added to the text box. The `r`n codes force a line break after the query is displayed. Next, the text color is set back to black.
With the Add-To-Chat function complete, the user's query is sent to DeepSeek-R1. This submission and the subsequent filtering process works identically to what you saw in the previous article. Once the response has been filtered, the response is added to the output box. Finally, the input box is cleared of any remaining text in order to make way for the user's next query.
Incidentally, I mentioned earlier that when you type a query you can either click the Submit button or just press Enter. Here is the code associated with the Enter key:
$InputBox.Add_KeyPress({
Param($Sender, $E)
if ($E.KeyChar -eq [Char]13) { # Check if Enter key was pressed
$SubmitButton.PerformClick()
}
})
This block of code checks to see if the Enter key has been pressed. If so, then PowerShell will literally click the Submit button on your behalf.
In my opinion, the script that I have created does a good job, but I tend to think of it as a version 1.0 effort. Even as I am concluding this blog post, I can think of a lot of capabilities that I would like to build into this script, such as the ability to use multiple AI models. I will most likely revisit the topic at some point in the near future and build a more advanced AI model.
So with that said, here is the full source code for my current script. I hope that you have as much fun with it as I have. Here is the code:
Add-Type -AssemblyName System.Windows.Forms
# Create the Form
$Form = New-Object System.Windows.Forms.Form
$Form.Text = "Poseys DeepSeek-R1 Chatbot"
$Form.Size = New-Object System.Drawing.Size(800, 600)
$Form.StartPosition = "CenterScreen"
# Create the User Input TextBox (Multiline for long text)
$InputBox = New-Object System.Windows.Forms.TextBox
$InputBox.Location = New-Object System.Drawing.Point(10, 10)
$InputBox.Size = New-Object System.Drawing.Size(650, 100)
$InputBox.Font = New-Object System.Drawing.Font("Arial", 14) # Default font
$InputBox.Multiline = $true
$InputBox.ScrollBars = "Vertical"
# Create the Submit Button
$SubmitButton = New-Object System.Windows.Forms.Button
$SubmitButton.Location = New-Object System.Drawing.Point(675, 40)
$SubmitButton.Size = New-Object System.Drawing.Size(75, 25)
$SubmitButton.Text = "Submit"
# Create the Conversation History TextBox (Multiline)
$OutputBox = New-Object System.Windows.Forms.RichTextBox
$OutputBox.Location = New-Object System.Drawing.Point(10, 120)
$OutputBox.Size = New-Object System.Drawing.Size(750, 390)
$OutputBox.Font = New-Object System.Drawing.Font("Arial", 14) # Default font
$OutputBox.BackColor = "#FFFFFFFF"
$OutputBox.ReadOnly = $true
$OutputBox.Multiline = $true
$OutputBox.ScrollBars = "Vertical"
# Create the Save Conversation Button
$SaveButton = New-Object System.Windows.Forms.Button
$SaveButton.Location = New-Object System.Drawing.Point(10, 515)
$SaveButton.Size = New-Object System.Drawing.Size(150, 30)
$SaveButton.Text = "Save Conversation"
# Create the Exit Button
$ExitButton = New-Object System.Windows.Forms.Button
$ExitButton.Location = New-Object System.Drawing.Point(210, 515)
$ExitButton.Size = New-Object System.Drawing.Size(75, 30)
$ExitButton.Text = "Exit"
# Function to handle output text color
Function Add-To-Chat {
Param($Text, $Color)
# Set the color to the text being appended
$OutputBox.SelectionStart = $OutputBox.TextLength
$OutputBox.SelectionLength = 0
# Ensure color is correctly assigned using System.Drawing.Color
$OutputBox.SelectionColor = $Color
# Append the text with the desired color
$OutputBox.AppendText("$Text`r`n")
# Reset color to default (black) after appending
$OutputBox.SelectionColor = "#FF000000"
}
# Event Handler for Submit Button
$SubmitButton.Add_Click({
$UserInput = $InputBox.Text
if ($UserInput -ne "") {
# Blue for user input
Add-To-Chat -Text "You: $UserInput" -Color "#FF0000FF"
#Send query to DeepSeek-R1
$Query = $UserInput
# Get response and filter it
$Response = & ollama run deepseek-r1 $Query
$ResponseString = $Response -Join "`n"
$Filter = "(?s)<think>.*?</think>\r?\n?"
$FilteredText = [regex]::replace($ResponseString, $Filter, "")
# Black for bot response
Add-To-Chat -Text "DeepSeek-R1: $FilteredText " -Color "#FF000000"
# Clear the input box
$InputBox.Clear()
}
})
# Event Handler for Save Button
$SaveButton.Add_Click({
$SaveFileDialog = New-Object System.Windows.Forms.SaveFileDialog
$SaveFileDialog.Filter = "Text Files (*.txt)|*.txt"
$SaveFileDialog.Title = "Save Conversation"
$SaveFileDialog.ShowDialog()
if ($SaveFileDialog.FileName -ne "") {
# Save the conversation text to the file
$OutputBox.Text | Set-Content $SaveFileDialog.FileName
[System.Windows.Forms.MessageBox]::Show("Conversation Saved!", "Success")
}
})
# Event Handler for Exit Button
$ExitButton.Add_Click({
$Form.Close()
})
# Event Handler for Enter Key (Pressing Enter does the same thing as clicking the Submit button.)
$InputBox.Add_KeyPress({
Param($Sender, $E)
if ($E.KeyChar -eq [Char]13) { # Check if Enter key was pressed
$SubmitButton.PerformClick()
}
})
# Add Controls to Form
$Form.Controls.Add($InputBox)
$Form.Controls.Add($SubmitButton)
$Form.Controls.Add($OutputBox)
$Form.Controls.Add($SaveButton)
$Form.Controls.Add($ExitButton)
# Show Form
$Form.ShowDialog() | Out-Null
About the Author
Brien Posey is a 22-time Microsoft MVP with decades of IT experience. As a freelance writer, Posey has written thousands of articles and contributed to several dozen books on a wide variety of IT topics. Prior to going freelance, Posey was a CIO for a national chain of hospitals and health care facilities. He has also served as a network administrator for some of the country's largest insurance companies and for the Department of Defense at Fort Knox. In addition to his continued work in IT, Posey has spent the last several years actively training as a commercial scientist-astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space. You can follow his spaceflight training on his Web site.