同一个事件,两种写法

先看一个示意的例子。数据源给出一个已确认事件:第34分钟,甲队某位边锋射门得分,比分变为1比0,助攻来自中场球员。

写法一(槽位化模板):“第{分钟}分钟,{球队}的{球员}破门,比分变为{比分}。”

填入之后是:“第34分钟,甲队的某位边锋破门,比分变为1比0。”

写法二(自由生成):“上半场过半,甲队终于撕开了防线,边路的突击手抢在后卫身前一脚推射,皮球应声入网。”

第二句读起来明显更有画面感,但仔细看,它已经引入了几处输入里没有的信息:“终于撕开了防线”是评价,“抢在后卫身前”是对过程的描述,“一脚推射”指定了射门方式。如果数据里根本没有射门方式的记录,这些都是模型补出来的。补得对,观众觉得精彩;补得错,就是一次事实错误,而且很难被发现,因为它听起来太自然了。

这就是矛盾的根源:自然的表达需要细节,而细节往往是模型编的。

模板的价值在于“空位有类型”

模板常被贬为“机械”,但它有一个重要特性:每个空位都有明确的类型和取值来源。

  • 分钟:来自比赛时钟,数字类型;
  • 球队:来自比赛状态,只能取两支参赛球队之一;
  • 球员:来自球员编号到标准名称的映射,只能取场上球员;
  • 比分:来自当前比分快照。

这意味着模板生成的每一句话,都可以被逐格审计。一旦某个值缺失,系统就知道这个空位填不上,可以换一个不需要它的句式,而不是让模型自由发挥去填补。

所以我们把模板看作兜底层,不是嫌弃它,而是明白它的用途:任何时候自由生成出问题,都可以回到这里,用最朴素的话把事实说清楚。

自由生成需要“围栏”,而不是“禁令”

完全禁止自由生成,主播会变得单调;完全放开,又会出错。折中的做法是给它一个围栏:

  1. 输入受限:只提供当前比赛状态、刚确认的事件和一份允许提及的实体清单;
  2. 风格分离:把“说什么”和“怎么说”写成两份独立输入,前者是事实,后者是语气、句长、节奏要求;
  3. 不要求补充:明确告诉模型没有的信息不要补充,同时允许它用泛化的描述(比如“一次漂亮的配合”)代替具体细节;
  4. 输出可解析:让模型同时输出文本和它引用的事实字段,方便后面核对。

第三条特别重要。模型有一种倾向,总想把句子写得“完整”,所以需要用指令和示例去纠正它,让它接受“信息不够时就少说”。

生成之后:数值与实体校验

即使有围栏,仍然要在输出之后做校验,否则等于把责任全部押在提示词上。校验一般分成几类:

校验项 检查内容 不通过时
数值文本中的比分、分钟、统计数字是否与快照一致 丢弃,回退模板
实体 出现的球员、球队是否在允许清单内 丢弃,回退模板
事件类型 文本描述的事件(进球、犯规、换人)是否与输入事件一致 丢弃,回退模板
时态与时间 是否把已发生的事说成正在发生,或反过来 修正或回退
倾向性表述 是否出现对球员或裁判的不当评价 拦截并交由人工规则处理

这里“数值”和“实体”是比较容易自动化的,因为它们可以通过文本抽取和比对完成。而“描述的过程是否真实”比较难,例如“一脚推射”这类细节,需要看输入里有没有对应字段。我们的做法比较保守:输入里没有的过程描述,一律视为越界。这会让文字略显平淡,但换来的是可以说明的边界。

校验只能发现“输出和输入不一致”,不能发现“输入本身是错的”。数据源出错时,校验会放行,这一类错误需要靠数据源的监控和更正机制处理,见 AI体育主播的整体链路设计

一次校验失败的走查

仍以前面的进球为例,这是一个示意的流程,文本和字段都是举例:

  1. 事实层给出:分钟34,甲队,射门得分球员为“某位边锋”,比分1比0,助攻球员为“中场球员”,射门方式字段为空;
  2. 表达层生成候选:“第34分钟,甲队边锋一脚远射得手,中场球员送出助攻,甲队1比0领先。”;
  3. 校验层抽取:分钟34,一致;球队,一致;比分,一致;球员,一致;“远射”一词对应的射门方式字段为空,判定越界
  4. 系统的处理:不放行这句,要求表达层重写,并明确“不要描述射门方式”;重写后的候选通过校验,播出;
  5. 如果重写连续失败,则回退到模板句。

这条流程里,校验层没有判断“远射”是否真实发生,它只判断“输入里是否有依据”。这种保守,正是我们希望的:不知道就不说,比说得漂亮更重要。

把事实层和风格层拆开

把上面的思路合起来,得到一个分层结构:

  1. 事实层:事件、状态、实体清单,全部来自结构化数据,带状态和时间戳;
  2. 约束层:规定哪些事实允许被引用,哪些不允许,哪些表述必须保守;
  3. 表达层:语言模型在约束内选择语气、句式、修辞,生成候选文本;
  4. 校验层:把候选文本拉回到事实层核对,通过才放行;
  5. 兜底层:校验失败时使用槽位化模板。

这个结构最大的好处是责任清晰。当某句话出问题,可以判断是事实层的数据问题、表达层的越界,还是校验层的漏检,而不是一句“模型又幻觉了”。

风格也是有边界的

有些风格上的做法看起来无害,实际上会悄悄影响事实:

  • 夸张修辞:把“一次不错的射门”说成“教科书般的完美破门”,属于主观评价,是否允许应由编辑规则决定;
  • 因果暗示:“因为换人,比赛出现转折”,暗示了因果关系,输入里如果没有对应依据,就属于过度解释;
  • 预测性语句:“这个球基本奠定了胜局”,容易在后续比赛中被打脸。

我们倾向于把这些交给一份可配置的“风格与边界规则”,由编辑维护,而不是隐藏在提示词里。这样风格可以调,事实边界不动。赛后类内容对因果和转折的解释要求更高,这一点在 赛后复盘从转折点出发的写法 里有另外的讨论。

怎么评价一个主播文本好不好

如果只看“读起来自然”,很容易选错方案。更合适的做法是把评价拆成两条独立的线:

  • 事实线:数值一致率、实体一致率、越界描述数量,这些是可以自动统计的;
  • 表达线:重复度、句式多样性、语气匹配度,可以由编辑抽样评价。

两条线不应该被平均成一个分数。事实线有硬门槛,达不到就不能上线;表达线则是在事实达标的前提下持续优化。此处没有引用任何实测数字,这些是评测的设计思路,具体门槛需要在真实数据上标定。

还没有完全解决的地方

  • 细节与安全的取舍:在不引入错误的前提下,怎样为文字增加足够多的信息量,仍然依赖丰富的结构化数据;
  • 跨语言一致性:同一事实用不同语言表达时,术语和名字如何保持一致,是另一个独立的难题;
  • 风格漂移:连续多场比赛之后,主播的语气会不会越来越模板化,需要长期观察。

总的来说,事实正确与表达自然并不是必须二选一的对立面,前提是把它们放到不同的层里,让各自的规则清楚、责任清楚。