Skip to main content
Glama

paeg-lang-style

Python License: MIT Tests PRs Welcome

Chinese | English


What This Is

paeg-lang-style is a Chinese language standards module — three-layer architecture (user requirements):

Layer

Capability

Core Files

Grammar rule constraints (most important)

Lexical/syntactic/punctuation rules as system prompts, directing the LLM to use complete words, complete syntax, and sufficient adverbials — works for anyone

rule_registry.py + prompts/builder.py

Forbidden-word fallback

Dynamically maintained forbidden-word lexicon (AI-speak/empty buzzwords/fake empathy/cheap encouragement/internet slang), a safety net when the LLM disobeys

forbidden.py

Rewriting script

LLM output post-processing: detect rule hits → feedback with rule IDs → multi-round Self-Refine rewriting

refiner.py + gate.py

Originated from the PAEG educational agent (v0.12-v0.71 iterations), refactored into a zero-host-dependency standalone plugin — any Python project can integrate it.

Core Features

  • Extensible rule set: rules externalized to data/rules.json; appending hot-loads them (RuleRegistry)

  • General principles direct the LLM: lexical completeness/syntactic completeness/sufficient-adverbial principles let the LLM generalize rather than memorize word-by-word (avoiding the narrowness of "only optimizing 倦 into 疲倦")

  • Deterministic fallback: enumeration-layer rules ("我在这里听着你。"→"我就在这里听你说说。") guard against LLM disobedience

  • Rule-ID feedback loop: rewrite feedback carries "violates #rule-lx-001", forming a rule-generation-feedback loop

  • Dynamic forbidden-word lexicon: runtime add/remove + external JSON hot-loading

  • Injection-based design: chat_fn is force-injected — plug in your own LLM call, zero host coupling

  • Three profile tiers: general / teaching / confessional — assemble system prompts by scenario

  • AI-taste detection: 5-dimensional signals — sentence-length variance/transition-word density/three-part structure/dashes/paragraph symmetry

  • 8+ grammar rules: GB/T 15834 punctuation standards + six categories of faulty sentences + teaching language standards

  • 75 tests all green + 20 behavioral consistency checks (string-equal vs. the original PAEG implementation)

Installation

# 方式 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")

Requires Python 3.9+. Zero third-party runtime dependencies.

Integrating as an MCP Server (install and use directly, just like MCP)

Accessibility standard (§3.109): after pip install in any project, declare it in the MCP client config to integrate — zero code bridge, zero host dependency.

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

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

MCP client config declaration (e.g. 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"
    }
  }
}

Exposed MCP tools (7):

Tool Name

Function

read/write

normalize_text

Text language-standards gate (L0 rules + L2 rewriting)

read

language_policy_check

AI-taste detection + forbidden-word hit report

read

forbidden_words

Dynamic forbidden-word lexicon management (add/remove/query)

write

check_grammar

Grammar check (8 rule categories)

read

check_ai_taste

AI-taste 5-dimensional signals

read

build_style_prompt

System prompt assembly (works for anyone)

read

list_rules

Extensible rule set listing

read

Quick Start

Three steps: install → assemble the prompt → process the output.

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)
# → "我们把这个时代里的每一个孩子,把他们的潜能一步步唤起。"

Table of Contents

Core Concepts

Three-layer architecture + rule-set data model — extensibility runs through all three places: rule definition/detection/prompt generation:

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 data model (Rule — extensible via external 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" (general-principle layer): prompt_block is assembled into the system prompt, directing the LLM to generalize — "any single-character adjective expressing state/feeling must be expanded to its full two-character form (倦/乏/沉/累/苦/慌/虚/弱/低/烦/闷/困/急/乱)". The LLM generalizes to unlisted words on its own, rather than only fixing "倦→疲倦".

  • type: "explicit" (enumeration layer): pattern + replacement deterministic fallback — the last line of defense when the LLM disobeys.

External Project Integration Guide

User requirement: any project/agent that wants to use our grammar rules module — how?

Scenario A: Only want "grammar rule constraints" (system prompt)

from paeg_lang_style import RuleRegistry

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

The rule fragments returned by build_prompt(profile) (lexical-completeness principle/syntactic-completeness principle/sufficient-adverbial principle/punctuation standards) can be concatenated directly into your LLM system prompt. This is the essence of "directing the LLM to use complete words" — no dependency on our rewriter.

Scenario B: Want to use the "rewriting script" to process LLM output

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)                    # 病句/违禁词确定性修正

Scenario C: Want to use the "forbidden-word lexicon"

from paeg_lang_style import ForbiddenWords

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

Scenario D: Want to extend the rules (extensibility)

Edit data/rules.json and append a rule — it hot-loads:

{
  "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()             # 每次调用前检查

Scenario E: Full integration (including the rule-ID feedback loop)

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)

Extensibility

Extension Point

Method

Mechanism

Grammar rules

Edit data/rules.json to append a Rule

RuleRegistry.load() merges + watch() hot-reload + PAEG_RULES_PATH env var overrides the path

Forbidden words

ForbiddenWords.load_json("custom.json") / add() / remove()

Runtime dynamic maintenance

Corpus

Replace data/weil_corpus.json with a neutral corpus

corpus_path parameter at construction

Profiles

Add profile_tags when adding rules

build_prompt(profile) filters by scenario

LLM backend

Inject any chat_fn

Force-injected, zero host coupling

Rule-ID contract

Rule id is stable, referenced in feedback

Rule-generation-feedback loop, convenient for telemetry

Maintainability

  • Zero host dependency: imports no host project modules, independently testable

  • Legacy API compatibility: rules.py/rules_enhanced.py kept as thin wrappers, backward compatible

  • 75 tests: full coverage of rule-set loading/hot-reload/detection/assembly/user extension/corruption tolerance

  • Behavioral consistency: 20 samples string-equal vs. the original PAEG implementation (zero drift)

  • Corruption tolerance: keeps the previous rule set when JSON is corrupted — never "runs empty"

  • Anti-bloat: token_budget controls system prompt length (default 800)

  • Clear separation of modes: general-principle layer (directs the LLM) vs. enumeration layer (deterministic fallback) with distinct responsibilities

Built-in Grammar Rules

ID

Type

Category

Rule

Trigger Pattern

Correction

rule-lx-general-001

general

lexical

Lexical completeness

Single-character state words (倦/乏/沉/累/苦/慌/虚/弱/低/烦/闷/困/急/乱)

Expand to full two-character form

rule-sx-general-001

general

syntactic

Syntactic completeness

Subject-verb-object/verb-object/preposition/compound sentences

All components present

rule-sx-general-002

general

syntactic

Sufficient adverbials

Short sentences starting with a verb/lone single verbs

Add time/place/manner/condition/object/purpose adverbials

rule-pn-general-001

general

punctuation

Punctuation standards (GB/T 15834)

Enumeration comma vs. comma/colon after 说

Punctuation standards

rule-lx-001

enumeration

lexical

倦→疲倦

觉得倦了|感到倦|已倦

Deterministic replacement

rule-lx-002

enumeration

lexical

乏→疲乏

的乏($|[,。;])

Deterministic replacement

rule-lx-003

enumeration

lexical

道出→说出来

道出

Deterministic replacement

rule-lx-004

enumeration

lexical

探知→探索并了解

探知

Deterministic replacement

rule-sx-001~004

enumeration

syntactic

"听着你" dangling

(我在这里|在这里|我)?听着你 + sentence end

听你说说

rule-sx-005

enumeration

syntactic

Dangling object

与你探讨$ etc.

Add object

rule-sx-006

enumeration

syntactic

Verb-object collocation

带着(重量|分量)

有很重的分量

rule-sx-007

enumeration

syntactic

Translationese redundancy

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

Say the verb directly

rule-pn-001

enumeration

punctuation

Comma after 说

说:"

Use a comma instead

Sufficient-adverbial principle details (rule-sx-general-002, user-added):

Every action/judgment should be clearly qualified with sufficient adverbials — time, place, manner, condition, object, purpose. "复习单词。" → "你可以在每天睡前用十分钟复习单词。" "使用这个软件。" → "你可以在每天固定的时间使用这个软件。"

Forbidden-Word Lexicon

Category

Examples

AI-speak clichés

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

Empty buzzwords

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

Fake-empathy verbs

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

Cheap encouragement

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

Low-grade internet slang

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

Empty praise adjectives

深刻 / 全面 / 系统 / 本质

How to extend: ForbiddenWords().load_json("path.json") — JSON structure {"extra_forbidden": [...], "ai_tells_extra": [...]}.

API Reference

RuleRegistry

Method

Signature

Description

all()

() -> list[Rule]

All rules

by_id(id)

(str) -> Rule|None

Look up a rule by ID

add_rule(rule)

(dict) -> bool

Add at runtime (same ID overrides built-in)

remove_rule(id)

(str) -> bool

Remove at runtime

load(path)

(str|None) -> int

Merge external JSON (hot-load)

watch(path)

(str|None) -> None

mtime watch

check_reload()

() -> bool

Check and reload

detect(text, profile)

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

Detect hit rules

apply_explicit(text, profile)

(str, str|None) -> str

Deterministic replacement

build_prompt(profile, token_budget)

(str, int) -> str

Assemble system prompt

LanguageRefiner / make_refiner

Method

Signature

Description

make_refiner(chat_fn, llm, corpus_path)

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

Factory (chat_fn required)

refine(text, context, max_rounds)

(str, str, int) -> str

Multi-round Self-Refine rewriting

check_grammar(text)

(str) -> list

Grammar check

detect_ai_tells(text)

(str) -> list

Forbidden-word hits

detect_ai_taste_signals(text)

(str) -> AITasteSignals

AI-taste signals

gate_content / gate_short

Function

Signature

Description

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

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

L0 rules + L2 rewriting

gate_short(text, context, refiner, polish_fn)

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

Short-text fast path (L0 only)

ForbiddenWords

Method

Signature

Description

add(word) / remove(word)

(str) -> bool

Runtime add/remove

load_json(path)

(str|None) -> int

Merge external lexicon

detect(text)

(str) -> list

List of hit words

detect_count(text)

(str) -> int

Total hit count

get_style_prompt

Parameter

Description

"all"

Full language-style prompt

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

Segments

["weil", "syntax"]

Multi-segment concatenation

Configuration Reference

Environment Variables

Variable

Default

Description

PAEG_RULES_PATH

src/paeg_lang_style/data/rules.json

Rule-set path override

data/ Files

File

Purpose

Extensible

data/rules.json

Grammar rule set

Yes, append to hot-load

data/forbidden_words.json

Forbidden-word lexicon

Yes, dynamic maintenance

data/weil_corpus.json

Corpus few-shot

Yes, replaceable

Architecture Design

宿主系统(任何 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 / 语料)

Integration with the PAEG Main Project

The PAEG educational agent integrates through the single adapter layer infra/lang_plugin_bridge.py (R18/R20 zero-breakage iron law):

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

See docs/integration_paeg.md for details.

Testing

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

Contribution Guide

Contributions welcome! Please read CONTRIBUTING.md (to be created) to learn about:

  • Add new grammar rules: edit data/rules.json to append a Rule (with tests)

  • Add forbidden words: ForbiddenWords.load_json or submit a PR directly to the built-in lexicon

  • Code style: follow the existing module structure + comment conventions

Changelog

See CHANGELOG.md for details.

Acknowledgements

  • PAEG Education Agent (v0.12-v0.71 iterations) — this plugin is extracted from its language specification module

  • LanguageTool — declarative rule engine paradigm (dev.languagetool.org)

  • textstat — readability measurement paradigm (github.com/textstat/textstat)

  • GB/T 15834-2011《Usage of Punctuation Marks》 — national standard for punctuation rules

  • Agent Skills Standard — progressive disclosure paradigm (agentskills.io)

License

MIT © 2026 PAEG Team — see the LICENSE file for details.

-
license - not tested
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • Prose linter + AI-slop detector: weasel words, passive voice, hedging, and research-cited AI tells

  • Deterministic validation for AI-generated artifacts: JSON Schema, OpenAPI response, SQL syntax.

  • Lints + auto-fixes how AI coding agents discover any new product. 24 rules, 6 tools, score 0-100.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Golden2002/paeg-lang-style-plugin'

If you have feedback or need assistance with the MCP directory API, please join our Discord server