Dify「模板轉(zhuǎn)換」節(jié)點(diǎn)終極指南:動態(tài)文本生成進(jìn)階技巧(附代碼)Jinja2引擎解析
這篇文章是關(guān)于Dify「模板轉(zhuǎn)換」節(jié)點(diǎn)的終極指南,解析了基于Jinja2模板引擎的動態(tài)文本生成技巧,涵蓋多源文本整合、知識檢索結(jié)構(gòu)化、動態(tài)API構(gòu)建及個性化內(nèi)容生成等六大應(yīng)用場景,助力開發(fā)者高效利用模板轉(zhuǎn)換節(jié)點(diǎn)。
很多小伙伴希望想看Dify工作流的方式,畢竟這樣才能在業(yè)務(wù)落地
但要想實(shí)現(xiàn)這個,前提是要掌握 Dify 的一個神器——模板轉(zhuǎn)換。
以下內(nèi)容是純知識干貨,適合轉(zhuǎn)發(fā)收藏起來逐個跟著實(shí)踐??赐昴軕?yīng)對 80% 的「動態(tài)文本生成」高頻場景。
Dify的模板轉(zhuǎn)換節(jié)點(diǎn),基于強(qiáng)大的Jinja2模板引擎,為AI應(yīng)用開發(fā)者提供了在工作流中進(jìn)行靈活數(shù)據(jù)轉(zhuǎn)換與動態(tài)文本生成的核心能力。
它允許開發(fā)者通過簡潔的模板語法,輕松實(shí)現(xiàn)文本拼接、格式轉(zhuǎn)換、數(shù)據(jù)結(jié)構(gòu)重組等多種操作,從而優(yōu)化數(shù)據(jù)流轉(zhuǎn)效率,增強(qiáng)應(yīng)用輸出的個性化與智能化。
本文將深入解析模板轉(zhuǎn)換節(jié)點(diǎn)的核心引擎Jinja2,并結(jié)合Dify平臺特性,展示其在多源文本合成、知識檢索結(jié)構(gòu)化、動態(tài)API構(gòu)建及個性化內(nèi)容生成等關(guān)鍵場景的應(yīng)用技巧,助您駕馭這一強(qiáng)大工具。
核心引擎:Jinja2的機(jī)制與特性
Jinja2是一款成熟、功能豐富且高效的Python模板引擎,其核心目標(biāo)在于將應(yīng)用程序的業(yè)務(wù)邏輯與展示邏輯(如HTML、XML、配置文件或任意文本格式)清晰分離。
它通過優(yōu)雅的語法、模板繼承、宏、過濾器及可擴(kuò)展性,實(shí)現(xiàn)了動態(tài)內(nèi)容嵌入靜態(tài)模板的需求。
Jinja2的語法直觀,主要包括:
- {{ … }}用于輸出變量或表達(dá)式結(jié)果(默認(rèn)自動HTML轉(zhuǎn)義以防XSS攻擊)
- {% … %}用于控制語句(如循環(huán)、條件判斷、宏定義)
- 以及{# … #}用于注釋。
其強(qiáng)大的特性如模板繼承允許定義基礎(chǔ)布局,子模板可覆寫特定區(qū)塊;宏則類似函數(shù),封裝可重用邏輯;豐富的內(nèi)置過濾器(如trim, join, length, default, tojson)及自定義過濾器能力,極大地增強(qiáng)了數(shù)據(jù)處理的靈活性。
Jinja2支持完整的控制結(jié)構(gòu),如{% if %}條件判斷和{% for %}循環(huán)(包含loop變量以訪問循環(huán)狀態(tài)),以及變量賦值{% set %}。這些特性使得模板不僅能展示數(shù)據(jù),還能執(zhí)行輕量級邏輯判斷與數(shù)據(jù)迭代處理。
在Dify中,模板轉(zhuǎn)換節(jié)點(diǎn)正是利用Jinja2的這些能力,使得開發(fā)者無需編寫復(fù)雜的代碼節(jié)點(diǎn),即可在工作流中高效處理和編排文本數(shù)據(jù)。
以上只是 Jinja2 的冰山一角,更多需要到中文文檔學(xué)習(xí):https://docs.jinkan.org/docs/jinja2/
為了幫助大家「干中學(xué)」我整理了模板轉(zhuǎn)換的 6 大高頻應(yīng)用場景,理解它們,也就掌握得七七八八了。
模板轉(zhuǎn)換節(jié)點(diǎn)的關(guān)鍵應(yīng)用場景與技巧
Dify的模板轉(zhuǎn)換節(jié)點(diǎn)憑借Jinja2引擎,在構(gòu)建AI應(yīng)用工作流時展現(xiàn)出極高的靈活性和實(shí)用性。以下將結(jié)合具體場景和代碼示例,探討其核心應(yīng)用方式,重點(diǎn)突出數(shù)據(jù)整合、結(jié)構(gòu)化輸出及動態(tài)生成能力。
1. 多源文本與數(shù)據(jù)拼接整合
在AI應(yīng)用中,常需要將來自不同節(jié)點(diǎn)或變量的文本片段、數(shù)據(jù)項組合成單一的、結(jié)構(gòu)化的文本輸出,作為后續(xù)LLM的提示詞、用戶回復(fù)或日志記錄。模板轉(zhuǎn)換節(jié)點(diǎn)為此提供了便捷的解決方案。例如,將分散的文章標(biāo)題、開頭和正文內(nèi)容合并成一篇完整文檔。
對于更復(fù)雜的場景,如處理迭代節(jié)點(diǎn)輸出的多個內(nèi)容項,可通過循環(huán)實(shí)現(xiàn)。假設(shè)迭代節(jié)點(diǎn)輸出一個名為arg的數(shù)組,每個元素section需要被拼接并用分隔符隔開:
{% for section in arg %}
{{ section }}
———————————-
{% endfor %}
這種方式常用于匯總迭代處理的結(jié)果,形成一份完整的報告或長文本。
例如我做公眾號的工作流,里面有個「迭代」負(fù)責(zé)把每篇內(nèi)容分別發(fā)布到公眾號里
迭代的下一個節(jié)點(diǎn)就做了一個「模板轉(zhuǎn)換」逐個每個成功發(fā)送的記錄都顯示出來
2. 知識檢索結(jié)果的結(jié)構(gòu)化與美化
從知識庫檢索到的信息往往包含多個內(nèi)容片段及其元數(shù)據(jù)(如相似度得分、來源等)。模板轉(zhuǎn)換節(jié)點(diǎn)能將這些原始數(shù)據(jù)優(yōu)雅地格式化為易讀的報告,例如Markdown格式,便于呈現(xiàn)或進(jìn)一步處理。
實(shí)例:
定義從知識庫中檢索的數(shù)組結(jié)果,為變量retrieved_chunks
核心還是要設(shè)計好展示的模板:
## 知識檢索報告
{% if retrieved_chunks and retrieved_chunks | length > 0 %}
{% for chunk in retrieved_chunks %}
###
{{ loop.index }}. {{ chunk.title }}
(相似度:
{{ “%.2f” | format(chunk.score | default(0)) }}
)
{{ chunk.content | replace(‘n’, ‘nn’) }}
—
{% endfor %}{% else %}
未檢索到相關(guān)信息。
{% endif %}
該模板遍歷retrieved_chunks列表,為每個知識片段創(chuàng)建包含序號、標(biāo)題、相似度(使用format過濾器格式化并提供default值)的子標(biāo)題,并處理內(nèi)容中的換行符,使其在Markdown中正確分段。
能看到它把知識庫檢索的結(jié)果結(jié)構(gòu)化整理出來了:
這段代碼是Jinja2能力的一個綜合展示,非常典型。
我們來逐行分解:
1){% if retrieved_chunks and retrieved_chunks | length > 0 %}: 這是一個條件判斷語句。
語法: {% if … %} … {% else %} … {% endif %} 是Jinja2的條件控制結(jié)構(gòu)。
解釋: 這里做了雙重檢查:retrieved_chunks 確保變量存在且不為null;retrieved_chunks | length > 0 確保這個變量(通常是列表或數(shù)組)不為空。| length 是一個過濾器 (Filter),作用是獲取變量的長度,類似于Python的len()。這個判斷保證了只有在確實(shí)檢索到內(nèi)容時,才執(zhí)行后續(xù)的循環(huán)渲染。
2){% for chunk in retrieved_chunks %}: 這是一個循環(huán)語句。
語法: {% for item in sequence %} … {% endfor %} 用于遍歷一個序列(如列表、數(shù)組)。
解釋: 它會遍歷retrieved_chunks數(shù)組中的每一個元素,并將當(dāng)前元素賦值給臨時變量chunk。chunk在Dify中通常是一個包含content, title, score等字段的對象。
3){{ loop.index }}: 這是Jinja2在循環(huán)中的一個特殊變量。
語法: loop變量在for循環(huán)內(nèi)部自動可用。
解釋: loop.index 返回當(dāng)前循環(huán)的迭代次數(shù)(從1開始)。其他常用的還有l(wèi)oop.index0(從0開始)、loop.first(是否為第一次迭代)、loop.last(是否為最后一次迭代),在處理列表時非常有用,比如在最后一項后不加分隔符。
4){{ “%.2f” | format(chunk.score | default(0)) }}: 這是一個嵌套使用過濾器的復(fù)雜表達(dá)式。
語法: | 符號用于將左側(cè)的值傳遞給右側(cè)的過濾器??梢赃B續(xù)使用,形成“管道(pipeline)”。
| default(0): 默認(rèn)值過濾器。如果chunk.score變量不存在或者為null,就使用括號里的0作為默認(rèn)值。這是保證代碼健壯性的關(guān)鍵,避免因缺少可選字段而報錯。
| format(…): 格式化過濾器。它將左側(cè)的字符串(”%.2f”)作為格式化模板,來處理括號內(nèi)的值。這里”%.2f”的意思是“格式化為一個保留兩位小數(shù)的浮點(diǎn)數(shù)”。
5){{ chunk.content | replace(‘n’, ‘nn’) }}: 字符串替換。
| replace(from, to): 替換過濾器。將輸入字符串中所有的from子串替換為to子串。在這里,它將內(nèi)容中的單個換行符n替換為兩個,這在Markdown語法里表示一個真正的換行(分段)。
3. 動態(tài)構(gòu)建API請求體與數(shù)據(jù)結(jié)構(gòu)
在與外部服務(wù)集成時,經(jīng)常需要根據(jù)動態(tài)輸入?yún)?shù)構(gòu)造特定格式(如JSON)的API請求體。模板轉(zhuǎn)換節(jié)點(diǎn)利用Jinja2的條件判斷和變量替換能力,可以靈活生成這類數(shù)據(jù)結(jié)構(gòu)。
{
“query”: “{{ user_query }}”,
“filters”: {
“status”: “{{ filter_type | default(‘any’) }}”,
{% if user_id %}
“customer_id”: “{{ user_id }}”,
{% endif %}
“created_after”: “{{ start_date_iso }}”
},
“pagination”: {
“limit”: {{ page_size | default(10) }},
“offset”: 0
}
}
此代碼的核心技巧在于在靜態(tài)的JSON結(jié)構(gòu)中嵌入動態(tài)邏輯,以生成符合API要求的請求體。
1){{ … | default(…) }}: 在這個例子中,default過濾器被多次使用,用于處理可選參數(shù)。
“status”: “{{ filter_type | default(‘any’) }}”: 如果上游節(jié)點(diǎn)傳入了filter_type變量,就使用它的值;如果沒有,就使用默認(rèn)值’any’。
“limit”: {{ page_size | default(10) }}: 同理,如果page_size未提供,則默認(rèn)為10。注意這里輸出的是數(shù)字,所以default的值也是數(shù)字10,而不是字符串’10’。Jinja2會正確處理數(shù)據(jù)類型。
2){% if user_id %}: 這是此模板最精妙的部分——動態(tài)增刪JSON字段。
語法: {% if variable %} … {% endif %}
解釋: 這個if語句塊包裹了”customer_id”: “{{ user_id }}”,這一整行。只有當(dāng)user_id變量存在且不為空時,這部分文本(包括鍵、值和末尾的逗號)才會被渲染到最終的輸出中。如果user_id不存在,這三行就會被完全忽略,從而實(shí)現(xiàn)了動態(tài)添加/移除customer_id字段的功能。
延伸技巧與注意點(diǎn): 這種方式對于處理JSON中的可選字段非常高效。但需要注意逗號的位置。在這個例子中,因?yàn)閕f塊后面還有一個固定的created_after字段,所以逗號可以安全地放在if塊內(nèi)部。如果if塊是對象中的最后一個可能的字段,直接加逗號可能會導(dǎo)致JSON格式錯誤。在這種情況下,通常需要更復(fù)雜的邏輯(如使用loop.last)來處理。
4. 實(shí)現(xiàn)個性化用戶體驗(yàn)與動態(tài)內(nèi)容定制
模板轉(zhuǎn)換節(jié)點(diǎn)能夠根據(jù)用戶屬性或上下文信息,生成個性化的文本內(nèi)容,從而提升AI應(yīng)用的交互體驗(yàn)。例如,根據(jù)用戶名稱和當(dāng)前時間生成動態(tài)問候語。
你好,{{ user.name }}!
{% if current_time.hour < 6 %}夜深了,早點(diǎn)休息。
{% elif current_time.hour < 12 %}早上好!
{% elif current_time.hour < 14 %}中午好!
{% elif current_time.hour < 18 %}下午好!
{% else %}晚上好!
{% endif %}
今天有什么可以幫您的嗎?
這里假設(shè)user.name和current_time.hour是上游傳入的變量,通過Jinja2的條件邏輯判斷當(dāng)前時間段,輸出相應(yīng)的問候。這種方式同樣適用于定制化產(chǎn)品推薦、動態(tài)郵件內(nèi)容生成等場景。
這個模板的核心是利用多級條件判斷來實(shí)現(xiàn)基于不同條件的文本分支。
1){{ user.name }}: 訪問對象屬性。
語法: object.property
解釋: 這表明user是一個對象(或字典),我們通過點(diǎn).來訪問其名為name的屬性。這是從變量中提取嵌套數(shù)據(jù)的標(biāo)準(zhǔn)方法。
2){% if … elif … else … %}: 完整的條件判斷鏈。
{% if current_time.hour < 6 %}: 首先檢查小時是否小于6。< 是標(biāo)準(zhǔn)的比較運(yùn)算符。
{% elif current_time.hour < 12 %}: 如果上一個if不成立,則檢查這個elif(”else if”的縮寫)條件。
后續(xù)的elif和else以此類推。Jinja2會按順序檢查,一旦某個條件為真,就執(zhí)行對應(yīng)的代碼塊,然后跳出整個if/elif/else結(jié)構(gòu)。
{% else %}: 如果以上所有if和elif條件都不滿足,則執(zhí)行else塊中的代碼。
語法: {% if condition1 %} … {% elif condition2 %} … {% else %} … {% endif %}
解釋:
5. HTML表單渲染與交互式內(nèi)容生成
Dify的模板轉(zhuǎn)換節(jié)點(diǎn)也支持渲染HTML內(nèi)容,可用于動態(tài)生成表單,為用戶提供更豐富的交互界面。
<form data-format=”json”>
// Default to text
<labelfor=”username”>Username:</label>
<inputtype=”text”name=”username”/>
<labelfor=”password”>Password:</label>
<inputtype=”password”name=”password”/>
<labelfor=”content”>Content:</label>
<textarea name=”content”></textarea>
<labelfor=”date”>Date:</label>
<inputtype=”date”name=”date”/>
<labelfor=”time”>Time:</label>
<inputtype=”time”name=”time”/>
<labelfor=”datetime”>Datetime:</label>
<inputtype=”datetime”name=”datetime”/>
<labelfor=”select”>Select:</label>
<inputtype=”select”name=”select”data-options='[“hello”,”world”]’/>
<inputtype=”checkbox”name=”check”data-tip=”By checking this means you agreed”/>
<button data-size=”small”data-variant=”primary”>Login</button></form>
效果是這樣:
而且每個組件還是選擇使用的,很方便:
。這段代碼本身并沒有使用Jinja2的動態(tài)語法(如{{}}或{% %}),它展示的是一個Dify平臺特定的功能:即模板轉(zhuǎn)換節(jié)點(diǎn)可以直接輸出特定格式的HTML,Dify的前端會將其解析并渲染成一個可交互的表單。
這里的關(guān)鍵點(diǎn)在于理解HTML標(biāo)簽上的data-*屬性,它們是給Dify平臺看的指令,而非標(biāo)準(zhǔn)的HTML行為。
<form data-format=”json”>:
解釋: 這個屬性告訴Dify,當(dāng)用戶提交這個表單時,應(yīng)該將表單數(shù)據(jù)聚合成一個JSON對象,而不是默認(rèn)的表單字符串。這是與后端或LLM節(jié)點(diǎn)進(jìn)行結(jié)構(gòu)化數(shù)據(jù)交互的基礎(chǔ)。
<input type=”select” data-options='[“hello”,”world”]’/>:
解釋: Dify識別到type=”select”,并會查找data-options屬性。它會將這個屬性的值(一個JSON數(shù)組格式的字符串)解析,并用它來填充下拉選擇框的選項。這是一種無需Jinja2循環(huán)就能動態(tài)定義選項的便捷方式。
<input type=”checkbox” data-tip=”By checking this means you agreed”/>:
解釋: data-tip屬性被Dify用來在界面上為該復(fù)選框生成一個提示性的氣泡(Tooltip),增強(qiáng)用戶體驗(yàn)。
<button data-size=”small” data-variant=”primary”>:
解釋: data-size和data-variant這類屬性用于控制Dify渲染出的按鈕的視覺樣式,如大小和顏色主題(例如primary通常是藍(lán)色主色調(diào))。
也就是說,模板轉(zhuǎn)換節(jié)點(diǎn)不僅能處理文本邏輯,還能作為動態(tài)UI生成器,在配合Jinja2語法來動態(tài)生成這些HTML。
6. 動態(tài)數(shù)據(jù)分析報告生成
# 銷售報告
{{ date.today() | date_format(“%Y-%m-%d”) }}
**總銷售額**:
¥{{ total_sales | round(2) | thousands_separator }}
## 區(qū)域表現(xiàn)
{% for region in regions %}- {{ region.name }}:
– 完成率: {{ (region.actual/region.target*100) | round(1) }}%
– 同比增長: {{ region.growth_rate | percent }}{% endfor %}
這個模板是前面所有知識點(diǎn)的一個高級融合,用于生成一份數(shù)據(jù)驅(qū)動的動態(tài)報告,包含了函數(shù)調(diào)用、算術(shù)運(yùn)算和多種專用過濾器。
1) {{ date.today() | date_format(“%Y-%m-%d”) }}: 調(diào)用方法并格式化。
date.today(): 這表示date是一個對象,并且它有一個可以被調(diào)用的方法today()。Jinja2允許在模板中執(zhí)行這種簡單的無參方法調(diào)用。
| date_format(…): 這是一個假設(shè)存在(或自定義)的日期格式化過濾器,非常實(shí)用。”%Y-%m-%d”是格式化指令,分別代表四位數(shù)年份、兩位數(shù)月份和兩位數(shù)日期,最終會輸出2023-10-27這樣的格式。
2) {{ total_sales | round(2) | thousands_separator }}: 過濾器鏈?zhǔn)秸{(diào)用。
| round(2): round過濾器,用于四舍五入。參數(shù)2表示保留兩位小數(shù)。
| thousands_separator: 這是一個非常有用的(通常是自定義或特定框架提供的)過濾器,用于給數(shù)字添加千位分隔符,如將12345.67轉(zhuǎn)換為12,345.67,極大提升了金額的可讀性。
3) {{ (region.actual/region.target*100) | round(1) }}%: 在模板中進(jìn)行數(shù)學(xué)計算。
(region.actual/region.target*100): 這是Jinja2一個極其強(qiáng)大的特性。你可以直接在{{ … }}內(nèi)用括號包裹表達(dá)式來進(jìn)行加減乘除等數(shù)學(xué)運(yùn)算。這里計算的是銷售完成率的百分比。
| round(1): 將計算結(jié)果四舍五入到一位小數(shù)。注意百分號%是寫在}}外面的,因?yàn)樗且粋€靜態(tài)的文本后綴。
4){{ region.growth_rate | percent }}: 專用數(shù)據(jù)格式化。
| percent: 類似于date_format,這是一個假設(shè)存在的專用過濾器,它能將一個小數(shù)(如0.15)直接轉(zhuǎn)換為帶百分號的字符串(15%),比手動乘以100再加百分號更優(yōu)雅。
通過熟練運(yùn)用Jinja2的各項特性,Dify的模板轉(zhuǎn)換節(jié)點(diǎn)遠(yuǎn)不止于簡單的文本替換。它能夠處理復(fù)雜邏輯、轉(zhuǎn)換數(shù)據(jù)格式、美化輸出,甚至創(chuàng)造互動內(nèi)容,是構(gòu)建強(qiáng)大、靈活A(yù)I應(yīng)用不可或缺的一環(huán)。
本文由人人都是產(chǎn)品經(jīng)理作者【餅干哥哥】,微信公眾號:【餅干哥哥AGI】,原創(chuàng)/授權(quán) 發(fā)布于人人都是產(chǎn)品經(jīng)理,未經(jīng)許可,禁止轉(zhuǎn)載。
題圖來自Unsplash,基于 CC0 協(xié)議。
- 目前還沒評論,等你發(fā)揮!