qinghuan
← 规定输出格式并检查 / 全部笔记

单元 09 / 规定输出格式并检查

P0 · 必会主线L1 · 基础

把模糊需求写成可测试的提示

把任务、资料和通过条件写清楚,再用一致的示例说明应该怎样回答、缺资料时怎么办。

本篇目录 · 按需要跳转

读完这篇,你能做什么

能把模糊需求改写为模板,并用八个边界样例比较两个提示版本。

学习理由、准备要求与知识点

为什么学它

先说清任务怎样才算完成,再用固定样例比较提示版本,才能知道改法是否有效。

先读这些内容

知识点清单

  • 任务目标与验收标准
  • 输入资料边界
  • 零样本提示
  • 少样本示例一致性
  • 缺失与冲突信息策略
  • 模板变量与分隔符
  • 单因素提示实验
  • 解释文本与证据区别

运行前先确认完整算法使用 Java 17 标准库;JDK 源码基线为 OpenJDK 17 GA。示例是内存中的机制模型,外部服务接入需要另外配置和验证。

01先弄懂它是什么

提示写得清楚,首先要把要做的事说清楚。“帮我整理资料”没有说明范围、来源和怎样算完成。换成“从给定笔记提取三条索引使用条件,每条附片段 ID,资料不足时说明缺项”,程序就有办法检查结果。任务、输入和验收条件越明确,提示也越容易维护。

只说明任务、不给示例,叫零样本提示;补充少量输入输出例子,叫少样本提示。例子不只是展示语气,还会影响模型采用哪些字段、按什么顺序写、缺资料时怎么办,因此彼此不能矛盾。例如同时给出“资料足够”和“资料不足”两种样例,就能更清楚地说明什么时候应回答、什么时候应说明缺项。

模板变量将稳定规则和动态数据分开,方便版本化与测试。但分隔符只是表达结构,不是权限墙。资料中出现“忽略规则”仍是不可信文本,应用必须在工具授权与数据边界处执行策略,不能把安全性完全寄托于一段提示。

文中这几个词,先认一认

验收标准
能实际核对的完成条件,例如字段是否齐全、引用是否对应来源、缺资料时是否明确说明。
模板变量
模板里由应用填入动态数据的位置。填入的内容不应被再次当作新的模板指令执行。
少样本示例
用少量输入和理想输出来说明任务应该怎么做,这些例子需要遵守同一套规则。

还有陌生词?到术语小抄里看一个具体例子 ↗

02看看它怎么工作

把提示拆成目标、资料、输出约束与缺失策略四部分。每部分只解决自己的问题:目标说明要做什么,资料声明可使用内容,约束定义输出形态,缺失策略处理不足和冲突。不要让示例中的临时事实变成所有请求的固定答案。

渲染模板时,只扫描原始模板并替换其中允许的变量一次。例如用户资料本身包含 ${secret},应把它当作普通文字放进去,不要再把 secret 当变量继续查找。否则资料内容就能改变模板处理过程,甚至带出内部字段。这个做法保护的是模板怎样被解释,并不能单独解决模型读到恶意指令后的提示注入。

实验时固定一组正常、空资料、冲突资料和恶意指令资料,先保存模板版本,再每次只改一个因素。记录合规率与具体失败类型,而不是凭一次回答是否顺眼决定优劣。模型提供的“我已核对”也应由引用映射或外部检查证实。

正在加载流程图…

图中状态只描述本篇可执行机制;业务调用仍需由外层应用负责。
查看流程图源码(Mermaid)
flowchart LR
  G["任务与验收标准"] --> T["版本化模板"]
  D["授权资料变量"] --> R["单次字面渲染"]
  T --> R
  R --> M["模型输出"]
  M --> V["结构与证据校验"]
  V --> E["固定样本比较"]

按顺序看,每一步做了什么

  1. 把模糊目标写成可以核对的输出和禁止行为。
  2. 确定输入资料范围与缺失、冲突处理策略。
  3. 选择一致的少样本示例,建立版本化模板。
  4. 单次渲染变量,不递归解释变量值。
  5. 在固定样本上做单因素比较并保留失败回归。

03对照实现代码

OpenJDK 17 Matcher 源码 (新标签页)↗

OpenJDK 17 GA,jdk-17+35 · Matcher.quoteReplacement / appendReplacement

下方为原创 Java 教学片段,调用已核验的 JDK API 说明局部机制;不是该类原样源码,也不实现神经网络。完整程序见算法模块。

核心机制代码 · java
Matcher matcher = Pattern.compile("[$][{]([a-z]+)[}]").matcher(template);
StringBuffer out = new StringBuffer();
while (matcher.find()) {
    String value = values.get(matcher.group(1));
    // 替换语法中的美元符号和反斜线按普通字符处理,避免被当作分组引用。
    matcher.appendReplacement(out, Matcher.quoteReplacement(value));
}
matcher.appendTail(out);

Matcher.quoteReplacement生成适合替换字符串语法的字面表示,主要处理美元符号和反斜线;它不是HTML转义、JSON转义或模型安全过滤器。

appendReplacement扫描的是原匹配输入,替换值被追加到输出缓冲,不自动再次作为模式输入。本题完整程序使用手写单遍扫描,显式展示同样的不递归边界。

模板变量不存在时应给出明确错误,而不是把null拼成字符串。生产模板还需控制允许变量名和最大输出长度,防止配置错误或巨大资料使请求失控。

Java片段解释的是确定性字符串处理。模型如何理解最终提示仍有概率性,模板渲染正确只能证明构造的文字符合规则,不能证明模型一定遵守所有自然语言要求。

代码先调用谁,再调用谁

  1. 加载受版本控制模板
  2. 识别原模板变量
  3. 检查变量白名单及存在性
  4. 按字面追加值而不递归解释
  5. 将完整提示交给后续受控调用

04动手写一个例子

不递归的单遍模板渲染

模板支持${name},变量名只能是字母数字下划线且非空;未知变量或未闭合表达式拒绝。替换值不再次展开。Java17 Main.java含固定边界测试。

输入 1
模板你好${name},name=Java
输出 1
你好Java
输入 2
模板${x},x=${secret}
输出 2
${secret}

游标只在原模板中前进,找到起始符后定位对应右花括号,验证变量名再取值。输出缓冲不重新送回扫描器,因此变量值无法引入新的展开步骤。

不以反复String.replace实现渲染,避免变量遍历顺序改变结果。例如先替换x再替换secret会误展开x的值,而相反顺序又产生不同输出。

遇到非法变量直接失败,调用者可以定位模板配置。没有占位符的普通文本原样保留,空模板输出空串;这种可预测行为便于对提示版本做差异测试。

为什么这样写是对的游标之前的原模板已按规则恰好处理一次,输出是该前缀的字面渲染;输出中出现的占位符从不影响剩余原模板的解释。

时间 O(T+O)额外空间 O(O)

T为模板长度,O为输出长度;各模板片段扫描和复制次数有界,变量哈希查找平均常数但需读取变量名。输出巨大时空间同样巨大,应由上层设置长度上限。

保存为 Main.java,运行 javac --release 17 -encoding UTF-8 Main.java,再运行 java Main。程序包含固定输入自测,断言失败时会抛出错误。

Main.java · 完整可运行程序 · Java
import java.util.*;
public class Main {
    static String render(String template,Map<String,String> values){
        StringBuilder out=new StringBuilder();int i=0;
        while(i<template.length()){
            if(template.charAt(i)=='$'&&i+1<template.length()&&template.charAt(i+1)=='{'){
                int end=template.indexOf('}',i+2);
                if(end<0)throw new IllegalArgumentException("unclosed variable");
                String name=template.substring(i+2,end);
                if(name.isEmpty())throw new IllegalArgumentException("empty name"); // 空变量名属于模板配置错误。
                for(char c:name.toCharArray())if(!(c>='a'&&c<='z'||c>='A'&&c<='Z'||c>='0'&&c<='9'||c=='_'))throw new IllegalArgumentException("name");
                String value=values.get(name);if(value==null)throw new IllegalArgumentException("missing variable");
                out.append(value);i=end+1; // 值只追加,绝不重新扫描它。
            }else out.append(template.charAt(i++));
        }
        return out.toString();
    }
    static void eq(String e,String a){if(!e.equals(a))throw new AssertionError(a);}
    static void bad(String t){try{render(t,Map.of());throw new AssertionError();}catch(IllegalArgumentException expected){}}
    public static void main(String[] args){
        eq("你好Java",render("你好${name}",Map.of("name","Java")));
        eq("${secret}",render("${x}",Map.of("x","${secret}","secret","hidden")));
        eq("$5"+(char)92+"x",render("${x}",Map.of("x","$5"+(char)92+"x")));// 字面保留特殊字符。
        eq("",render("",Map.of()));eq("AA",render("${x}${x}",Map.of("x","A")));
        bad("${missing}");bad("${x");bad("${}");
        System.out.println("PASS 8 tests");
    }
}

这些特殊情况也要试一试

  • 值含新的占位符也保持字面,不递归展开。
  • 变量名缺失与变量值为空字符串不同,空值可合法输出。
  • 未闭合模板是配置错误,不能默默当普通文字。
进阶选读 · 后续再读:可组合模板的依赖验证

场景模板片段相互引用且需要复用,单遍规则不足以表达结构。

做法把引用建成有向图,先检测循环与未知节点,再按拓扑顺序展开;限制总展开长度,避免无环但指数膨胀的重复引用。

复杂度图验证O(V+E),实际展开至少O(输出长度);无环并不保证输出长度对输入图规模为线性。

好处与代价组合模板提高复用,但增加依赖与版本管理;简短固定模板往往更易审计和比较。

05项目里怎么用

将提示模板当作可版本化配置,与数据样本和输出Schema一起评审。修改“允许补充常识”为“仅使用资料”会改变正确性标准,必须相应调整评估集。模板版本应进入运行元数据,才能解释相同问题在两次运行中的行为变化。

输入资料保留来源ID、时间与适用版本,冲突时要求指出分歧而非擅自合并。示例可以展示如何引用,但最终引用ID必须来自当前允许集合。模板渲染器不应把隐藏凭证或跨用户资料作为变量提供,即使提示声明“不要泄露”也不能替代数据最小化。

安全验收看实际工具轨迹:恶意资料是否诱导越权检索、写操作或外部发送。提示层表达规则,应用层执行授权、参数校验与确认;这两个层次配合才能缩小失控范围。基础练习先完成确定性模板与固定样本,再读工具安全专题。

容易踩的坑

  • 大量添加“专业、认真”等词却没有验收标准。
  • 少样本示例字段与正式要求不一致。
  • 递归展开用户数据,改变模板控制流程。
  • 将分隔符或quoteReplacement当作提示注入防护保证。

几种做法,怎么选

表格有四列,窄屏可左右滑动查看代价和适用条件。

方案优势代价与限制适用条件
零样本规格短且易维护复杂格式可能表达不充分任务简单且契约明确
少样本模板能展示边界和风格占上下文,示例偏差会传播需要示范结构与缺失处理
程序校验配合提示可强制结构与授权边界需要额外代码和错误流程可验收的正式应用

06检验是否读懂了

先自己想、自己写,再展开答案核对。场景题是假设的练习情境;遇到还没学过的内容,可以做完基础后再回来。

先用自己的话解释

01提示目标与验收标准有何区别?

展开参考答案与推导

目标说明想完成什么,验收标准说明怎样核对完成;“整理知识”是目标,“三条条件并附来源ID”是可检查标准。

02quoteReplacement能防什么?

展开参考答案与推导

它防止替换字符串中的特殊字符被解释成正则替换语法,不负责HTML、JSON或模型层安全。

03为什么变量值不应递归展开?

展开参考答案与推导

动态数据不应改变模板控制结构;递归还使结果依赖替换顺序,并可能读取原本不该引用的变量。

换个情况,还会处理吗

01提示改完一次回答很好,能认定更优吗?

展开参考答案与推导

需要在固定样本和相同配置下重复比较,通过率与失败类型比单个展示案例更有解释力。

02资料要求忽略规则,该在哪里阻止越权?

展开参考答案与推导

把资料作为不可信输入,同时由应用检查身份、工具范围和资源归属;提示提醒只是其中一层。

03引用格式正确却来源不存在怎么办?

展开参考答案与推导

核对引用ID是否在当前资料集合,拒绝未知ID并保留失败样本;格式规范不能证明引用真实存在。

写代码试一试

01两次相同变量怎么处理?

输入 / 条件
${x}-${x},x=A
输出 / 预期
A-A

提示 每次读取原模板变量。

展开参考答案与推导

两处都追加同一字面值,输出不被再次扫描,复杂度与最终输出长度相关。

02如何区分空值与缺字段?

输入 / 条件
x=""与没有x
输出 / 预期
前者输出空串,后者拒绝

提示 检查映射存在与值策略。

展开参考答案与推导

本题允许空字符串但拒绝null;若业务允许null,应使用containsKey区分存在性并明确null渲染规则。

03无环模板为什么仍可能很大?

输入 / 条件
每层引用前一片段两次
输出 / 预期
展开长度随层数倍增

提示 图规模与输出规模不同。

展开参考答案与推导

拓扑检测只保证没有循环,不能限制重复复制;必须设置最大输出长度并对共享片段采用受控渲染。

读完之后,独立完成

课后作业:自己做一遍

本篇共 10 道作业,先完成 8 道基础与综合任务,再按前置知识挑战进阶题。其中包含 1 道思维拓展,试着换个条件,看看原来的办法是否还管用。不附参考答案。

这次练什么

能把模糊需求改写为模板,并用八个边界样例比较两个提示版本。

本篇重点加练

资料边界与单因素实验帮助识别提示改动的真实作用,重点防止比较条件被同时改变。

  • 输入资料边界
  • 单因素提示实验

重点内容会多练几次。先说清楚怎么做,再试试空数据、出错或条件改变时会发生什么。

先自己做,卡住时记下问题,再回来查。问答题写清“为什么、什么时候适用”;动手题留下输入、输出和运行步骤,方便下次重做。

基础必做

  1. 作业 01原理问答

    将“帮我安排学习”改写为可验收任务,明确输入资料、目标用户、结果字段和资料之外的信息处理要求。

    提交内容
    一份独立书面回答或标注图,包含自造例子、概念边界及判断依据。
    怎样算完成
    • 逐项回应题目要求,区分事实、假设与个人判断。
    • 能用自己的例子解释适用条件,记录尚未弄懂的点。

    练到的知识点任务目标与验收标准 · 输入资料边界

  2. 作业 02代码推演

    为同一任务分别构造零样本与两例少样本提示,逐项审查示例在格式、标签和边界处理上是否一致。

    提交内容
    手工推演记录,写明输入约定、中间状态、最终判断;可运行时附程序对照记录。
    怎样算完成
    • 推演包含中间过程,数据形状、单位、顺序或状态前后一致。
    • 主动检查至少一个边界或异常条件,能解释手算与运行差异。

    练到的知识点零样本提示 · 少样本示例一致性

  3. 作业 03原理问答

    为提示实验编写输入冻结清单,区分任务内容、资料版本、提示变量与外部模型设置,说明哪些变化会让单因素结论失效。

    提交内容
    概念或合同说明、关系图与自造案例,明确事实、假设和适用条件。
    怎样算完成
    • 关键概念有明确边界,能用案例检验声明。
    • 未获证据支持的假设单独标注。

    练到的知识点输入资料边界 · 单因素提示实验

综合应用

  1. 作业 04面试场景

    输入资料缺少截止日期且两条记录相互矛盾,模板变量中还包含类似分隔符的内容。设计输出契约与输入编码规则。

    提交内容
    场景分析与决策记录,包含信息缺口、约束、备选方案和验证计划。
    怎样算完成
    • 方案回应给定约束,列出至少一种替代方案及代价。
    • 每项关键结论说明所需证据,不能核实的部分明确标注。

    练到的知识点缺失与冲突信息策略 · 模板变量与分隔符

  2. 作业 05编程实践

    建立六条固定测试输入,仅改变一个提示因素并运行假模型或可用模型,分别记录结果与引用证据,保留不能验证的输出。

    提交内容
    可复现的最小程序或实验材料、自写测试、环境说明与运行记录;题目允许纸面实验时提交完整案例表。
    怎样算完成
    • 提交物按说明可以重现;测试覆盖正常、边界与失败场景。
    • 运行证据与断言能核验声明的行为,注明模拟与真实执行范围。

    练到的知识点单因素提示实验 · 解释文本与证据区别

  3. 作业 06排错实验

    在少样本中故意插入一个格式冲突例子,再将变量替换为空值,观察并记录失败类型,不把一次成功当稳定性证明。

    提交内容
    最小故障输入、复现步骤、观测记录、定位依据及回归用例。
    怎样算完成
    • 其他人可按记录复现故障,并区分现象与已验证原因。
    • 定位过程有观测依据,回归用例可以再次暴露原问题。

    练到的知识点输入资料边界 · 少样本示例一致性 · 模板变量与分隔符

  4. 作业 07编程实践

    构造两份只在资料边界表达上不同的提示,使用同一组含额外无关资料的离线任务,保存逐项判定记录和实际改变的文本差异。

    提交内容
    可复现的小程序或题目允许的离线实验、自写测试、输入和运行记录。
    怎样算完成
    • 输入、环境和运行过程可重现,测试覆盖声明的重点条件。
    • 验证目标由合同确定,模拟结果不冒充真实服务证据。

    练到的知识点输入资料边界 · 单因素提示实验

  5. 作业 08排错实验

    一份提示对照报告同时换了示例、模型与资料版本。拆解报告的可支持结论,设计最少的补充实验来缩小不确定性。

    提交内容
    最小故障序列、观测记录、原因核对与可再次触发原问题的测试。
    怎样算完成
    • 故障可以稳定重现,现象与已验证原因分开。
    • 观测记录足以判断声明的合同是否被违反。

    练到的知识点输入资料边界 · 单因素提示实验

进阶挑战 · 掌握前置后选做

  1. 作业 09设计评审

    设计提示版本的发布与回滚流程,包含开发样例、冻结测试集和人工复审,说明何种证据足以支持更新。

    提交内容
    设计评审文档或对照实验报告,包含前置条件、方案取舍、验收证据与尚未验证的范围。
    怎样算完成
    • 比较使用一致条件与事先声明的标准,记录失败与未知结果。
    • 说明方案的适用前提、未覆盖风险及后续验证方法。

    练到的知识点任务目标与验收标准 · 缺失与冲突信息策略 · 单因素提示实验

思维拓展

先写出你的猜想,再用例子或实验验证。答案可以不同,但要说清依据、适用情况,以及还有什么没弄懂。

  1. 作业 10思维拓展 · 开放探究

    提出“明确标出资料范围能改善某类任务”的可证伪假设,预先定义失败情形与评价方法,并说明样本不足时如何限制结论。

    提交内容
    可证伪假设、预先声明的比较协议、小规模证据与限制说明。
    怎样算完成
    • 假设存在可被否定的条件,协议在观察结果前声明。
    • 包含不支持假设的可能结果及不确定性说明。

    练到的知识点输入资料边界 · 单因素提示实验

完成后,再检验一次

给每题标记“独立完成 / 查阅后完成 / 尚未完成”。查过资料或没做出的题,记下卡在哪里。隔一天换一组输入再试,能解释结果和出错原因,再把这个知识点标为掌握。

继续阅读

先看能帮你完成当前练习的部分。例子跑通后,再读更深入的解释。

打开资料库,找下一份学习材料 ↗