Skip to main content
Glama

paeg-lang-style

Python License: MIT Tests PRs Welcome

中文 | English


Что это такое

paeg-lang-style — это модуль норм китайского языка — трёхуровневая архитектура (требование пользователя):

Уровень

Возможности

Основные файлы

Ограничение грамматическими правилами (самое важное)

Лексические/синтаксические/пунктуационные правила как системный промпт, управляющий LLM: полные слова, полный синтаксис, достаточные обстоятельства — кто бы ни использовал, всё собирается

rule_registry.py + prompts/builder.py

Запасной вариант — запрещённые слова

Динамически поддерживаемый словарь запрещённых слов (AI-штампы/пустые громкие слова/псевдоэмпатия/дешёвое поощрение/интернет-сленг) — нижняя граница на случай непослушания LLM

forbidden.py

Скрипт переписывания

Постобработка вывода LLM: обнаружение срабатывания правил → обратная связь с ID правила → многораундовое переписывание Self-Refine

refiner.py + gate.py

Происходит из образовательного агента PAEG (итерации v0.12–v0.71), переработан в независимый плагин без зависимостей от хоста — подключается к любому Python-проекту.

Related MCP server: Chinese Sensitive Words MCP Server

Ключевые возможности

  • Расширяемый набор правил: правила вынесены в data/rules.json, добавление = горячая загрузка (RuleRegistry)

  • Общие принципы управляют LLM: общие принципы лексической полноты/синтаксической полноты/достаточных обстоятельств заставляют LLM обобщать, а не запоминать слово за словом (избегая узости «оптимизировать только 倦→疲倦»)

  • Детерминированный запасной вариант: правила уровня перечисления («我在这里听着你。」→「我就在这里听你说说。」) на случай непослушания LLM

  • Замкнутый цикл обратной связи по ID правил: обратная связь при переписывании содержит «нарушено #rule-lx-001», образуя цикл правило-генерация-обратная связь

  • Динамический словарь запрещённых слов: добавление/удаление во время выполнения + горячая загрузка внешнего JSON

  • Инъекционный дизайн: chat_fn принудительно инъецируется — подключаете собственный вызов LLM, нулевая связность с хостом

  • Три профиля: general / teaching / confessional — сборка системного промпта по сценарию

  • Детекция AI-стиля: 5 сигналов — вариативность длины предложений/плотность переходных слов/трёхчастная структура/тире/симметрия абзацев

  • 8+ грамматических правил: стандарт пунктуации GB/T 15834 + шесть типов ошибочных предложений + нормы педагогической речи

  • 75 тестов все зелёные + 20 фрагментов поведенческой согласованности (строковое равенство с исходной реализацией PAEG)

Установка

# 方式 1:pip 安装(推荐)
pip install -e /path/to/paeg-lang-style-plugin

# 方式 2:直接引用(零安装)
# 把 src/ 加入 sys.path 即可
import sys
sys.path.insert(0, "/path/to/paeg-lang-style-plugin/src")

Требуется Python 3.9+. Ноль сторонних зависимостей во время выполнения.

Подключение в качестве MCP-сервера (установка как MCP — сразу готово к использованию)

Стандарт доступности (§3.109): любой проект после pip install объявляет конфигурацию в MCP-клиенте и подключается — нулевой код-мост, нулевая зависимость от хоста.

# 方式 1:console_scripts 入口(pip install 后)
paeg-lang-style-mcp

# 方式 2:python -m 入口(源码运行)
python -m paeg_lang_style.mcp_server

Объявление конфигурации MCP-клиента (например, config/mcp_servers.json):

{
  "mcpServers": {
    "paeg-lang-style": {
      "command": "python",
      "args": ["-m", "paeg_lang_style.mcp_server"],
      "cwd": "D:/wbo-workspace/paeg_project/paeg-lang-style-plugin"
    }
  }
}

Предоставляемые MCP-инструменты (7 шт.):

Имя инструмента

Функция

read/write

normalize_text

Шлюз норм языка текста (правила L0 + переписывание L2)

read

language_policy_check

Детекция AI-стиля + отчёт о срабатывании запрещённых слов

read

forbidden_words

Управление динамическим словарём запрещённых слов (добавление/удаление/просмотр)

write

check_grammar

Проверка грамматики (8 категорий правил)

read

check_ai_taste

5 сигналов AI-стиля

read

build_style_prompt

Сборка системного промпта (кто бы ни использовал, всё собирается)

read

list_rules

Список расширяемого набора правил

read

Быстрый старт

Три шага: установка → сборка промпта → обработка вывода.

from paeg_lang_style import RuleRegistry, make_refiner, gate_content

# Step 1: 语法规则拼进你的系统提示词(谁用都拼)
system_prompt = "你是教育智能体,负责讲解数学概念。"
system_prompt += RuleRegistry().build_prompt("teaching")   # 通则层指挥 LLM

# Step 2: 注入你的 LLM 调用(改写脚本)
def my_llm(system, user, max_tokens=800, **kw):
    return call_my_llm_api(system, user, max_tokens=max_tokens)

refiner = make_refiner(chat_fn=my_llm)

# Step 3: LLM 输出后处理(L0 规则 + L2 重写)
raw_output = "总的来说,让我们一起赋能这个时代!"
clean = gate_content(raw_output, refiner=refiner)
# → "我们把这个时代里的每一个孩子,把他们的潜能一步步唤起。"

Содержание

Ключевые концепции

Трёхуровневая архитектура + модель данных набора правил — расширяемость пронизывает три места: определение правил/детекцию/генерацию промпта:

graph LR
    A[LLM 生成文本] --> B[gate_content 守门]
    B --> C{L0 规则检测}
    C -->|命中列举层| D[确定性替换<br/>听着你→听你说说]
    C -->|通则触发| E[L2 refiner.refine<br/>chat_fn 注入 LLM]
    E --> F[反馈带规则 ID<br/>违反 #rule-lx-001]
    F --> G[多轮 Self-Refine]
    D --> H[输出]
    G --> H
    H --> I[收口: 规则再跑一遍]

Модель данных правила (Rule — расширяется внешним JSON):

{
  "id": "rule-lx-general-001",
  "type": "general",
  "category": "lexical",
  "pattern": "(倦|乏|沉|累|苦|慌|虚|弱|低|烦|闷|困|急|乱)",
  "replacement": null,
  "message": "存在单字状态词——应扩展为完整双字词形",
  "prompt_block": "### 词法完整通则(指挥 LLM 泛化)...",
  "severity": "high",
  "enabled": true,
  "source": "builtin",
  "profile_tags": ["general", "teaching", "confessional"]
}
  • type: "general" (уровень общих принципов): prompt_block встраивается в системный промпт, управляя обобщением LLM — «все односложные прилагательные состояния/ощущения расширяются до полной двусложной формы (倦/乏/沉/累/苦/慌/虚/弱/低/烦/闷/困/急/乱)». LLM сам обобщает на неперечисленные слова, а не только исправляет «倦→疲倦».

  • type: "explicit" (уровень перечисления): pattern + replacement — детерминированный запасной вариант — последний рубеж на случай непослушания LLM.

Руководство по подключению внешних проектов

Требование пользователя: любой проект/агент хочет использовать наш модуль грамматических правил — как это сделать?

Сценарий A: нужны только «ограничения грамматическими правилами» (системный промпт)

from paeg_lang_style import RuleRegistry

# 语法规则拼进自己的系统提示词(谁用都拼)
system = "你是我的客服机器人。"
system += RuleRegistry().build_prompt("general")   # 或 "teaching" / "confessional"

Фрагменты правил, возвращаемые build_prompt(profile) (общий принцип лексической полноты/общий принцип синтаксической полноты/общий принцип достаточных обстоятельств/нормы пунктуации), напрямую встраиваются в системный промпт вашего LLM. Это и есть суть «управления LLM в использовании полных слов» — не зависит от нашего переписывателя.

Сценарий B: нужен «скрипт переписывания» для обработки вывода LLM

from paeg_lang_style import make_refiner, gate_content

# 注入你自己的 LLM 调用包装(chat_fn 强制注入,零宿主耦合)
def my_chat(system, user, max_tokens=800, **kw):
    return call_your_llm(system, user, max_tokens=max_tokens)

refiner = make_refiner(chat_fn=my_chat)
clean = gate_content(your_llm_output, refiner=refiner)   # L0 规则 + L2 重写
# 纯规则(不调 LLM):
clean = gate_content(your_llm_output)                    # 病句/违禁词确定性修正

Сценарий C: нужен «словарь запрещённых слов»

from paeg_lang_style import ForbiddenWords

fb = ForbiddenWords()                     # 内置违禁词(AI 腔/空洞大词/伪共情/网络用语)
fb.load_json("my_words.json")             # 合并你自己的词库(动态扩充)
fb.add("你们公司的禁词")                  # 运行时新增
hits = fb.detect(text)                    # → ["禁词1", "禁词2"]

Сценарий D: нужно расширить правила (расширяемость)

Отредактируйте data/rules.json, добавьте одно правило — и оно горячо загрузится:

{
  "rules": [
    {
      "id": "rule-my-001",
      "type": "explicit",
      "category": "lexical",
      "pattern": "你们行业的黑话",
      "replacement": "规范说法",
      "message": "这是行业黑话,应改规范",
      "severity": "medium",
      "enabled": true,
      "source": "user",
      "profile_tags": ["general"]
    }
  ]
}
reg = RuleRegistry()
reg.load("data/rules.json")    # 合并(追加即生效)
reg.watch("data/rules.json")   # mtime 变更自动热重载
reg.check_reload()             # 每次调用前检查

Сценарий E: полное подключение (включая замкнутый цикл обратной связи по ID правил)

from paeg_lang_style import RuleRegistry, make_refiner, gate_content, get_style_prompt

# 1. 系统提示词(规则 + 风格)
system = get_style_prompt("all") + "\n" + RuleRegistry().build_prompt("general")

# 2. 改写器(规则检测 → 反馈带 ID → 重写)
refiner = make_refiner(chat_fn=my_chat)

# 3. 守门(L0 规则 + L2 重写 + 收口)
final = gate_content(raw, refiner=refiner)

Расширяемость

Точка расширения

Способ

Механизм

Грамматические правила

Редактирование data/rules.json, добавление Rule

RuleRegistry.load() объединяет + watch() горячая перезагрузка + переменная окружения PAEG_RULES_PATH переопределяет путь

Запрещённые слова

ForbiddenWords.load_json("自定义.json") / add() / remove()

динамическое сопровождение во время выполнения

Корпус

Замена data/weil_corpus.json на нейтральный корпус

параметр corpus_path при конструировании

Профиль

Добавление profile_tags при добавлении правила

build_prompt(profile) фильтрует по сценарию

Бэкенд LLM

Инъекция любого chat_fn

принудительная инъекция, нулевая связность с хостом

Контракт ID правил

Стабильный id правила, ссылки в обратной связи

цикл правило-генерация-обратная связь, удобно для телеметрии

Сопровождаемость

  • Нулевая зависимость от хоста: не импортирует ни одного модуля хост-проекта, независимо тестируется

  • Совместимость со старым API: rules.py/rules_enhanced.py сохранены как тонкие обёртки, обратная совместимость

  • 75 тестов: полное покрытие загрузки набора правил/горячей перезагрузки/детекции/сборки/расширения пользователем/устойчивости к повреждениям

  • Поведенческая согласованность: 20 фрагментов — строковое равенство с исходной реализацией PAEG (нулевой дрейф)

  • Устойчивость к повреждениям: при повреждении JSON сохраняется предыдущий набор правил, никогда не «запуск с пустотой»

  • Защита от раздувания: token_budget контролирует длину системного промпта (по умолчанию 800)

  • Чёткая модель: разделение обязанностей уровня общих принципов (управление LLM) и уровня перечисления (детерминированный запасной вариант)

Встроенные грамматические правила

ID

Тип

Категория

Правило

Триггерный шаблон

Исправление

rule-lx-general-001

общий принцип

лексика

лексическая полнота

односложные слова состояния (倦/乏/沉/累/苦/慌/虚/弱/低/烦/闷/困/急/乱)

расширение до полной двусложной формы

rule-sx-general-001

общий принцип

синтаксис

синтаксическая полнота

подлежащее-сказуемое-дополнение/глагол-дополнение/предлог/сложное предложение

все компоненты на месте

rule-sx-general-002

общий принцип

синтаксис

достаточные обстоятельства

короткие предложения, начинающиеся с глагола/одинокие одиночные глаголы

дополнить обстоятельства времени/места/способа/условия/объекта/цели

rule-pn-general-001

общий принцип

пунктуация

нормы пунктуации (GB/T 15834)

顿号 против 逗号/двоеточие после «сказал»

нормы пунктуации

rule-lx-001

перечисление

лексика

倦→疲倦

觉得倦了|感到倦|已倦

детерминированная замена

rule-lx-002

перечисление

лексика

乏→疲乏

的乏($|[,。;])

детерминированная замена

rule-lx-003

перечисление

лексика

道出→说出来

道出

детерминированная замена

rule-lx-004

перечисление

лексика

探知→探索并了解

探知

детерминированная замена

rule-sx-001~004

перечисление

синтаксис

«слушать тебя» без дополнения

(我在这里|在这里|我)?听着你 + конец предложения

听你说说

rule-sx-005

перечисление

синтаксис

висячее дополнение

与你探讨$ и т.п.

дополнить дополнение

rule-sx-006

перечисление

синтаксис

сочетание глагол-дополнение

带着(重量|分量)

有很重的分量

rule-sx-007

перечисление

синтаксис

избыточность переводческого стиля

进行(一个)?(分析|讨论|思考)

сказать глагол напрямую

rule-pn-001

перечисление

пунктуация

запятая после «сказал»

说:"

заменить на запятую

Подробности общего принципа достаточных обстоятельств (rule-sx-general-002, добавлено пользователем):

Каждое действие/суждение поясняется достаточными обстоятельствами — время, место, способ, условие, объект, цель. «复习单词。」 → «你可以在每天睡前用十分钟复习单词。」 «使用这个软件。」 → «你可以在每天固定的时间使用这个软件。」

Словарь запрещённых слов

Категория

Примеры

AI-штампы

总的来说 / 综上所述 / 值得注意的是 / 让我们一起

Пустые громкие слова

赋能 / 点亮 / 激活 / 重塑 / 升级 / 全方位

Псевдоэмпатические глаголы

接住(情绪)/ 托住 / 兜住 / 我懂你 / 心疼你

Дешёвое поощрение

加油 / 你真棒 / 你一定可以

Низкопробный интернет-сленг

yyds / 绝绝子 / 栓Q / 破防 / 内卷 / 躺平 / 宝子

Пустые хвалебные прилагательные

深刻 / 全面 / 系统 / 本质

Способ расширения: ForbiddenWords().load_json("path.json") — структура JSON {"extra_forbidden": [...], "ai_tells_extra": [...]}.

Справочник API

RuleRegistry

Метод

Сигнатура

Описание

all()

() -> list[Rule]

все правила

by_id(id)

(str) -> Rule|None

поиск правила по ID

add_rule(rule)

(dict) -> bool

добавление во время выполнения (тот же ID переопределяет встроенное)

remove_rule(id)

(str) -> bool

удаление во время выполнения

load(path)

(str|None) -> int

объединение внешнего JSON (горячая загрузка)

watch(path)

(str|None) -> None

отслеживание mtime

check_reload()

() -> bool

проверка и перезагрузка

detect(text, profile)

(str, str|None) -> list[Rule]

детекция сработавших правил

apply_explicit(text, profile)

(str, str|None) -> str

детерминированная замена

build_prompt(profile, token_budget)

(str, int) -> str

сборка системного промпта

LanguageRefiner / make_refiner

Метод

Сигнатура

Описание

make_refiner(chat_fn, llm, corpus_path)

(*, chat_fn, ...) -> LanguageRefiner

фабрика (chat_fn обязателен)

refine(text, context, max_rounds)

(str, str, int) -> str

многораундовое переписывание Self-Refine

check_grammar(text)

(str) -> list

проверка грамматики

detect_ai_tells(text)

(str) -> list

срабатывание запрещённых слов

detect_ai_taste_signals(text)

(str) -> AITasteSignals

сигналы AI-стиля

gate_content / gate_short

Функция

Сигнатура

Описание

gate_content(text, context, apply_l2, refiner, polish_fn)

(str, str, bool, refiner|None, fn|None) -> str

правила L0 + переписывание L2

gate_short(text, context, refiner, polish_fn)

(str, str, ...) -> str

быстрый путь для коротких текстов (только L0)

ForbiddenWords

Метод

Сигнатура

Описание

add(word) / remove(word)

(str) -> bool

добавление/удаление во время выполнения

load_json(path)

(str|None) -> int

объединение внешнего словаря

detect(text)

(str) -> list

список сработавших слов

detect_count(text)

(str) -> int

общее число срабатываний

get_style_prompt

Параметр

Описание

"all"

полный промпт языкового стиля

"weil" / "lexicon" / "syntax" / "forbidden"

по секциям

["weil", "syntax"]

объединение нескольких секций

Справочник конфигурации

Переменные окружения

Переменная

Значение по умолчанию

Описание

PAEG_RULES_PATH

src/paeg_lang_style/data/rules.json

переопределение пути к набору правил

Файлы data/

Файл

Назначение

Расширяемость

data/rules.json

набор грамматических правил

да, добавление = горячая загрузка

data/forbidden_words.json

словарь запрещённых слов

да, динамическое сопровождение

data/weil_corpus.json

корпус few-shot

да, можно заменить

Архитектура

宿主系统(任何 Python 项目 / 智能体)
  system_prompt += RuleRegistry().build_prompt()    <- 语法规则拼系统提示词(谁用都拼)
  gate_content(output, refiner=make_refiner(chat))  <- 输出后处理
        |
        | 零宿主依赖(不 import 宿主任何模块)
        v
paeg_lang_style(独立插件)
  +------------------+  +-----------------+  +-----------------+
  | rule_registry    |  | forbidden.py    |  | ai_taste.py     |
  | 可扩充规则集      |  | 动态违禁词库     |  | AI 味检测        |
  +--------+---------+  +--------+--------+  +--------+--------+
           |                    |                     |
           v                    v                     v
  +-----------------------------------------------------------+
  | refiner.py(改写脚本:chat_fn 注入 + 规则 ID 闭环)           |
  | gate.py(守门入口:L0+L2 编排)                              |
  +-----------------------------------------------------------+
  data/(rules.json / forbidden_words.json / 语料)

Интеграция с основным проектом PAEG

Образовательный агент PAEG подключается через единственный адаптационный слой infra/lang_plugin_bridge.py (железное правило нулевого разрушения R18/R20):

from infra.lang_plugin_bridge import gate_content, get_style_prompt, make_refiner
# 插件挂载 → 走插件;插件未挂载 → 静默回退 PAEG 原实现(旧文件永不删除)

Подробнее см. docs/integration_paeg.md.

Тестирование

python -m pytest tests/ -q
# 75 项:规则集加载/热重载/检测/拼装/用户扩充/损坏容错 + 通则 + 充分状语 + 行为一致性

Руководство по вкладу

Приветствуется вклад! Пожалуйста, прочитайте CONTRIBUTING.md (в разработке), чтобы узнать:

  • Новые грамматические правила: отредактируйте data/rules.json и добавьте Rule (включая тесты)

  • Новые запрещённые слова: ForbiddenWords.load_json или отправьте PR во встроенный словарь

  • Стиль кода: следуйте существующей структуре модулей + правилам комментирования

Журнал изменений

Подробнее см. CHANGELOG.md.

Благодарности

  • PAEG 教育智能体 (итерации v0.12-v0.71) — этот плагин извлечён из его модуля языковых норм

  • LanguageTool — парадигма декларативного движка правил (dev.languagetool.org)

  • textstat — парадигма измерения читабельности (github.com/textstat/textstat)

  • GB/T 15834-2011《标点符号用法》 — национальный стандарт правил пунктуации

  • Стандарт Agent Skills — парадигма прогрессивного раскрытия (agentskills.io)

Лицензия

MIT © 2026 PAEG Team — подробнее см. файл LICENSE.

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    B
    maintenance
    Local-first toolkit with 16 tools for Chinese web-novel (网文) authors: style baselines, foreshadowing and plot-thread tracking, continuity & OOC audits, keyword and sentence-pattern analysis, and offline semantic search. No API key, no network — everything runs on your machine.
    19
    986 npm
    22
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Provides AI models with tools to proofread and format Chinese text before delivery, covering typos, punctuation, casing, spacing, and platform-specific character limits. It runs as a zero-dependency MCP service so the model checks and fixes its own Chinese writing automatically.
    4
    1
    MIT