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
要用 Rust 來構建一個基於大型語言模型(LLM, Large Language Model)的應用,這涉及到幾個步驟。一般來說,LLM 是基於預訓練的深度學習模型(如 GPT、BERT 等),而 Rust 主要用於系統級別的開發,因此直接用 Rust 訓練或運行這類模型並不常見。相反,常見的做法是使用 Rust 與其他訓練好模型的框架(如 Python 的 TensorFlow 或 PyTorch)進行整合。 主要步驟: 1. 使用已有的預訓練模型: 利用 Rust 調用預訓練的 LLM 模型,你可以使用外部庫如 ONNX, ggml, 或通過 API 調用服務(例如 OpenAI GPT-3 API 或 Hugging Face Hub)來實現。 2. Rust 機器學習庫: 使用 Rust 的機器學習庫來進行模型推理(而非訓練)。例如: tch-rs:Rust 中的 PyTorch 綁定庫,可以使用已經用 PyTorch 訓練的模型。 onnxruntime-rs:使用 ONNX 格式的模型,這是一個運行預訓練模型的高效方式。 3. 與 Python、C++ 等框架互操作: Rust 可以通過 FFI 調用其他語言實現的機器學習模型,這樣你可以利用 Rust 的性能和內存管理來構建高效的推理系統。 4. 調用雲端 API: 你可以利用 OpenAI 的 API 或 Hugging Face 的模型 API 來進行 LLM 應用。Rust 有非常高效的 HTTP 庫如 reqwest,可以調用這些服務來進行模型推理。 簡單步驟範例:使用 reqwest 調用 OpenAI 的 GPT-3 API 這裡我們將展示如何使用 Rust 調用 OpenAI GPT-3 API 進行文本生成。 步驟: 1. 建立一個新 Rust 專案: cargo new gpt3_client cd gpt3_client 2. 編輯 Cargo.toml,新增以下依賴: [dependencies] reqwest = { version = "0.11", features = ["json"] } tokio = { version = "1", features = ["full"] } serde = { version = "1.0", features = ["derive"] } 3. 在 src/main.rs 編寫如下代碼: use reqwest::Client; use serde::{Deserialize, Serialize}; use std::env; #[derive(Serialize)] struct OpenAIRequest { model: String, prompt: String, max_tokens: u32, } #[derive(Deserialize)] struct OpenAIResponse { choices: Vec<Choice>, } #[derive(Deserialize)] struct Choice { text: String, } #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { // 從環境變量中獲取 API 密鑰 let api_key = env::var("OPENAI_API_KEY").expect("OpenAI API key not set"); // 設置 OpenAI 請求 let request_body = OpenAIRequest { model: "text-davinci-003".to_string(), prompt: "Write a Rust code example".to_string(), max_tokens: 100, }; // 發送請求 let client = Client::new(); let res = client .post("https://api.openai.com/v1/completions") .header("Authorization", format!("Bearer {}", api_key)) .json(&request_body) .send() .await?; // 解析回應 let openai_response: OpenAIResponse = res.json().await?; // 打印回應的第一個選擇結果 if let Some(choice) = openai_response.choices.first() { println!("Response: {}", choice.text); } Ok(()) } 詳細說明: 1. 請求 API: 使用 reqwest 發送 HTTP POST 請求到 OpenAI API,並包含 model、prompt 和 max_tokens 等參數。 2. 回應解析: 使用 serde 來序列化和反序列化 JSON 格式的請求和回應。 3. 異步請求: Rust 的 tokio 用於實現異步 HTTP 請求,提高性能。 其他選擇: tch-rs:使用 PyTorch 綁定來加載和推理 LLM。 ggml-rs:Rust 庫,用於加載量化和高效的 LLM 模型,如 LLaMA。