POML 与 LangChain 集成
本文基于官方页面(microsoft.github.io/poml/stable... POML 在 LangChain 中的集成方式、安装步骤、基础用法、两种模板模式,以及与 f-string/Jinja 等模板方法的对比。
导语/背景介绍
- 官方说明:POML 通过
LangchainPomlTemplate
与 LangChain 无缝集成,为 LangChain 内置模板系统(Jinja2 与 f-strings)提供有力替代方案。
安装与使用方法(Installation / Basic Usage)
安装(Installation)
bash
pip install langchain langchain-openai
基础用法(Basic Usage)
python
from poml.integration.langchain import LangchainPomlTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
# 从文件加载 POML 模板
prompt_template = LangchainPomlTemplate.from_file("explain_code.poml")
# 或者从字符串创建模板
prompt_template = LangchainPomlTemplate.from_template(
"<poml><task>Explain this:</task>"
"<code inline=\"false\"><document src=\"{{ code_file }}\" parser=\"txt\" /></code></poml>"
)
# 在 LangChain chain 中使用
llm = ChatOpenAI(model="gpt-4.1")
chain = prompt_template | llm | StrOutputParser()
result = chain.invoke({"code_file": "test_sample.py"})
功能介绍:Speaker 模式与非 Speaker 模式(Speaker Mode vs Non-Speaker Mode)
python
# Speaker 模式:返回 ChatPromptValue(结构化消息)
# 适用于需要会话结构(system/user/assistant)的场景
template = LangchainPomlTemplate.from_file("conversation.poml", speaker_mode=True)
# 非 Speaker 模式:返回 StringPromptValue(纯文本)
# 适用于需要单段文本输出的场景
template = LangchainPomlTemplate.from_file("summary.poml", speaker_mode=False)
与 f-string、Jinja 及其他模板的对比(POML vs f-string, Jinja, and Other Templates)
官方页面指出:可通过
LangchainPomlTemplate
获得 POML 的多数能力;某些 POML 特性在其他模板系统也可实现;也有部分特性可能与 LangChain 不兼容(例如工具使用)。以下示例用于对比差异与优势。
1) 模板语法与能力(Template Syntax and Capabilities)
- Jinja2/f-string:主要是字符串插值与(Jinja 提供的)基础条件/循环。
python
from langchain.prompts import PromptTemplate
prompt_template = PromptTemplate.from_template(
"Answer the question as if you are {person}, fully embodying their style, "
"wit, personality, and habits of speech. The question is: {question}"
)
- POML:在插值之外,支持结构化组件与逻辑流。
xml
<poml>
<system-msg>You are {{ person }}, answer in their unique style and personality.</system-msg>
<human-msg>{{ question }}</human-msg>
<div if="include_examples">
<examples>
<document src="{{ person }}_examples.txt" />
</examples>
</div>
</poml>
python
from poml.integration.langchain import LangchainPomlTemplate
prompt_template = LangchainPomlTemplate.from_file("persona_prompt.poml")
prompt_template.invoke({
"person": "Mark Twain",
"question": "What is the meaning of life?",
"include_examples": True
})
2) 富内容与文件引入(Rich Content and File Inclusion)
- 替代方案(Jinja2/f-string):需要手工读取与处理 PDF,然后再注入模板。
python
import PyPDF2
from langchain.prompts import PromptTemplate
def read_pdf(file_path):
with open(file_path, 'rb') as file:
reader = PyPDF2.PdfReader(file)
text = ""
for page in reader.pages:
text += page.extract_text()
return text
pdf_content = read_pdf("document.pdf")
prompt = PromptTemplate.from_template(
"Analyze this document:\n{pdf_text}\n\nQuestion: {question}"
)
result = chain.invoke({"pdf_text": pdf_content, "question": "What are the key points?"})
- POML 方式:无需手工处理文件,直接引用。
xml
<poml>
<task>Analyze this document and answer the question.</task>
<document src="{{ pdf_path }}" />
<human-msg>{{ question }}</human-msg>
</poml>
python
result = chain.invoke({
"pdf_path": "document.pdf",
"question": "What are the key points?"
})
3) 用结构化标签组织 few-shot 示例(Structured Tags to Organize Few-shot Examples)
- LangChain FewShotPromptTemplate:
python
from langchain.prompts import FewShotPromptTemplate, PromptTemplate
examples = [
{"input": "2+2", "output": "4"},
{"input": "3*3", "output": "9"}
]
example_prompt = PromptTemplate(
input_variables=["input", "output"],
template="Input: {input}\nOutput: {output}"
)
few_shot_prompt = FewShotPromptTemplate(
examples=examples,
example_prompt=example_prompt,
prefix="Solve these math problems:",
suffix="Input: {input}\nOutput:",
input_variables=["input"]
)
- POML:
xml
<poml>
<task>Solve these math problems:</task>
<example for="ex in examples">
<example-input>{{ ex.input }}</example-input>
<example-output>{{ ex.output }}</example-output>
</example>
<human-msg>{{ input }}</human-msg>
</poml>
- 直接得到(Immediately gives you):
json
[
{ "speaker": "system", "content": "# Task\n\nSolve these math problems:" },
{ "speaker": "human", "content": "2+2" },
{ "speaker": "ai", "content": "4" },
{ "speaker": "human", "content": "3*3" },
{ "speaker": "ai", "content": "9" },
{ "speaker": "human", "content": "5-4" }
]
4) 对话格式支持(Support for Conversational Formats)
- 替代方案:需要多段独立 prompt 或复杂的字符串拼接来管理会话。
python
system_prompt = "You are a helpful assistant."
user_prompt = "What is {{ language }}?"
assistant_response = "{{ language }} is a programming language..."
followup = "Can you give an example of {{ language }}?"
# 手工管理会话流
from langchain.prompts import PromptTemplate
template_user = PromptTemplate.from_template(user_prompt)
template_assistant = PromptTemplate.from_template(assistant_response)
template_followup = PromptTemplate.from_template(followup)
template_messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": template_user},
{"role": "ai", "content": template_assistant},
{"role": "user", "content": template_followup},
]
- POML:一个文件描述整个 AI 会话。
xml
<poml>
<system-msg>You are a helpful assistant.</system-msg>
<human-msg>What is {{ language }}?</human-msg>
<ai-msg>{{ language }} is a high-level, interpreted programming language...</ai-msg>
<human-msg>Can you give an example of {{ language }}?</human-msg>
</poml>
使用场景
- 官方页面未提供具体使用场景示例。
优势亮点(基于页面表述)
- 与 LangChain 的无缝集成,
LangchainPomlTemplate
可直接用于链式调用。 - 可作为 Jinja2/f-string 的替代:除插值外,支持结构化组件与逻辑流。
- 富内容与文件引入:例如直接引用文档(如 PDF),无需手工解析。
- 结构化标签便于组织 few-shot 示例,并直接得到结构化会话消息。
- 支持对话格式:可在同一 POML 文件中表达完整会话。
- 注意:页面指出部分 POML 特性可能与 LangChain 不兼容(例如工具使用)。
未来集成(Future Integrations)
- LangSmith:面向 LangChain 的调试与监控平台
- Langfuse:用于 LLM 可观测性与分析
总结/展望
- 本页展示了 POML 在 LangChain 中的集成方式:安装、基础用法、两种模板模式,以及与其他模板方法的对比示例。
- 如需完整细节与最新示例,请参阅官方页面: