PowerShell 整合 ChatGPT API 執行批次任務
3 |
處理資料時請 ChatGPT 幫忙已成日常,就算是寫 PowerShell 時也不例外。因此,我想要有個函式,希望能做到傳 Prompt 批次呼叫 ChatGPT API 執行翻譯、摘要等的任務,隨時隨地想要 AI 就有 AI。
舉個例子,假設我有個 JSON 檔 demo.json:
[
{ "id": 1, "name_en": "Harry Potter and the Philosopher's Stone" },
{ "id": 2, "name_en": "The Bridges of Madison County"},
{ "id": 3, "name_en": "The Da Vinci Code"},
{ "id": 4, "name_en": "Anne of Green Gables"}
]
希望能用短短幾行 PowerShell 程式為 JSON 裡的英文書加上台灣翻譯書名:
. .\gpt-chat.ps1
SetSystemPrompt '你是暢銷書專家,請將以下英文書名翻譯成台灣發行書名(只需回答書名即可):'
Get-Content .\demo.json | ConvertFrom-Json | ForEach-Object {
$item = [PSCustomObject]$_
$name_cht = CallComplete $_.name_en
# 迴圈呼叫時,實務上可能要加點時間間隔避免超過流量上限
# 更有效率的做法是改成一次查詢多筆,再從回答解析取出多筆結果
Start-Sleep -Seconds 1
$item | Add-Member -MemberType NoteProperty -Name name_cht -Value $name_cht
return $item
} | ConvertTo-Json
期望執行後得到以下內容:
這個 gpt-chat.ps1 要怎麼寫呢?一點也不難。
若你有 Azure OpenAI API 服務,開啟 Azure OpenAI Studio 的聊天遊樂場,裡面有個【檢視程式碼】功能:
上面有 C#、Python、JavaScript、Java、Go 的程式範例,PowerShell 的話,則可參考 curl 寫法,改寫成 Invoke-WebRequets 或 Invoke-RestMethod 即可。
實測發現 PowerShell 5 的 Invoke-RestMethod 的 UTF8 支援不佳,索性改用 WebClient 物件較好控制細節;PowerShell 6+ 則可直接用 Invoke-RestMethod。而依照慣例,我不愛 API Key 用碼存,故花了點工夫用 SecretString 加密,而首次使用會詢問 URL 跟 API Key (如下圖),參考上圖 curl 範例中的網址跟 API 金鑰填入存成 .settings JSON 檔,之後就可以愉快使用了。
以下是完整程式碼:
param ([string]$question)
$ErrorActionPreference = "Stop"
$settingsPath = '.\azure-openai.settings'
function ReadApiSettings() {
try {
if (Test-Path $settingsPath) {
$settings = Get-Content $settingsPath | ConvertFrom-Json
$apiUrl = $settings.apiUrl
$apiKey = $settings.apiKey
}
}
catch { }
if ([string]::IsNullOrEmpty($apiUrl) -or [string]::IsNullOrEmpty($apiKey)) {
Write-Host "Please set Azure OpenAI url and key" -ForegroundColor Yellow
if ([string]::IsNullOrEmpty($apiUrl)) {
Write-Host " ex: https://<host-name>.openai.azure.com/openai/deployments/<deploy-name>/chat/completions?api-version=2024-02-15-preview"
Write-Host "API Url: " -ForegroundColor Cyan
$apiUrl = Read-Host
}
if ([string]::IsNullOrEmpty($apiKey)) {
Write-Host "API Key: " -ForegroundColor Cyan
$apiKey = Read-Host -AsSecureString | ConvertFrom-SecureString
}
@{
apiUrl = $apiUrl
apiKey = $apiKey
} | ConvertTo-Json | Set-Content -Path $settingsPath
}
$Global:apiUrl = $apiUrl
$Global:apiKey = $apiKey
}
ReadApiSettings
$Global:systemPrompt = 'You are an AI assistant that helps people find information.'
function SetSystemPrompt($prompt) { $Global:systemPrompt = $prompt }
function DecryptApiKey() {
$secStr = $Global:apiKey | ConvertTo-SecureString
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secStr)
return [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
}
function CallComplete($prompt) {
$fullPrompt = $Global:systemPrompt + ' ' + $prompt
$payLoad = [PSCustomObject]@{
messages = @(
[PSCustomObject]@{
role = "system"
content = @(
[PSCustomObject]@{
type = "text"
text = $fullPrompt
temperature=0.7
top_p = 0.95
max_tokens = 2048
}
)
}
)
}
$json = $payLoad | ConvertTo-Json -Depth 5
# PowerShell 6+,可直接用 Invoke-RestMethod
# $response = Invoke-RestMethod -Uri $Global:apiUrl -Method POST -Headers $headers -Body $json
# PowerShell 5.1,需用 WebClient 自行處理編碼問題
$wc = New-Object System.Net.WebClient
$wc.Headers.Add('Content-Type', 'application/json; charset=utf-8')
$wc.Headers.Add('api-key', (DecryptApiKey))
$response = $wc.UploadData($Global:apiUrl, [System.Text.Encoding]::UTF8.GetBytes($json))
$response = [System.Text.Encoding]::UTF8.GetString($response) | ConvertFrom-Json
return $response.choices[0].message.content
}
if ($question -ne '') {
CallComplete($question)
}
就醬,未來在 PowerShell 要整合 ChatGPT API 就方便多了。
Example of how to call Azure OpenAI api in PowerShell to provide chatting or translation function.
Comments
# by Hank
可以請 ChatGPT 寫出符合本文需求的 PowerShell 麼
# by Jeffrey
to Hank, 請它給 Python 範例的成功率比較高,PowerShell 的訓練資料偏少,能幫上大忙,但精準度仍不夠理想。 依我的看法,靠 AI 寫程式至少要有能力看懂程式碼,矇著眼 AI 給什麼跑什麼,出錯只能問 AI 怎麼改,很難過著幸福快樂的日子。(至少以現在 LLM 的水準還沒辦法)
# by Lou
等待複核中,留言將在稍後顯示 / The comment is awaiting review.