Skip to content

Instantly share code, notes, and snippets.

@SMSAgentSoftware
Last active December 13, 2024 19:06
Show Gist options
  • Save SMSAgentSoftware/f1af7b3c0faa595fc15ca3e8671c36e6 to your computer and use it in GitHub Desktop.
Save SMSAgentSoftware/f1af7b3c0faa595fc15ca3e8671c36e6 to your computer and use it in GitHub Desktop.
PowerShell function for Azure OpenAI Chat API interaction via REST.
function Invoke-AzOpenAIChat {
<#
.SYNOPSIS
PowerShell function for Azure OpenAI Chat API interaction via REST.
.DESCRIPTION
Provides a robust interface to Azure OpenAI Chat API with features including:
- Conversation history management
- Token usage tracking
- Markdown rendering support
- Temperature control for response creativity
- Verbosity levels for response detail
- Browser-based markdown viewing option
.PARAMETER Prompt
The message to send to the Azure OpenAI Chat API.
Mandatory: Yes
Pipeline: Accepts input
Position: 0
.PARAMETER Endpoint
The Azure OpenAI endpoint URL.
Mandatory: No
Default: Standard endpoint URL
Validation: Must be HTTPS URL
.PARAMETER Model
The deployment name of the AI model.
Mandatory: No
Default: gpt-4o-mini
Valid values: You define the values that the parameter can accept.
.PARAMETER ApiVersion
API version for Azure OpenAI.
Mandatory: No
Default: 2024-10-21
Validation: Must match YYYY-MM-DD format
.PARAMETER IncludeTokenUsage
Switch to include token usage statistics in response.
Mandatory: No
.PARAMETER Temperature
Controls response creativity and randomness.
Mandatory: No
Default: 0.2
Range: 0.0 - 2.0
.PARAMETER StartNewChat
Switch to start a new chat session / clear chat history.
Mandatory: No
.PARAMETER ModelContext
System context/prompt for AI behavior.
Mandatory: No
Default: PowerShell expert assistant context
.PARAMETER NoMarkdown
Switch to disable markdown rendering.
Mandatory: No
.PARAMETER UseBrowser
Switch to view markdown in browser.
Mandatory: No
.PARAMETER Verbosity
Controls response detail level.
Mandatory: No
Default: medium
Valid values: none, low, medium, high
.EXAMPLE
PS> Invoke-AzOpenAIChat "Write a function to get system info"
Returns AI-generated PowerShell code with explanations
.EXAMPLE
PS> "How to use arrays?" | Invoke-AzOpenAIChat -Temperature 0.8 -Verbosity high
Returns detailed array explanation with high creativity
.NOTES
Author: Trevor Jones
Version: 1.0
Requires: Az.Accounts module
#>
[CmdletBinding()]
param (
# Main prompt parameter
[Parameter(Mandatory = $true,
ValueFromPipeline = $true,
Position = 0)]
[ValidateNotNullOrEmpty()]
[string]$Prompt,
# Azure OpenAI endpoint URL
[Parameter(Mandatory = $false)]
[ValidatePattern('^https:\/\/.*')]
[string]$Endpoint = "https://<my-endpoint>.openai.azure.com",
# AI model selection
[Parameter(Mandatory = $false)]
[ValidateSet("gpt-4o-mini", "gpt-4o")] # Add your models here by their deployment name
[string]$Model = "gpt-4o-mini",
# API version parameter
[Parameter(Mandatory = $false)]
[ValidatePattern('^\d{4}-\d{2}-\d{2}$')]
[string]$ApiVersion = "2024-10-21",
# Token usage tracking switch
[Parameter(Mandatory = $false)]
[switch]$IncludeTokenUsage,
# Response creativity control
[Parameter(Mandatory = $false)]
[ValidateRange(0.0, 2.0)]
[double]$Temperature = 0.2,
# New chat session control
[Parameter(Mandatory = $false)]
[switch]$StartNewChat,
# AI behavior context
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$ModelContext = "You are a helpful and friendly assistant with expertise in PowerShell scripting and command line. Assume user is using the operating system 'Windows 11' unless otherwise specified. ",
# Output format controls
[Parameter(Mandatory = $false)]
[switch]$NoMarkdown,
[Parameter(Mandatory = $false)]
[switch]$UseBrowser,
# Response detail level
[Parameter(Mandatory = $false)]
[ValidateSet("none", "low", "medium", "high")]
[string]$Verbosity = "medium"
)
begin {
# Module dependency check
if (-not (Get-Module -Name Az.Accounts -ListAvailable)) {
try {
Install-Module -Name Az.Accounts -Force -AllowClobber -Scope CurrentUser -Repository PSGallery -ErrorAction Stop
}
catch {
throw "Failed to install Az.Accounts module: $_"
}
}
Import-Module Az.Accounts -ErrorAction Stop
# Set verbosity level text
$verbosityText = switch ($Verbosity) {
"none" { "Just provide the code and do not provide any explanation of it." }
"low" { "Please keep the response concise and to the point. Focus on providing code, and just explain it very briefly." }
"medium" { "Please keep the response concise. Provide a reasonable level of explanation for the code, adding some inline comments." }
"high" { "Provide a detailed explanation of the code and add inline comments to it." }
}
$ModelContext += $verbosityText
# Initialize chat history
if ($StartNewChat -or -not (Get-Variable -Name aichatmessages -ErrorAction SilentlyContinue)) {
$global:aichatmessages = @(@{
role = 'system'
content = $ModelContext
})
}
}
process {
try {
# Get Azure access token with retry
try {
$secureAccessToken = Get-AzAccessToken -ResourceUrl "https://cognitiveservices.azure.com" -AsSecureString -WarningAction SilentlyContinue -ErrorAction Stop |
Select-Object -ExpandProperty Token
}
catch {
Write-Verbose "Initial token acquisition failed, attempting login..."
Connect-AzAccount -WarningAction SilentlyContinue -ErrorAction Stop
$secureAccessToken = Get-AzAccessToken -ResourceUrl "https://cognitiveservices.azure.com" -AsSecureString -WarningAction SilentlyContinue -ErrorAction Stop |
Select-Object -ExpandProperty Token
}
# Convert the secure string token to plain text
if ($PSVersionTable.PSVersion -ge [Version]"7.0") {
$accessToken = $secureAccessToken | ConvertFrom-SecureString -AsPlainText
}
else {
$accessToken = [PSCredential]::new('dummy', $secureAccessToken).GetNetworkCredential().Password
}
# Add user prompt to chat history
$global:aichatmessages += @{
role = "user"
content = $Prompt
}
# Prepare request
$headers = @{ "Authorization" = "Bearer $accessToken" }
$body = @{
temperature = $Temperature
messages = @($global:aichatmessages)
} | ConvertTo-Json
# Make API request with comprehensive error handling
$url = "$Endpoint/openai/deployments/$Model/chat/completions?api-version=$ApiVersion"
try {
$response = Invoke-RestMethod -Uri $url -Method Post -Headers $headers -Body $body -ContentType 'application/json' -ErrorAction Stop
}
catch [System.Net.WebException] {
$statusCode = [int]$_.Exception.Response.StatusCode
$errorMessage = switch ($statusCode) {
401 { "Unauthorized: Please check your authentication token" }
403 { "Forbidden: Access denied to the API endpoint" }
404 { "Not Found: Invalid endpoint or model deployment" }
429 { "Rate Limited: Too many requests, please try again later" }
500 { "Internal Server Error: Azure OpenAI service error" }
503 { "Service Unavailable: Azure OpenAI service is temporarily unavailable" }
default {
$reader = New-Object System.IO.StreamReader($_.Exception.Response.GetResponseStream())
$reader.ReadToEnd()
}
}
throw "API Request Failed ($statusCode): $errorMessage"
}
catch {
throw "Unexpected error during API request: $_"
}
# Update chat history with response
$global:aichatmessages += @{
role = 'system'
content = $response.choices[0].message.content
}
# Format response
$content = $response.choices[0].message.content
if ($IncludeTokenUsage) {
$content += "`n`nCompletion tokens: $($response.usage.completion_tokens) | "
$content += "Prompt tokens: $($response.usage.prompt_tokens) | "
$content += "Total tokens: $($response.usage.total_tokens)"
}
# Handle markdown rendering based on PowerShell version and preferences
if ($PSVersionTable.PSVersion -ge [Version]"6.1" -and -not $NoMarkdown) {
if ($UseBrowser) {
return $content | Show-Markdown -UseBrowser
}
return $content | Show-Markdown
}
return $content
}
catch {
Write-Error "Unexpected error: $_"
return $null
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment