用文字編輯器手工打造 docx
「docx 說到底不就是 zip 嗎? 那把 XML 壓成 zip 再改個副檔名,不就變成 docx 了?」
抱著這個想法實際試了一下,結果理所當然地失敗了。docx 並不「只是」zip 而已,zip 裡的內容必須遵循一套固定的封裝結構,也就是 OOXML (Office Open XML)。既然都動手了,就順便實際驗證一下,到底要做到什麼程度才能做出貨真價實的 docx。
「docx 說到底不就是 zip 嗎? 那把 XML 壓成 zip 再改個副檔名,不就變成 docx 了?」
抱著這個想法實際試了一下,結果理所當然地失敗了。docx 並不「只是」zip 而已,zip 裡的內容必須遵循一套固定的封裝結構,也就是 OOXML (Office Open XML)。既然都動手了,就順便實際驗證一下,到底要做到什麼程度才能做出貨真價實的 docx。
介紹如何從 PowerShell 經由 Google Cloud 的 Vertex AI 呼叫 Gemini 模型。涵蓋 OpenAI 相容端點與原生 Gemini 端點兩種方式。
不需要 API 金鑰,可直接使用現有的 Google Cloud 認證資訊。
$accessToken = (gcloud auth print-access-token)
$apiKey = $env:VERTEX_API_KEY
https://{region}-aiplatform.googleapis.com/v1beta1/projects/{projectId}/locations/{region}/endpoints/openapi/chat/completions
請求與回應格式與 OpenAI API 相同。模型名稱需加上 google/ 前綴(例:google/gemini-2.5-flash-lite)。
https://{region}-aiplatform.googleapis.com/v1/projects/{projectId}/locations/{region}/publishers/google/models/{model}:generateContent
若需要串流請使用 :streamGenerateContent。
$projectId = "your-project-id"
$region = "us-central1"
$model = "google/gemini-2.5-flash-lite"
$accessToken = (gcloud auth print-access-token)
$body = @{
model = $model
messages = @(
@{
role = "user"
content = "東京的人口是多少?"
}
)
} | ConvertTo-Json -Depth 10
$uri = "https://$region-aiplatform.googleapis.com/v1beta1/projects/$projectId/locations/$region/endpoints/openapi/chat/completions"
$response = Invoke-RestMethod `
-Uri $uri `
-Method Post `
-ContentType "application/json" `
-Headers @{ Authorization = "Bearer $accessToken" } `
-Body $body
$response.choices[0].message.content
$projectId = "your-project-id"
$region = "us-central1"
$model = "gemini-2.5-flash-lite"
$apiKey = $env:VERTEX_API_KEY
$body = @{
contents = @(
@{
role = "user"
parts = @(
@{ text = "東京的人口是多少?" }
)
}
)
} | ConvertTo-Json -Depth 10
$uri = "https://$region-aiplatform.googleapis.com/v1/projects/$projectId/locations/$region/publishers/google/models/${model}:generateContent?key=$apiKey"
$response = Invoke-RestMethod `
-Uri $uri `
-Method Post `
-ContentType "application/json" `
-Body $body
$response.candidates[0].content.parts[0].text
$response.choices[0].message.content # 產生的文字
$response.usage.total_tokens # 總 Token 數
$response.model # 使用的模型
$response.candidates[0].content.parts[0].text # 產生的文字
$response.usageMetadata.totalTokenCount # 總 Token 數
$response.modelVersion # 使用的模型版本
串流(streamGenerateContent)會回傳多個 chunk 的陣列,需將文字串接取出。
$fullText = ($response | ForEach-Object {
$_.candidates[0].content.parts[0].text
}) -join ""
$body = @{
model = $model
messages = @(
@{
role = "system"
content = "您是用日語回答的 AI 助理,請簡潔回覆。"
}
@{
role = "user"
content = "光速是多少?"
}
)
} | ConvertTo-Json -Depth 10
$body = @{
system_instruction = @{
parts = @(
@{ text = "您是用日語回答的 AI 助理,請簡潔回覆。" }
)
}
contents = @(
@{
role = "user"
parts = @(@{ text = "光速是多少?" })
}
)
} | ConvertTo-Json -Depth 10
將歷史對話依序放入陣列即可實現多回合對話。
$body = @{
model = $model
messages = @(
@{ role = "user"; content = "你比較喜歡貓還是狗?" }
@{ role = "assistant"; content = "我喜歡貓。" }
@{ role = "user"; content = "為什麼?" }
)
} | ConvertTo-Json -Depth 10
助理的角色需指定為 "model"。
$body = @{
contents = @(
@{
role = "user"
parts = @(@{ text = "你比較喜歡貓還是狗?" })
}
@{
role = "model"
parts = @(@{ text = "我喜歡貓。" })
}
@{
role = "user"
parts = @(@{ text = "為什麼?" })
}
)
} | ConvertTo-Json -Depth 10
| 模型 | OpenAI 相容名稱 | 特性 |
|---|---|---|
gemini-2.5-flash-lite | google/gemini-2.5-flash-lite | 輕量、快速、低成本 |
gemini-2.5-flash | google/gemini-2.5-flash | 平衡型 |
gemini-2.5-pro | google/gemini-2.5-pro | 高精度,適合複雜任務 |
| 情況 | 推薦方式 |
|---|---|
| 已有 GCP 認證的環境(開發、CI 等) | OpenAI 相容 + gcloud auth |
| 只能使用 API 金鑰 | 原生 Gemini |
| 從 OpenAI 移轉中 | OpenAI 相容(最小化程式碼變更) |
| 需要串流 | 原生 Gemini |
$env:VERTEX_API_KEY)讀取。