POML 模板引擎(Template Engine)

POML 模板引擎(Template Engine)

参考官方文档:microsoft.github.io/poml/stable...

概览

POML 的模板引擎让你在提示中使用"变量、表达式、循环、条件、文件包含"等动态能力,从而构建可复用、可组合的复杂提示。


表达式(Expressions)

  • 基本用法:使用双花括号 {{ }} 在内容位置插入变量或表达式结果。
poml 复制代码
<poml>
  <p>Hello, {{ name }}!</p>
</poml>
  • 属性中的表达式:也可用于属性值。
poml 复制代码
<poml>
  <task caption="Task #{{ index }}">This is task No. {{ index }}.</task>
</poml>
  • 支持的表达式(JavaScript 语法):
    • 变量:{{variableName}}
    • 算术:{{a + b}}{{x * y}}{{count / total}}
    • 字符串拼接:{{firstName + " " + lastName}}
    • 数组访问:{{myArray[0]}}
    • 对象属性:{{myObject.property}}
    • 函数调用:{{myFunction(arg1, arg2)}}(若函数在上下文中可用)
    • 三元运算:{{condition ? A : B}}
    • 循环变量:{{loop.index}} 等(见下文)

提示:属性中的表达式会先求值再进行类型自动转换(见"类型自动转换")。


let 变量与数据导入(Let Expressions)

<let> 用于定义变量、导入外部数据,并在模板内复用。

1) 从字面量设置变量

  • 内容作为字面量:
poml 复制代码
<poml>
  <let name="greeting">Hello, world!</let>
  <p>{{ greeting }}</p>
</poml>
  • 使用 value 属性(会按 JS 表达式求值,注意字符串需要引号):
poml 复制代码
<poml>
  <let name="greeting" value="'Hello, world!'" />
  <p>{{ greeting }}</p>
</poml>

2) 从文件导入数据(命名变量)

  • users.json 的内容导入到 users 变量:
poml 复制代码
<poml>
  <let name="users" src="users.json" />
  <p>First user: {{ users[0].name }}</p>
</poml>

type 可指定文件类型(如 jsontextcsv),不提供时按扩展名推断。

3) 从文件导入(不命名)

  • 直接把 JSON 顶层的键注入到当前上下文:
poml 复制代码
<poml>
  <let src="config.json" />
  <p>API Key: {{ apiKey }}</p>
</poml>

config.json 示例:

json 复制代码
{ "apiKey": "your_api_key" }

4) 使用内联 JSON 与类型标注

poml 复制代码
<poml>
  <let name="person">{ "name": "Alice", "age": 30 }</let>
  <p>Name: {{ person.name }}, Age: {{ person.age }}</p>

  <let name="count" type="integer">5</let>
  <p>Count: {{ count }}</p>
</poml>

5) 基于表达式设置变量

poml 复制代码
<poml>
  <let name="base" value="10" />
  <let name="increment" value="5" />
  <let name="total" value="{{ base + increment }}" />
  <p>Total: {{ total }}</p> <!-- 输出:15 -->
</poml>

类型自动转换(Type-Autocasting in Attributes)

  • 组件属性会根据其定义的类型自动转换:
    • Boolean:"true"1"1"{{true}}true"false"0"0"{{false}}false
    • Number:"123"45.6{{anyNumber}}{{myNumber+1.3}} → 相应数值
    • Object:尝试解析为 JSON 对象,例如:
      • data='{"name":"John","age":30}'
      • data="{{{name: 'John', age: 30}}}"(三花括号语法,直接提供对象字面量)
    • String:不做转换

示例(概念演示):

poml 复制代码
<poml>
  <let name="boolVar" type="boolean" value="true"/>
  <let name="numVar"  type="number"  value="42"/>
  <let name="objVar"  type="object"  value="{{ { key: 'value' } }}"/>
  <MyComponent
    boolProp="{{ boolVar }}"
    numProp="{{ numVar }}"
    objProp="{{ objVar }}"
    stringProp="hello"
  />
</poml>

for 循环(For Attribute)

  • 语法:for="itemName in listExpr"
poml 复制代码
<poml>
  <list>
    <item for="item in ['apple', 'banana', 'cherry']">{{ item }}</item>
  </list>
</poml>

循环变量(Loop Variables)

  • loop.index:当前索引(从 0 开始)
  • loop.length:总长度
  • loop.first:是否第一项(true/false)
  • loop.last:是否最后一项(true/false)
poml 复制代码
<poml>
  <let name="all_demos" value='[
    { "input": "What is your name?", "output": "My name is POML." },
    { "input": "What can you do?",  "output": "I can generate prompts." }
  ]'/>
  <examples>
    <example for="example in all_demos" chat="false"
             caption="Example {{ loop.index + 1 }}" captionStyle="header">
      <input>{{ example.input }}</input>
      <output>{{ example.output }}</output>
    </example>
  </examples>
</poml>

条件渲染(If Condition)

  • 使用 if 属性按条件渲染元素:
poml 复制代码
<poml>
  <let name="isVisible" value="true"/>
  <let name="isHidden"  value="{{ !isVisible }}"/>
  <p if="isVisible">This paragraph is visible.</p>
  <p if="isHidden">This paragraph is hidden.</p>
</poml>

if 的值可直接写变量名(按布尔解释)或任意表达式。


文件包含(Include Files)

  • 使用 <include src="..." /> 将其他 POML 片段注入当前文件;被包含文件可访问当前上下文的变量。
  • forif 可与 include 同用:
poml 复制代码
<poml>
  <include src="row.poml" for="i in [1,2,3]" />
  <include src="footer.poml" if="showFooter" />
</poml>

路径 src 相对于当前 POML 文件;避免循环包含。


实战组合示例

  • 目标:从 JSON 读取人员列表,循环渲染为多行,页脚按条件包含。

目录结构:

  • people.json
  • row.poml
  • main.poml

people.json

json 复制代码
[
  { "name": "Alice", "role": "PM" },
  { "name": "Bob",   "role": "Engineer" }
]

row.poml

poml 复制代码
<p><b>{{ person.name }}</b> - {{ person.role }}</p>

main.poml

poml 复制代码
<poml>
  <let name="people" src="people.json" />
  <let name="showFooter" value="true" />

  <section>
    <include src="row.poml" for="person in people" />
  </section>

  <footer if="showFooter">
    <p>Total: {{ people.length }}</p>
  </footer>
</poml>

实践建议与常见坑

  • 字符串字面量在 value 中必须加引号;内容写法则按字面量处理。
  • 对象型属性可用 JSON 字符串或三花括号对象字面量:
    • data='{"name":"John","age":30}'
    • data="{{{name: 'John', age: 30}}}"
  • 文件路径相对当前 .poml;注意编码与格式(如 JSON 的逗号与引号)。
  • 循环与条件可叠加在 include 上,便于模块化拆分。
  • 谨慎使用自定义函数调用;优先使用纯表达式与 let,保证可移植性与可调试性。

相关推荐
chaofa用代码打点酱油10 小时前
RAG 进化之路:传统 RAG 到工具与强化学习双轮驱动的 Agentic RAG
算法·llm
山顶夕景11 小时前
【MLLM】Qwen3-Omni全模态模型源码解读
大模型·llm·多模态·mllm
阿福Chris14 小时前
Dify本地初始化后安装模型供应商瞬间失败控制台报错401
大模型·llm·dify·大模型工具
镰刀韭菜1 天前
【AI4S】DrugChat:迈向在药物分子图上实现类似ChatGPT的功能
llm·图神经网络·预训练·gnn·ai4s·drugchat·药物分子图谱
山顶夕景2 天前
【LLM-RL】GSPO算法Group Sequence Policy Optimization
llm·强化学习·rlhf·gspo
余衫马2 天前
llama.cpp:本地大模型推理的高性能 C++ 框架
c++·人工智能·llm·llama·大模型部署
yaocheng的ai分身2 天前
A16Z 大佬 Alex Rampell《Software Is Eating Labor》演讲
llm
utmhikari2 天前
【测试人生】LLM赋能游戏自动化测试的一些想法
自动化测试·游戏·ai·大模型·llm·游戏测试
智泊AI2 天前
突然发现:大模型RAG优化思路真的好清晰!
llm
玩转AGI3 天前
【必收藏】12-Factor Agents:让大模型Agent从能跑起来到能用起来的企业级设计指南
人工智能·程序员·llm