本文 AI 產出,尚未審核
LangChain 課程 – Prompts:提示工程
主題:PromptTemplate 使用方法
簡介
在使用大型語言模型(LLM)時,Prompt(提示) 的寫法直接決定了模型輸出的品質與一致性。隨著應用日益複雜,單純的字串拼接已難以維護,這時 PromptTemplate 便成為 LangChain 中最常用且最強大的工具。
本篇文章將說明什麼是 PromptTemplate、如何在程式碼中建立與管理模板,並提供多個實務範例,讓你能快速上手、避免常見陷阱,進而在聊天機器人、文件摘要、資料擷取等場景中發揮最大效能。
核心概念
1. PromptTemplate 是什麼?
- PromptTemplate 是一個 可參數化的文字模板,允許你在執行時動態填入變數。
- 它把 固定的指令文字(系統訊息、格式要求)與 變動的內容(使用者輸入、文件片段)分離,提升 可讀性、可維護性 與 重用性。
- LangChain 提供了多種模板類型:
PromptTemplate(最基本)、ChatPromptTemplate(適用於多輪對話)以及FewShotPromptTemplate(支援示例提示)。
2. 基本語法
import { PromptTemplate } from "langchain/prompts";
const template = `你是一位專業的旅遊導遊,請根據以下資訊為使用者規劃三天兩夜的行程。
地點: {location}
旅遊偏好: {preference}
預算: {budget}元`;
const prompt = new PromptTemplate({
inputVariables: ["location", "preference", "budget"],
template,
});
inputVariables:列出模板中所有 占位變數,LangChain 會在呼叫format時檢查是否提供完整。template:實際的文字模板,使用{variable}方式標示變數位置。
3. 使用 format 產生最終 Prompt
const filledPrompt = await prompt.format({
location: "台北",
preference: "美食與文化",
budget: 8000,
});
console.log(filledPrompt);
輸出:
你是一位專業的旅遊導遊,請根據以下資訊為使用者規劃三天兩夜的行程。
地點: 台北
旅遊偏好: 美食與文化
預算: 8000元
4. 進階功能
| 功能 | 說明 | 範例 |
|---|---|---|
| Partial Variables | 事先固定某些變數,只在執行時提供其餘部分。 | new PromptTemplate({ template, inputVariables, partialVariables: {budget: 5000} }) |
| Template Format | 支援 f-string、jinja2 等不同語法。 |
templateFormat: "jinja2" |
| Output Parser | 結合 BaseOutputParser,直接解析模型回傳的結構化資料。 |
outputParser: new JsonOutputParser() |
程式碼範例
以下提供 五個 常見且實用的範例,涵蓋不同情境與技巧。每段程式碼均附有說明註解,方便初學者快速理解。
範例 1:基本的問答 Prompt
import { PromptTemplate } from "langchain/prompts";
const qaTemplate = new PromptTemplate({
inputVariables: ["question"],
template: `以下是一段簡短的說明,請根據說明回答使用者的問題。
說明: {context}
問題: {question}
請直接給出答案,避免冗長解釋。`,
});
async function ask(question, context) {
const prompt = await qaTemplate.format({ question, context });
// 假設已有 LLM 實例 llm
const answer = await llm.invoke(prompt);
return answer;
}
重點:把「說明」與「問題」分開,讓 LLM 能聚焦在核心資訊上。
範例 2:使用 Partial Variables 固定系統角色
import { PromptTemplate } from "langchain/prompts";
const systemPrompt = new PromptTemplate({
inputVariables: ["user_input"],
partialVariables: { role: "你是一位友善的程式設計教練" },
template: `{role}
使用者: {user_input}
教練:`,
});
const prompt = await systemPrompt.format({ user_input: "什麼是 closure?" });
console.log(prompt);
輸出:
你是一位友善的程式設計教練
使用者: 什麼是 closure?
教練:
技巧:當角色資訊不會變動時,用
partialVariables省去每次填入的麻煩。
範例 3:結合 Jinja2 語法的複雜模板
import { PromptTemplate } from "langchain/prompts";
const jinjaTemplate = new PromptTemplate({
inputVariables: ["items"],
template: `
{% for item in items %}
- {{item.name}} (價格: {{item.price}}元)
{% endfor %}
請根據上述商品清單,推薦三件最適合預算 1500 元的商品。`,
templateFormat: "jinja2",
});
const prompt = await jinjaTemplate.format({
items: [
{ name: "筆記型電腦", price: 30000 },
{ name: "藍牙耳機", price: 1200 },
{ name: "行動電源", price: 800 },
{ name: "鍵盤", price: 1500 },
],
});
console.log(prompt);
說明:利用
for迴圈動態產生清單,適合處理 多筆資料。
範例 4:Few‑Shot Prompt(示例提示)
import { FewShotPromptTemplate, PromptTemplate } from "langchain/prompts";
const examplePrompt = new PromptTemplate({
inputVariables: ["question", "answer"],
template: `Q: {question}
A: {answer}`,
});
const fewShot = new FewShotPromptTemplate({
examplePrompt,
examples: [
{ question: "台北 101 的高度?", answer: "508 公尺" },
{ question: "Python 的創始人是誰?", answer: "Guido van Rossum" },
],
prefix: "以下是一些問答示例,請根據示例回答新問題。",
suffix: "Q: {input}\nA:",
inputVariables: ["input"],
});
const prompt = await fewShot.format({ input: "JavaScript 的發明者是誰?" });
console.log(prompt);
產生的 Prompt:
以下是一些問答示例,請根據示例回答新問題。
Q: 台北 101 的高度?
A: 508 公尺
Q: Python 的創始人是誰?
A: Guido van Rossum
Q: JavaScript 的發明者是誰?
A:
效益:提供 示例 能顯著提升模型的正確率,特別是對於 特定格式 或 領域知識。
範例 5:結合 Output Parser 直接得到 JSON
import { PromptTemplate } from "langchain/prompts";
import { JsonOutputParser } from "langchain/output_parsers";
const jsonParser = new JsonOutputParser();
const weatherTemplate = new PromptTemplate({
inputVariables: ["city"],
template: `請提供 {city} 未來 3 天的天氣預報,回傳格式必須是 JSON,欄位包括 date、high、low、description。`,
outputParser: jsonParser,
});
async function getWeather(city) {
const prompt = await weatherTemplate.format({ city });
const rawResponse = await llm.invoke(prompt); // LLM 回傳文字
const parsed = await jsonParser.parse(rawResponse);
return parsed; // 直接得到 JavaScript 物件
}
亮點:OutputParser 讓你在取得 LLM 輸出後,立即得到結構化資料,省去自行正則表達式或
JSON.parse的麻煩。
常見陷阱與最佳實踐
| 陷阱 | 說明 | 解決方案 |
|---|---|---|
| 忘記列出所有變數 | inputVariables 與模板不一致時會拋出錯誤。 |
使用 IDE 或 TypeScript 型別檢查,確保變數名一致。 |
| 模板過長導致 token 超限 | 大型上下文一次性塞入會觸發 token 超過模型上限。 | 分段 送入模型或使用 Retriever 先篩選相關段落。 |
| 變數值未經清理 | 使用者輸入可能包含特殊字符或換行,導致 Prompt 結構被破壞。 | 在 format 前 sanitize(例如移除多餘的換行、轉義引號)。 |
| 示例過多 | Few‑Shot Prompt 中示例太多會佔用大量 token,反而降低效能。 | 僅保留 關鍵 2–3 個 最具代表性的示例。 |
| 忽略 Output Parser | 直接使用文字回應,需要自行解析,容易出錯。 | 配合 Parser,讓 LangChain 自動把文字轉成結構化資料。 |
最佳實踐
- 模組化:將常用模板抽成獨立檔案,使用
export const共享。 - 使用 Partial Variables 來固定不變的系統訊息或角色設定。
- 加入註解:在模板內使用
#或/* */標註說明,方便日後維護。 - 測試 Prompt:在正式部署前,用單元測試驗證
format後的字串是否符合預期。 - 結合 Retriever:若需要大量文件作為上下文,先用向量搜尋找出最相關的段落,再填入 Prompt。
實際應用場景
| 場景 | PromptTemplate 如何發揮作用 |
|---|---|
| 客服聊天機器人 | 使用 ChatPromptTemplate 搭配 partialVariables 設定「客服角色」與「公司政策」;動態填入使用者問題。 |
| 文件摘要 | 先透過向量檢索取得關鍵段落,然後用 PromptTemplate 把段落與「請摘要」指令組合。 |
| 程式碼生成 | 利用 FewShotPromptTemplate 提供幾個範例函式,讓模型學習風格,再根據使用者需求產生新程式碼。 |
| 市場分析報告 | 結合 JsonOutputParser,讓模型直接回傳結構化的 KPI 數據,省去後續資料清洗。 |
| 多語言翻譯 | 把「目標語言」作為變數,模板固定「請將以下文字翻譯成 {target_lang}」;適用於批次翻譯。 |
總結
PromptTemplate 是 LangChain 中最基礎且最強大的組件之一,它讓我們能以 結構化、可維護 的方式編寫提示,從而提升大型語言模型的效能與可靠性。透過本文的五個實作範例,你已掌握:
- 如何建立基本與進階的 PromptTemplate
- 使用 Partial Variables、Jinja2、Few‑Shot 與 Output Parser 等進階功能
- 常見的錯誤與最佳實踐
只要把 模板化思維 融入日常開發流程,無論是聊天機器人、文件摘要或是自動化報告,都能快速產出高品質的 LLM 輸出。現在就把這些技巧套用到你的專案中,體驗 PromptTemplate 帶來的效能提升吧!祝開發順利 🚀