PsChat.psm1
using module ".\Private\OutHelper.psm1" using module ".\Classes\Options.psm1" using module ".\Classes\OpenAiChat.psm1" using module ".\Classes\PsChatUi.psm1" $ErrorActionPreference = "Stop" $OPENAI_AUTH_TOKEN=$ENV:OPENAI_AUTH_TOKEN function Get-PsChatAnswer { <# .SYNOPSIS Request an answer from OpenAI Chat Completion. .DESCRIPTION This function is a wrapper around OpenAI Chat Completion. It takes a question and returns an answer. Please note $ENV:OPENAI_AUTH_TOKEN must be set with a valid OpenAI API key. .PARAMETER InputObject The question (which may include message history) to ask. Must be either: 1) A string or an array of strings, eg. "hello" or @("hello", "whats your name?") 2) A hashtable/object, eg. @{ "role"="user"; "content"="hello" } or @( @{ "role"="user"; "content"="hello" }, @{ "role"="assistant"; "content"="hello" } ) .PARAMETER NoEnumerate If set, the InputObject is not enumerated. This is useful if you want to pass an array of hashtables/objects, eg.: @( @{ "role"="user"; "content"="hello" } @{ "role"="assistant"; "content"="hello" } @{ "role"="user"; "content"="whats your name?" } ) .EXAMPLE Get-PsChatAnswer "What is your name?" # Asks OpenAI Chat for its name. .EXAMPLE "Hello OpenAI" | Get-PsChatAnswer # Says hello to OpenAI using pipes. .EXAMPLE $dialog = @( @{ "role"="user"; "content"="Hello OpenAI. Can we talk Powershell?" }, @{ "role"="assistant"; "content"="Hello! Of course, we can talk about PowerShell. What would you like to know or discuss?" }, @{ "role"="user"; "content"="How does piping work?" } ) Get-PsChatAnswer -InputObject $dialog -NoEnumerate # Asks OpenAI a question, based on previous messages. #> [CmdletBinding()] param( [Parameter(ValueFromPipeline=$true)] [PSObject[]]$InputObject, [Switch]$NoEnumerate, [int]$NumberOfAnswers = 1, [string]$OpenAiAuthToken, [decimal]$Temperature, [decimal]$Top_P ) Begin { # Initialize any variables or resources needed for the function $authToken = if($OpenAiAuthToken) { $OpenAiAuthToken } else { $OPENAI_AUTH_TOKEN } $chatApi = [OpenAiChat]::new($authToken) if($Temperature) { $chatApi.Temperature = $Temperature } if($Top_P) { $chatApi.Top_p = $Top_P } if($NumberOfAnswers -ne 1) { $chatApi.N = $NumberOfAnswers } } Process { # handle array of hashtable/object, eg. @( @{ "role"="user"; "content"="hello" } ) if($NoEnumerate -and $InputObject -is [array]) { Write-Output -InputObject $chatApi.GetAnswer($InputObject) } else { # iterate over each item in the pipeline foreach ($item in $InputObject) { $messages = @() $answer = $null # handle string, eg. "hello" if($item -is [string]) { $messages += [OpenAiChatMessage]::ToAssistant($item) $answer = $chatApi.GetAnswer($messages) } # handle hashtable/object, eg. @{ "role"="user"; "content"="hello" } if($item -is [Hashtable]) { $messages += $item $answer = $chatApi.GetAnswer($messages) } if($null -ne $answer) { Write-Output -InputObject $answer } } } } End { } } function Invoke-PsChat { <# .SYNOPSIS Create an interactive chat session with OpenAI Chat Completion in Powershell. .DESCRIPTION This function creates an interactive chat session with OpenAI Chat Completion in Powershell. You can press 'h' in the chat to get help. Please note $ENV:OPENAI_AUTH_TOKEN must be set with a valid OpenAI API key. .PARAMETER Question The initial question to ask the OpenAI Chat. This parameter is optional. .PARAMETER Single Specifies that the execution will end after the response to the initial question. This parameter is optional. .PARAMETER PreLoadMessagesPath Specifies the path to a JSON-file containing chat messages (useful for providing context). This parameter is optional. .PARAMETER AutoSave Specifies whether the chat messages should be autosaved or not. This parameter is optional, and takes a Switch datatype. .PARAMETER AutoSavePath Specifies the path (file name) to where autosaved chat messages should be stored. This parameter is optional. .PARAMETER WordCountWarningThreshold Specifies the maximum number of words before a warning should be issued. This parameter is optional, and takes an Integer datatype. Its default value is 300 to minimize cost. You can you the 'z' command to compress the dialog into a single message. .EXAMPLE Invoke-PsChat "What is your name?" # Start a chat by asking OpenAI Chat for its name. .EXAMPLE Invoke-PsChat "What is your name?" -Single # Asks the question and quits. #> param( # Initial invocation parameters [Parameter(Position=0)][string]$Question, [Parameter(Position=1)][Switch]$Single, # Options for the chat [string]$PreLoadMessagesPath, [Switch]$AutoSave, [string]$AutoSavePath, [int]$WordCountWarningThreshold = 300, # API parameters [string]$OpenAiAuthToken, [decimal]$Temperature, [decimal]$Top_P ) $options = [Options]::new() $options.AutoSave = $AutoSave $options.AutoSavePath = $AutoSavePath $options.WordCountWarningThreshold = $WordCountWarningThreshold $options.PreLoadMessagesPath = $PreLoadMessagesPath # initialize the api $authToken = if($OpenAiAuthToken) { $OpenAiAuthToken } else { $OPENAI_AUTH_TOKEN } $chat = [PsChatUi]::new($authToken, $options) if($Temperature) { $chat.ChatApi.Temperature = $Temperature } if($Top_P) { $chat.ChatApi.Top_p = $Top_P } $chat.Start($Question, $Single) return } Export-ModuleMember -Function Invoke-PsChat, Get-PsChatAnswer |