☰
用 Vale-LLM-slop 给 AI 文本做 Lint:精准识别并消除“AI 味”
2026/10/24 0:13:32 网站建设 项目流程

团队这两年维护过不少技术文档和算法白皮书,有一个感受越来越明显:AI 写出来的内容,质量下限变高了,但“AI味”也变多了。如果你把 ChatGPT、Claude 生成的段落直接贴进项目 README、技术博客或者内部 Wiki,第一次阅读可能觉得通顺,可一旦多看几篇,就会发现它们共享同一套词汇、同一类转折、同一种“看似严谨但什么都没说”的节奏。这不是玄学,而是可以量化的语言特征。既然代码有 Lint,那散文为什么不能有 Lint?

这篇文章要聊的项目是Vale-LLM-slop,从名字可以看出,它做的正是“面向 LLM 文本的散文检查”:用 Vale 这个开源 prose linter,把大模型输出中典型的高频套话、空洞连接词和模板化表达识别出来。文章会讲清楚三个问题:它到底检测什么、它为什么能帮你把文档质量拉回人类水准、以及你该怎么把它接入到自己的写作和 CI 流程里。

如果你经常要把 LLM 生成的内容改写成可发布文档,或者你在负责团队知识库、技术博客和 API 文档的质量规范,这篇文章值得读完。

1. 为什么“AI 味”文案需要一个 Linter

先看一个特别常见的场景。你需要写一段接口说明,原话可能是:

As an AI language model, I must emphasize that APIs are essential components in modern software architecture. Moreover, it is crucial to note that robust error handling plays an important role in ensuring system reliability and stability.

这段话有问题吗?从语法看没有,每个句子都是对的。从信息量看,问题就出来了:大量存在的“As an AI language model”“Moreover”“it is crucial to note that”都是元话语,它们不携带业务信息,只是让段落看起来更流畅。更麻烦的是,这种表达会在文档里成片出现,读者会逐渐失去耐心。

代码圈早就解决过类似问题。eslint能检查未使用变量,checkstyle能强制代码风格,pylint能提醒你不要把函数写得过于复杂。这些工具的核心思路是:把“好不好”拆成一条条可执行的规则。Vale 把同样思路搬到了文字层:它不是自然语言处理模型,也不理解你写了什么意思,它用基于规则的模式匹配去识别那些会让文字变廉价、变啰嗦、变“AI”的表达。

Vale-LLM-slop 要做的,就是把这几年 LLM 输出中被讨论最多的“模型腔”总结成规则集。这里的判断很明确:“AI 味”是一种可耻的冗余,而冗余应该被机器拦下来,而不是靠人工逐句猜。

2. Vale 与 LLM-slop:先搞清楚两个概念

2.1 Vale 不是拼写检查器,是 prose linter

Vale 是一个用 Go 编写、MIT 协议开源的散文风格检查器。它和 Grammarly、scspell这类工具的根本区别在于:Grammarly 偏语法纠错,Vale 偏风格规则。它并不试图理解句子成分,而是基于配置好的规则,在文本里搜索特定 token、匹配正则表达式,或者检查写作风格的一致性。

Vale 官方遵循一套简洁的思想:一切皆规则,规则基于styles目录组织。你可以按团队需求新增、禁用规则,也可以把多种规则集合起来形成一个风格包。

它支持常见的文本格式,包括 Markdown、HTML、reStructuredText、AsciiDoc 等。这对技术文档场景非常友好,你不需要把文章从 Markdown 转成纯文本再来检查。

2.2 LLM-slop 指的是什么

“slop”这个词在 AI 圈里是贬义的,指的是大模型生成内容里那种低质量、模板化、信息密度极低的文本。它不一定有语法错误,甚至很容易达到“及格分”,但整体看会觉得作者在堆词而不是在表达。

常见特征包括:

  • 过度使用 “delve”“furthermore”“moreover”“in conclusion” 这类高级连接词
  • 开头总爱写 “In today's fast-paced world” 一类毫无信息量的背景句
  • 总在强调 “It is important to note that”,但实际上后面跟的内容并没有那么重要
  • 大量使用被动语态和名词化表达,把简单动作包装成严肃过程
  • 重复“As an AI language model”,把模型的自我身份放进本该属于用户的文档里

这些特征说到底和“代码里的魔法数字”一样:出现一次没什么,但成规模出现就会毁掉文档的可读性。LLM-slop 就是专门识别这些特征的规则集合。

2.3 Vale-LLM-slop 到底做了什么

从项目命名看,Vale-LLM-slop 的本质是打包了一批针对 LLM 文本特征的 Vale 规则。你把它放进 Vale 的 styles 目录,然后基于这些规则去 lint 自己的文档。

它解决的痛点是:过去你要自己积累一份“AI 腔调词表”,当团队里有人粘贴模型输出时,靠提醒和纪律来约束。现在你把这个词表和句式模式交给机器,让它在 CI 或编辑器里自动提示。

它当然也不能解决所有问题,比如大模型生成的内容可能在逻辑上完全错误,但风格上毫无破绽,那是语义理解层的任务,不是风格检查的边界。这一点要清楚:Vale-LLM-slop 不会替你做事实核查,它只负责把那些“听起来很糟糕但语法完全正确”的句子标出来。

3. 环境准备与前置条件

项目类型决定了环境版本,这里不追新版本号,以“能跑通、能扩展”为原则。下面这些步骤在 macOS 和 Linux 上都适用,Windows 用户建议在 WSL 里操作。

3.1 安装 Vale

Vale 的官方文档一直在更新安装方式,最稳妥的两个安装渠道是 Homebrew 和直接下载二进制包。

使用 Homebrew 安装:

brew install vale

安装完成后验证:

vale --version

输出类似:

vale version v3.x.x

如果提示找不到命令,检查一下 PATH 配置,Homebrew 默认安装位置一般不会出现问题。

也可以使用官方提供的预编译二进制。去 GitHub Releases 页面找到对应平台的压缩包,解压后把可执行文件放置到系统 PATH 目录,例如/usr/local/bin。

3.2 获取 LLM-slop 风格规则

Vale-LLM-slop 通常是作为 Vale 的 styles 目录内容存在。获取方式有两种:一是直接克隆或下载对应的规则仓库,二是自己手动创建规则文件。这部分请你以项目仓库的实际 README 为准,常见做法是把规则文件复制到项目的.vale/styles/目录:

mkdir -p .vale/styles # 将下载下来的规则目录放到 styles 下

如果你暂时无法获取到该项目的完整规则集,也可以先照着下一节的思路,用最少配置注册一个自定义规则,把这条链路跑通。Vale 的价值在于规则可扩展,最终你会希望用自己团队见过的高频“AI 腔”表达式去填充规则集。

4. 最小配置跑通

4.1 创建 .vale.ini

Vale 通过.vale.ini配置文件声明 styles 路径、检查的文件类型和要启用的规则集。在项目根目录创建:

# .vale.ini StylesPath = .vale/styles MinAlertLevel = warning [*.md] BasedOnStyles = Vale, LLMSlop

关键字段说明:

配置项作用
StylesPath指定规则目录的路径,Vale 会从这里读取所有 style 子目录
MinAlertLevel最低告警级别,可选suggestion、warning、error
BasedOnStyles当前文件类型要启用哪些规则包
[*.md]声明规则应用于 Markdown 文件;你可以改成[*.{md,rst,adoc}]

4.2 第一个 demo 文件

写一个带有典型 AI 腔调的 Markdown 文件:

# Demo In today's fast-paced world, it is important to note that APIs play a crucial role in modern software architecture. Moreover, robust error handling remains an essential component in ensuring system reliability. Furthermore, as an AI language model, I would like to emphasize that developers should always test their code before deployment.

注意,我不建议你在实际文档里写这种话,这里只是为了验证 linter 是否生效。

运行:

vale demo.md

预期会得到类似下面的告警:

demo.md:3:1: warning: Avoid using 'In today's fast-paced world' (LLMSlop.Clichés) demo.md:3:19: warning: Avoid using 'it is important to note that' (LLMSlop.RedundantPhrases) demo.md:4:84: warning: Avoid using 'Moreover' (LLMSlop.TransitionOveruse)

看到这类输出,说明链路已经通了。Vale 会告诉你具体位置、命中的规则,以及所属规则文件。

5. 运行与效果验证

5.1 运行命令

最小验证目标是:命令能跑、规则能命中、告警级别能控制。

vale .vale/styles/README.md

如果你只有文项目录,可以跑:

vale .

Vale 会自动按.vale.ini里配置的文件类型过滤。

5.2 输出解读

Vale 默认输出格式类似:

docs/api.md:12:3: warning: Avoid using 'delve into' (LLMSlop.Clichés)

字段分别为:文件路径、行号、列号、告警级别、告警详情和规则来源。

在 CI 或脚本里,更推荐使用--output参数指定结构化输出:

vale --output=JSON docs/

JSON 输出可以很方便地和测试报告、质量门禁系统对接。如果你希望严格阻止低质量文案合入主分支,可以把MinAlertLevel提到error,同时把 Vale 的退出码作为 CI 判断条件。

5.3 在文件内忽略某些规则

实际写作中,总有些词是有意使用的。Vale 支持在 Markdown 里通过注释语法临时忽略规则:

<!-- vale LLMSlop.Clichés = NO --> The system will unlock the full potential of the API. <!-- vale LLMSlop.Clichés = YES -->

这样可以避免在合理语境中被误报。不过要提醒一点:临时豁免如果太多,规则就会失效。团队使用时应控制豁免数量,而不是把所有告警都静音掉。

6. 定制你的 LLM slop 检测规则

如果你拿到的规则包不够全,或者团队里积累了新的“AI 腔”表达,完全可以自己写 Vale 规则。

6.1 词汇级检测

Vale 的existence扩展是最常用的规则类型,用于检测某个 token 是否出现。比如要禁止“delve”这类词:

# .vale/styles/LLMSlop/Clichés.yml extends: existence message: "Avoid using '%s' in content." ignorecase: true level: warning tokens: - delve - unlock the full potential - it is important to note that - in today's fast-paced world

用法说明:

  • extends: existence表示这是存在性检测
  • tokens是一个列表,每个 token 会独立匹配
  • ignorecase: true会忽略大小写,能覆盖句首大写情况

6.2 句式级检测

如果你想把“As an AI language model”这类多词模板也检测出来,其实也在tokens里覆盖即可。但对于需要更精细匹配的场景,比如检查连续三句中是否使用了过多被动语态,可以换成occurrence规则:

# .vale/styles/LLMSlop/PassiveOveruse.yml extends: occurrence message: "More than 3 occurrences of '%s'." scope: sentence max: 3 token: '\b(?:is|are|was|were)\s+\w+ed\b'

这个规则会在一个句子里统计is done、are built这类被动结构的数量,超过阈值就告警。这里用到的是正则表达式匹配,Vale 底层的正则语法与 RE2 基本一致,能用,但别写太复杂的回溯表达式。

6.3 结构化文档提示

除了正文,Vale 还能检查 Markdown 文档的小标题结构。可以写规则判断标题是否以“Introduction”“Conclusion”这类宽泛名词开头。虽然这类规则有误报风险,但如果你发现团队里的 AI 生成文档总喜欢用“Introduction”做章节名,它也是一个可落地的约束。

定制规则时,尽量做到“小规则、准命中”,不要把十几个表达堆进一条规则里。每条规则最好只盯一类问题,这样在豁免、调级和追踪时都更清晰。

7. 集成到编辑器与 CI

7.1 VS Code / Vim 集成

Vale 社区为编辑器提供了插件,体验和 LSP 类似:打开文件时,问题行下面会出现波浪线,鼠标悬停即可看到告警详情。

  • VS Code:安装“Vale”扩展,在使用前先配置好项目根目录的.vale.ini
  • Vim/Neovim:可以通过异步 lint 插件接入 Vale,例如把vale加入ale或null-ls的 linter 列表

编辑器的价值在于即时反馈:你不用等到提交时才被 CI 拦下,而是在写的时候就意识到这个问题。建议在团队里先让编辑检查作为辅助提示,等大家对规则集有共识后,再把它提升为 CI 门禁。

7.2 CI 接入

下面是一个 GitHub Actions 用例,在每次修改 Markdown 文档时触发检查:

name: prose-lint on: pull_request: paths: - '**.md' jobs: vale: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install Vale run: | sudo apt-get update sudo apt-get install -y jq # 请以 Vale 最新安装说明为准 # ... vale --version - name: Run Vale run: vale . --output=JSON > vale-output.json || true - name: Check issues run: | jq -e '.files | to_entries[] | select(.value|length > 0)' vale-output.json

这段示例只是为了说明接入思路。实际 CI 脚本要按 Vale 官方当前推荐的安装方式来写。核心判断是:用 Vale 的退出码和结构化输出做质量门禁,比在群里反复提醒更可靠。

8. 常见问题与排查思路

问题现象可能原因排查方式解决方案
运行vale找不到命令安装路径不在 PATH 里which vale查看可执行文件位置将 Vale 所在目录加入 PATH,或用绝对路径执行
提示Found .vale.ini but no styles path specifiedStylesPath路径配置错误检查.vale/目录是否存在在.vale.ini中把StylesPath指到正确目录
规则不生效BasedOnStyles没写规则包名查看.vale/styles/下的目录名确认规则包目录名与BasedOnStyles完全一致
LLM-slop 规则误报正常词汇词表过宽,命中业务术语查看告警详情,判断是否合理在文档中用 Vale 注释豁免,或删除 tokens 中的误报词
CI 中 Vale 退出码非 0 导致构建失败MinAlertLevel过高或存在高等级告警查看 JSON 输出的告警级别调整MinAlertLevel,或者先修复告警再合并
正则规则性能差、检查慢正则过于复杂用简单的 token 列表替代复杂正则把existence的 tokens 写得更直接

9. 最佳实践与工程建议

如果只是把 Vale-LLM-slop 装上、跑一遍、看到告警就完事,那它带来的价值会非常有限。真正把它变成团队质量工具,下面这些建议值得考虑。

规则集要跟随团队写作习惯演进。LLM-slop 的词表不是固定的,今天模型的新版本可能会换一套常用连接词。建议团队每季度抽一次最近新增的文档,把人工 reviewers 的反馈转成新规则,比如这周某个人又在文档里写了“harness the power of”,那就把它加进 tokens。规则是活文档,不是一次性配置。

先建议、后警告、再门禁。不要第一天就把 Vale 的MinAlertLevel设成error,否则历史文档会冒出一堆红色告警,大家会直接忽略它。更好的方式是先保持warning,收集两周的运行数据,再逐条决定哪些规则要升级为error,哪些规则要删除。

禁止批量豁免历史文档。有人会在接入 Vale 时,直接给旧文档全部加<!-- vale off -->。这不是不行,但会让一个本来能自动化质量检查的流程退化成“假装检查”。更推荐的做法是:新文档强制遵守新规则,旧文档按优先级逐步清理。

把 Vale 和 LLM 输出流程结合起来。如果你团队里有人用 LLM 生成初稿,惯例可以定为:生成后立即跑一次vale,把明显套话改掉,再交给人工编辑。这样既保留了 LLM 的产出速度,又不会让“AI 腔”直接进入仓库。

留意 Vale 版本的更新。Vale 自身也在迭代,新版可能调整配置格式或命令参数。升级前最好在测试分支跑一遍回归,确认.vale.ini和自定义规则还都兼容。

在散文质量这件事上,人的判断力仍然不可替代。Vale-LLM-slop 能拦截的,只是那些机器可以量化的模式;但它帮团队省下来的注意力,可以留给真正重要的内容判断:这段文档的逻辑是否自洽,这个 API 的例子是否真实,这个架构决策的理由是否站得住脚。把这些事留给人类,把“delve”这类套路词留给机器,这才是 Linter 该有的分工。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询