ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Outlines 模板系统(Template)完全指南:用 Jinja2 构建可复用、可组合的结构化提示词

Outlines 模板系统(Template)完全指南:用 Jinja2 构建可复用、可组合的结构化提示词 Outlines 模板系统Template完全指南用 Jinja2 构建可复用、可组合的结构化提示词【免费下载链接】outlinesStructured Outputs项目地址: https://gitcode.com/GitHub_Trending/ou/outlinesOutlines 的Template是一个基于 Jinja2 的提示词模板系统它把提示词结构从具体内容中解耦让你用带占位符的模板来复用、组合、渲染提示词。本文以 docs/features/utility/template.md 为主线结合 src/outlines/templates.py 的源码实现与 tests/test_templates.py 的测试用例系统讲解Template的创建方式、渲染调用、嵌套组合、自定义过滤器与内置过滤器以及它与Application、各模型接入方式的配合实战。读完本文你将掌握如何为分类、抽取、Agent 等任务编写工程化、可维护的提示词层。Template 是什么在 Outlines 中Template是可复用提示词结构的载体模板本身是一段包含 Jinja2 占位符如{{ name }}的文本运行时用关键字参数把动态内容填充进去渲染出最终喂给模型的提示词字符串。Template在 src/outlines/init.py 中被导出到顶层命名空间因此可以直接从outlines导入from outlines import Template在源码中Template是一个dataclass见 src/outlines/templates.py内部封装了一个jinja2.Template实例。它不直接返回普通函数而是返回一个可调用的类实例这样模板对象可以被外部访问、复用和组合。创建模板from_string 与 from_file创建Template实例有两种类方法方法用途签名Template.from_string(content)从包含 Jinja2 模板的字符串创建from_string(cls, content: str, filters: Dict[str, Callable] {})Template.from_file(path)从包含 Jinja2 模板的文件创建from_file(cls, path: Path, filters: Dict[str, Callable] {})从字符串创建from outlines import Template # Create a template from a string template_str Hello, {{ name }}! The weather today is {{ weather }}. template Template.from_string(template_str)从文件创建# Create a template from a file, assuming the content of template_str is put into a file template Template.from_file(path_to/my_file.txt)from_file在底层使用jinja2.FileSystemLoader加载目录为模板文件所在的目录见 src/outlines/templates.py。有一个值得注意的限制from_file不允许include或模板继承引用该文件所在目录及其子目录之外的文件这在源码 docstring 中有明确说明设计如此避免跨目录的文件访问。仓库中的真实用法可参考 docs/examples/classification.md它从prompt_templates/classification.txt文件加载客服工单分类模板from outlines import Template customer_support Template.from_file(prompt_templates/classification.txt)再比如 docs/examples/react_agent.md 从prompt_templates/react_agent.txt加载 ReAct Agent 提示词。底层预处理细节从字符串构建模板时build_template_from_string会做几件值得了解的事情自动去缩进用inspect.cleandoc(content)去掉首尾空行和公共缩进因此你用三引号缩进书写模板时渲染结果不会带多余的缩进。保留结尾换行如果原始内容以空行结尾会补回一个换行符。压缩多余空白用正则把行内多余的连续空白压缩为单个空格但保留紧跟换行符的空白——这样模板里用反斜杠\续行的写法A long test \ 换行 that we break渲染后会合并成一行A long test that we break。这一行为由 tests/test_templates.py 中的test_render_escaped_linebreak用例验证。调用模板渲染提示词创建模板后直接以模板所需变量作为关键字参数调用它即可得到渲染后的字符串# Call the template to render the prompt prompt: str template(nameAlice, weathersunny) print(prompt) # Hello, Alice!\nThe weather today is sunny.底层渲染逻辑在Template.__call__src/outlines/templates.py它调用self.template.render(**kwargs)并把结果以str返回。测试用例 tests/test_templates.py 验证了基本渲染行为content Hello, {{ name }}! prompt Template.from_string(content) assert prompt(nameWorld) Hello, World!模板支持完整的 Jinja2 控制流语法。例如 tests/test_templates.py 中的用例展示了循环与条件渲染# 循环 {% for e in examples %} Example: {{e}} {% endfor -%} # 条件 {% if is_true %} true {% endif -%}注意-%}结尾标签会吞掉后面的换行这在拼接多行提示词时非常有用可以精确控制输出中的空行。组合模板构建复杂提示词结构模板可以被嵌套组合用来构建复杂的提示词结构。你可以分别定义用户消息模板和系统消息模板再把它们作为变量填充进一个更大的对话模板from outlines import Template # Create component templates user_template Template.from_string(User: {{ query }}) system_template Template.from_string(System: {{ instruction }}) # Create a composite template chat_template Template.from_string( {{ system }} {{ user }} ) # Fill in nested templates prompt chat_template( systemsystem_template(instructionYou are a helpful assistant.), useruser_template(queryWhat is machine learning?) ) print(prompt) # System: You are a helpful assistant. # # User: What is machine learning?组合模板的能力意味着你可以把提示词拆成小的、可单独维护与测试的组件再在顶层拼接。由于每个Template实例本身就是可调用对象__call__返回渲染后的字符串它天然可以作为另一个模板的变量值传入——这正是组合得以成立的结构基础。自定义过滤器扩展模板能力你可以给模板注册自定义 Jinja2 过滤器。方式是把一个字典作为第二个参数传入字典的键是过滤器名字值是对应的过滤器函数。模板内按 Jinja2 常规语法使用过滤器渲染时函数会被应用到关联变量上from outlines import Template def uppercase(text: str) - str: return text.upper() # Add custom filter when creating template template Template.from_string( Hello {{ name | uppercase }}!, filters{uppercase: uppercase} ) prompt template(namealice) print(prompt) # Hello ALICE!from_string与from_file都接受这个filters参数。在源码的 create_jinja_env 中用户传入的过滤器会被逐一写入env.filters并且会覆盖同名的预定义过滤器——这提供了一种可扩展的定制机制。对应的测试用例见 tests/test_templates.pytpl {{ name | custom_filter }} assert render(tpl, {custom_filter: custom_filter}, nameJohn) JOHN内置过滤器面向 LLM 提示词的六个预置工具除了用户自定义过滤器Outlines 在创建 Jinja2 环境时预置了六个过滤器见 create_jinja_env它们专为把 Python 对象直接嵌入提示词而设计过滤器作用实现name返回可调用对象的函数名get_fn_namedescription返回可调用对象 docstring 的第一行get_fn_descriptionsource返回可调用对象的源码get_fn_sourcesignature返回可调用对象的参数签名get_fn_signatureargs返回带类型注解与默认值的参数列表get_fn_argsschema将 dict 或 Pydantic 模型渲染为可读的 JSON Schemaget_schema这些过滤器的行为在 tests/test_templates.py 中有完整验证。例如def foo(bar: str) - str: This is a sample function. return bar # name filter {{ func | name }} # - foo # description filter {{ func | description }} # - This is a sample function. # signature filter {{ func | signature }} # - bar: str # args filter {{ func | args }} # - bar: str其中source过滤器只截取从def开始的部分剔除装饰器等前置代码signature过滤器用正则提取函数源码括号内的参数部分均通过 tests/test_templates.py 的测试。schema 过滤器的 JSON Schema 渲染规则schema过滤器通过functools.singledispatch分派见 src/outlines/templates.py对dict直接 pretty-print 成带缩进的 JSON对 PydanticBaseModel类型调用model_json_schema()或旧版schema()后由 parse_pydantic_schema 与 parse_pydantic_schema_value 递归渲染成便于喂给模型的描述性 Schema对其他类型抛出NotImplementedError。渲染规则要点均有测试支撑见 tests/test_templates.py字段带description时输出描述文本enum字段输出形如leather | chainmail | plate的可选项集合嵌套 Pydantic 模型沿$ref递归展开成嵌套 JSONOptional[T]字段按底层类型渲染Optional[Enum]仍显示枚举值而不是占位符真正的多成员联合类型A | B无法用单一分支表达回退为name占位符避免误导性展示。Jinja2 环境配置渲染行为的关键开关Template使用的 Jinja2 环境create_jinja_env设置了几个对提示词渲染影响显著的选项选项取值影响trim_blocksTrue删除标签块后的首个换行符lstrip_blocksTrue删除标签块前的空白keep_trailing_newlineTrue保留模板末尾的换行符undefinedjinja2.StrictUndefined渲染时引用未定义变量会抛错而不是静默输出空字符串StrictUndefined尤其值得注意如果调用模板时漏传了某个变量渲染会直接抛出jinja2.UndefinedError从而在开发期就暴露模板与调用参数不一致的问题而不是把空内容悄悄拼进提示词。从文件加载的进阶用法include 与模板继承由于from_file基于jinja2.FileSystemLoader它天然支持 Jinja2 的include与{% extends %}模板继承。测试 tests/test_templates.py 构造了一个完整例子一个基础模板base_template.txt定义{% block content %}一个include.txt循环渲染示例问答对主模板prompt.txt继承基础模板并在 block 内 include 示例文件{% extends base_template.txt %} {% block content %} Here is a prompt with examples: {% include include.txt %} Now please answer the following question: Q: {{ question }} A: {% endblock %}渲染结果会把两个 few-shot 示例与最终问题拼接成完整提示词见test_prompt_from_file的断言。这正是把少量样本few-shot examples从代码中抽离到独立文件、按需组合的推荐做法。需要注意的限制是from_file的 include/继承只能引用模板文件所在目录含子目录内的文件。实战Template 与 Generator、Application 的配合配合 Generator 做分类结合 docs/examples/classification.md模板文件加载后直接传入变量渲染出一批提示词再交给Generator做结构化输出from typing import Literal import outlines from outlines import Template customer_support Template.from_file(prompt_templates/classification.txt) requests [ My hair is one fire! Please help me!!!, Just wanted to say hi ] prompts [customer_support(requestrequest) for request in requests] generator outlines.Generator(model, Literal[URGENT, STANDARD]) labels generator(prompts) print(labels) # [URGENT, STANDARD]配合 Application 封装可复用组件Template还经常与Application配合Application把一个提示词模板和一个输出类型封装成可复用组件调用时传入模型与模板变量字典见 docs/features/utility/application.md 与 src/outlines/applications.pyfrom typing import Literal import transformers from outlines import Application, Template, from_transformers template_str Is {{ name }} a boy or a girl name? template Template.from_string(template_str) model from_transformers( transformers.AutoModelForCausalLM.from_pretrained(microsoft/Phi-3-mini-4k-instruct), transformers.AutoTokenizer.from_pretrained(microsoft/Phi-3-mini-4k-instruct) ) application Application(template, Literal[boy, girl]) response application(model, {name: Alice}, max_new_tokens10) print(response) # girlApplication内部会对同一模型复用Generator实例仅在模型变化时重建而提示词始终由self.template(**template_vars)渲染见 src/outlines/applications.py因此Template是构造 Application 时推荐的提示词载体。仓库中还有大量基于Template的真实案例可供对照学习chain_of_densitydocs/examples/chain_of_density.md模板文件 docs/examples/prompt_templates/chain_of_density.txt、few-shot 抽取docs/examples/extraction.md、知识图谱抽取docs/examples/knowledge_graph_extraction.md等展示了从简单插值到复杂指令式模板的多种应用形态。小结Outlines 的Template以 Jinja2 为引擎提供了一套轻量而完整的提示词工程基础设施两种创建方式from_string适合内嵌短模板from_file适合把提示词沉淀为独立文件并支持include与模板继承可组合模板实例本身就是可调用对象可以嵌套渲染出多段式对话提示词可扩展自定义过滤器可注册也可覆盖内置过滤器内置的name/description/source/signature/args/schema六个过滤器让 Python 函数与 Pydantic 模型能直接、规范化地嵌入提示词行为可控StrictUndefined、trim_blocks、lstrip_blocks、keep_trailing_newline等环境选项保证了渲染结果的确定性与可预期性生态整合与Generator、Application及各类模型接入方式transformers、llamacpp、vllm 等无缝配合是 Outlines 结构化生成工作流中提示词层的标准答案。【免费下载链接】outlinesStructured Outputs项目地址: https://gitcode.com/GitHub_Trending/ou/outlines创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表