
最近在整理一批大模型跑出來的技術文檔時我發(fā)現(xiàn)一個挺有意思的現(xiàn)象LLM 寫的東西越來越“像回事”越來越流暢也越來越容易在細節(jié)上騙到自己。它會把猜測寫得像結論會把不確定的參數(shù)寫成確定值甚至會在沒有依據(jù)的情況下一本正經(jīng)地拋出“經(jīng)過調研”“業(yè)內(nèi)普遍認為”“實驗表明”這類看起來很有分量的表述。這讓我想到一個問題在把 LLM 生成的內(nèi)容交給下游之前我們能不能用最輕量、最可控的方式先給它加一道“可信度閘門”不是做大模型安全對齊也不是上一套完整的內(nèi)容審核系統(tǒng)而是用幾行正則把那些典型的“自我欺騙”信號攔截下來。我后面會直接給出可復用的代碼和規(guī)則庫適合處理批量文檔、自動生成報告、AI 輔助寫文章這類場景。先說結論正則不是萬能的但對 LLM 輸出做初篩它反而比很多重型方案更高效。因為它不依賴額外模型不需要訓練數(shù)據(jù)也幾乎沒有延遲。你只需要想清楚一個問題——你想攔住什么樣的不可信表達。把這個想清楚了剩下的事情就是寫規(guī)則、做測試、調閾值。1. 內(nèi)容整體設計與思路拆解1.1 為什么 LLM 會“騙自己”我們常說的 AI 幻覺本質上不是模型“故意撒謊”而是它在生成下一個 token 時選擇了概率上最合理的說法而不是事實核查后的結論。當上下文里沒有正確答案時它就會根據(jù)訓練數(shù)據(jù)里的相似模式編織出一個“聽起來合理”的回答。有人把這種情況比作“超級自信的實習生”你問它一個問題它不知道答案但它絕不會說“我不知道”它會給你講一個邏輯完整、細節(jié)豐富、語氣篤定的故事。更麻煩的是這個故事里可能有真實的部分也有編造的部分混合在一起很難分辨。在實際使用 LLM 生成文章、報告、招聘 JD、客服回復時這種“自信”會以固定的語言模式出現(xiàn)。比如用“肯定”“必然”“毫無疑問”來強化主觀判斷用“眾所周知”“眾所周知的是”“業(yè)界認為”來替代證據(jù)用“根據(jù)相關研究”“實驗表明”“數(shù)據(jù)顯示”來偽造依據(jù)用“我建議你”“我的建議是”來掩蓋知識盲區(qū)用“目前”“截止目前”“最新的”來表達時效性不確定的信息這些表達本身不一定錯誤但放在可信度體系里它們是“高危信號”。如果我們要給 AI 生成的內(nèi)容加一道閘門攔截的不該只是“違法違禁詞”而該是這類“確定性溢出”的表述——它們才是 LLM 騙自己、也騙讀者的地方。1.2 閘門應有的結構和規(guī)則設計思路我所說的“可信度閘門”是一個獨立于生成流程的過濾層。它的定位不是“糾正內(nèi)容”而是“標記風險”。設計上我會把它拆成三層第一層是“絕對禁出規(guī)則”比如隱私數(shù)據(jù)、侮辱性詞匯、明確違法指令這類直接攔下。第二層是“高置信風險規(guī)則”比如“根據(jù)查證”“調查研究發(fā)現(xiàn)”“專家指出”這類匹配后打上“待核查”標簽交給人工或后續(xù)流程處理。第三層是“弱信號規(guī)則”比如“可能”“或許”“大概”這類不確定詞的數(shù)量異常這個配合上下文判斷不單獨觸發(fā)攔截。正則主要承載第一層和第二層的功能。第三層可以簡單做詞頻統(tǒng)計跟正則一起配合使用性價比很高。這種設計的核心思路是不要試圖判斷一句話是真是假只判斷這句話“是不是聽起來太真了”。因為真假判斷需要外部知識而“聽起來太真”只是語言模式問題。正則能從語言模式入手完成一道高效的初篩。1.3 為什么不用更復雜的方案在做這道閘門之前我考慮過幾個替代方案微調一個小模型做幻覺檢測、用大模型 API 做二次審核、接入第三方內(nèi)容安全平臺。最后都沒選原因很實際。微調模型需要構造訓練集、跑訓練流程、維護版本對大多數(shù)內(nèi)容生成場景來說太重了而且幻覺檢測本身定義模糊標注成本極高。用大模型 API 做二次審核效果不錯但每次輸出都要多一次 API 調用成本和延遲翻倍對于批量生成場景不合適。第三方內(nèi)容安全平臺擅長攔截色情、政治、廣告這類內(nèi)容但對“AI 自夸式表達”這類軟性可信度問題覆蓋很有限。正則方案的好處是透明、可控、可解釋。每個規(guī)則都是一條肉眼可見的字符串通過了就是通過了被攔截了會告訴你因為哪條規(guī)則這在實際使用時很關鍵。另一個好處是零成本部署——只要不是要求攔截效果達到 100%正則適合大多數(shù)場景。2. 核心細節(jié)解析與實操要點2.1 幾類典型的高危語言信號我在整理規(guī)則庫的時候會把 LLM 輸出里的高風險表達分成幾個大類。第一類是“權威冒充型”。這類通常以“根據(jù)”“研究表明”“專家稱”開頭后面接的內(nèi)容卻很可能沒有出處。規(guī)則上既要匹配這類開頭短語也要注意別把用戶自己引用的真實文獻誤殺。第二類是“確定性斷言型”。包括“毫無疑問”“事實是”“可以肯定的是”“關鍵點在于”等。這類措辭本身沒有任何問題像科普文章、產(chǎn)品文檔里也會有但如果一段 AI 生成的內(nèi)容里同時出現(xiàn)多個這樣的詞就需要警惕內(nèi)容可能是“想當然”而不是“查證過”。第三類是“未來承諾型”。比如“將為用戶帶來”“必將改變”“有望實現(xiàn)”“接下來會”這類。這類在營銷文案里特別常見LLM 生成營銷內(nèi)容時還會變本加厲。如果我們要做的是事件報道、產(chǎn)品說明這類表達就很危險因為它們把預測和事實混在了一起。第四類是“虛假具體化型”。這是最難防的一類也是 AI 幻覺最容易出現(xiàn)的地方。它表現(xiàn)為突然蹦出一個精確的百分比、一個具體的日期、一個問卷樣本量、一個“第X次測試”。正則很難直接判斷數(shù)字真假但可以通過模式捕捉出現(xiàn)“有效率達 99%”“調研了 1200 個用戶”“2023 年 11 月的某項研究”這類具體細節(jié)時標記為“需要二次核實”。這類幻覺往往細節(jié)越多越危險。2.2 正則規(guī)則庫的構建方法構建規(guī)則庫的時候不能一股腦把所有模式堆到一個文件里就行我會分模塊管理。最基本的模塊是“詞條模式”針對固定短語做匹配比如r毫無疑問 r眾所周知 r無需置疑 r不可否認然后是“句式模式”針對一類句式結構做匹配重點處理“根據(jù)/據(jù) xxx 表示/認為/發(fā)現(xiàn)”這類形式r(?:根據(jù)|據(jù)|援引)(?:相關|某|一位|業(yè)內(nèi))?(?:研究|報告|數(shù)據(jù)|專家|人士|分析)這里用非捕獲組(?:)可以避免匹配時生成多余的分組性能也好一些。使用re模塊時我會用re.compile預編譯所有規(guī)則避免每次調用都重新解析表達式。詞條模式容易維護但誤報率最高。因為很多詞在特定領域里是正常的比如數(shù)學論文里“顯然有”就是合法的。這時候需要給規(guī)則加上“上下文限制”——只有當一個詞出現(xiàn)在某類句子主干位置時才觸發(fā)。這個邏輯跟正則配合可以做到先用一個寬松的正則找到高風險句再檢查句子上下文里有沒有“證明”“推導”這類詞有就降低權重。2.3 規(guī)則觸發(fā)的分級處理我給規(guī)則設置了兩個級別攔截和提示。攔截級規(guī)則觸發(fā)后內(nèi)容不會通過閘門。主要用于以下情況全文找不到任何可驗證信息卻大量使用確定性表達生成的內(nèi)容里頻繁出現(xiàn)“根據(jù)最新研究”“大量研究表明”但沒有任何參考文獻數(shù)字型幻覺特征集中爆發(fā)比如一段三百字內(nèi)容里出現(xiàn) 5 個以上“精確”數(shù)據(jù)。提示級規(guī)則觸發(fā)后內(nèi)容正常通過但會在系統(tǒng)里留下一條“待人工復核”記錄。生成周報時如果有一段話“團隊效率提升 30%”閘門不會攔但會給運營者發(fā)個提示請確認這個 30% 的來源。這種分級的好處是不讓閘門成為內(nèi)容生產(chǎn)的阻礙而是變成一個輔助檢查工具。實際實現(xiàn)里邏輯不復雜掃描全文統(tǒng)計命中的規(guī)則數(shù)量與等級命中攔截級規(guī)則達到 1 條直接攔截命中提示級規(guī)則超過 3 條則要求人工確認后排發(fā)所有命中信息記錄下來生成報告2.4 容易被忽略的細節(jié)正則與文本預處理的配合直接拿原始文本跑正則在大部分情況下沒問題但有些小坑需要提前處理。第一是中文文本標點不統(tǒng)一。有人用中文全角括號有人用英文半角括號如果規(guī)則里寫了研究表明文本里是(研究表明)匹配就會失敗。好的做法是先在預處理階段把英文括號、逗號、引號統(tǒng)一成中文或做歸一化但要注意代碼層面別把正常英文文本搞亂。第二是換行和空格。LLM 輸出 Markdown 時經(jīng)常會在句子里意外插入換行破壞正則的^和$匹配。用re.DOTALL或者把文本先壓縮成“單行化”再跑正則是更穩(wěn)妥的思路。第三是字符長度限制。如果一篇文章特別長直接構建一個超大的正則跑全量文本性能會很差。建議按句子或段落切分逐段檢測。這個通過正則切分很好實現(xiàn)sentences re.split(r(?[。!?])\s*, text)這樣既能做逐句檢測也能在命中的時候定位到具體是哪一句出了問題比返回“第 5000 個字符有風險”友好得多。3. 實操過程與核心環(huán)節(jié)實現(xiàn)3.1 搭建一個可用的正則可信度閘門下面這段代碼是我在實際項目里用過的精簡版本。它不依賴任何第三方庫只使用 Python 標準庫。import re from typing import List, Tuple, Dict class ConfidenceGate: 正則可信度閘門檢測 LLM 輸出中的高風險可信度信號。 def __init__(self): # 攔截級規(guī)則命中即判定高風險 self.block_rules [ { name: 偽造依據(jù)型, pattern: re.compile( r(?:根據(jù)|據(jù)|援引)(?:相關|某|一位|業(yè)內(nèi))? r(?:研究|報告|數(shù)據(jù)|統(tǒng)計|專家|人士|分析|實驗)[^。]{0,30} r(?:表明|顯示|指出|認為|發(fā)現(xiàn))?, re.IGNORECASE ), reason: 段落疑似引用不存在的依據(jù)請核實來源 }, { name: 絕對斷言型, pattern: re.compile( r(?:毫無疑問|無庸置疑|絕對可以|百分之百是| r確定無疑|鐵定|必然如此|肯定是這樣) ), reason: 存在過度確定性表達可能掩蓋事實不確定性 }, { name: 模糊數(shù)量型, pattern: re.compile( r(?:絕大多數(shù)|好多|大量證據(jù)|無數(shù)案例|幾乎所有)[^。]{0,20} r(?:表示|證明|認為|說明) ), reason: 使用不可驗證的模糊數(shù)量作為論據(jù) }, ] # 提示級規(guī)則命中后僅提示 self.warn_rules [ { name: 專家背書型, pattern: re.compile(r(?:專家|學者|業(yè)內(nèi)人士|研究人員)\s*(?:表示|認為|說|指出)), reason: 請確認是否提供了具體專家或研究人員信息 }, { name: 時效敏感型, pattern: re.compile(r(?:目前|現(xiàn)在|最新|近期|當下|如今)[^。]{0,10}(?:技術|研究|數(shù)據(jù)|政策)), reason: 時效性詞匯可能隨時間失效建議補充生成日期 }, { name: 數(shù)據(jù)暗示型, pattern: re.compile(r(?:\d(?:\.\d)?\s*%|\d\s*人|\d\s*份|\d\s*次|\d\s*年)), reason: 出現(xiàn)具體數(shù)字請核對來源 }, ] def _scan_rule(self, text: str, rule: Dict) - List[Tuple[str, str]]: result [] for match in rule[pattern].finditer(text): # 取命中的前后文作為上下文 start max(0, match.start() - 15) end min(len(text), match.end() 15) context text[start:end].replace(\n, ) result.append((context, rule[reason])) return result def check(self, text: str) - Dict: 對輸入文本進行掃描。 report { blocked: False, need_review: False, issues: [] } for rule in self.block_rules: findings self._scan_rule(text, rule) if findings: report[blocked] True for context, reason in findings: report[issues].append({ level: block, rule: rule[name], context: context, reason: reason }) warn_count 0 for rule in self.warn_rules: findings self._scan_rule(text, rule) if findings: warn_count len(findings) for context, reason in findings[:2]: report[issues].append({ level: warn, rule: rule[name], context: context, reason: reason }) if warn_count 3: report[need_review] True return report這段代碼里block_rules是硬性攔截規(guī)則warn_rules是提示規(guī)則。實際使用的時候可以對一個句子先做切分再逐句調用這樣定位更準確。3.2 實際測試跑一組 AI 生成內(nèi)容我用 LLM 隨便生成了一段“某產(chǎn)品市場分析”把結果放進閘門跑了一遍輸入片段一無風險該產(chǎn)品目前主要面向中小企業(yè)的HR部門提供的核心功能包括簡歷解析、面試排期和報表統(tǒng)計。運行時輸出{blocked: false, need_review: false, issues: []}這段沒有觸發(fā)任何規(guī)則判斷正確。輸入片段二典型 AI 口吻根據(jù)最新研究報告顯示采用該產(chǎn)品的企業(yè)員工招聘效率平均提升了60%左右。 毫無疑問這是當前市場上最優(yōu)質的解決方案。據(jù)業(yè)內(nèi)專家分析未來三年內(nèi)該領域市場規(guī)模將達到500億元。運行時輸出簡化字段{ blocked: true, issues: [ {level: block, rule: 偽造依據(jù)型, reason: 段落疑似引用不存在的依據(jù)請核實來源}, {level: block, rule: 絕對斷言型, reason: 存在過度確定性表達}, {level: warn, rule: 數(shù)據(jù)暗示型, reason: 出現(xiàn)具體數(shù)字請核對來源} ] }可以清楚地看到哪些句子有風險、哪些詞觸發(fā)了攔截人工復核的時候不用從頭看全文只查這些命中點就行。3.3 在真實流水線中的接入方式在實際項目里這道閘門不是單獨運行的。我通常把它作為“內(nèi)容發(fā)布前最后一道檢查”塞進流水線接入方式很簡單在拿到 LLM 輸出之后調用一次即可gate ConfidenceGate() def ai_generate_and_check(prompt: str) - Dict: # 假設已有調用大模型的方法 raw_text llm_generate(prompt) # 可信度閘門檢查 result gate.check(raw_text) if result[blocked]: # 高風險打回重寫或轉人工 return {status: rejected, report: result} elif result[need_review]: # 低風險提示人為確認后發(fā) return {status: review, report: result} else: return {status: approved, content: raw_text}另外還有兩個組合使用建議。第一如果用的是 OpenAI 這類 API可以在系統(tǒng)提示詞里要求“不要使用模糊引用格式除非你能提供明確來源”這個能顯著減少前期命中量。第二在輸出鏈路里加一個“置信度閾值”比如只對超過一定長度的文檔做檢查對短句可以跳過。還可以讓閘門在“生成-檢測-重寫-再檢測”流程里跑兩輪第一次命中高風險規(guī)則后把命中信息反饋給 LLM讓它自我修正后重新輸出再跑一次往往能過。4. 常見問題與排查技巧實錄4.1 規(guī)則匹配過度把正常的原創(chuàng)內(nèi)容也攔了這個問題遇到過太多次。一開始我加的規(guī)則特別激進比如只要出現(xiàn)“數(shù)據(jù)顯示”就攔截結果有一篇正常引用 Excel 報表總結的文檔被攔下來了文案里寫的是“數(shù)據(jù)顯示新用戶占比為 42%”這其實是作者自己后臺的真實數(shù)據(jù)。誤攔的原因是規(guī)則沒有區(qū)分“聲稱型引用”和“回溯型引用”。后來我把規(guī)則調整成必須滿足“模糊引用詞 結論性動詞 沒有具體來源標識”三個條件才觸發(fā)攔截。如果句子后半段出現(xiàn)了“根據(jù)內(nèi)部報表”說明來源是明確的就把它降為提示。正則表達式中可以使用前瞻后顧來約束r(?!內(nèi)部)(?!我方)(?!該企業(yè)的)根據(jù)(?:相關|某|一位|業(yè)內(nèi))?(?:研究|報告|數(shù)據(jù))這個負向后顧(?!...)能比較有效地排除掉“根據(jù)我方數(shù)據(jù)”這類場景。給規(guī)則調優(yōu)時最關鍵的是準備好“正樣本集”和“負樣本集”。拿一百篇已經(jīng)認為可信的正常文章跑一遍把所有誤報都找出來逐個調整。如果沒做這一步規(guī)則庫很容易在某個特定領域過度擬合。4.2 完全沒匹配到但內(nèi)容仍然有幻覺正則閘門有個天然的邊界它只能識別“看起來可疑的表達”不能判斷“表達很好的謊言”。如果 LLM 一句“根據(jù)市場趨勢未來一年行業(yè)增速預計為 8.7%”這句話里沒有用任何“毫無疑問”“專家表示”之類的詞那我的規(guī)則庫是真拿它沒辦法——但這不是正則方案失效而是一個整體的定位問題。很多幻覺內(nèi)容并沒有明顯的語言特征。它的特征在事實層面日期錯了、數(shù)據(jù)來源不存在、人物頭銜對不上。這種情況下無論是正則還是關鍵詞匹配都很難兜底需要靠檢索增強生成RAG把外部知識接進來或者靠人工抽檢。我自己的建議是不要把可信度閘門當成幻覺的終結方案把它當成過濾器。它解決的是“一類問題”——自信表達類幻覺。對于超過這個范圍的情況優(yōu)先考慮在提示詞里要求 LLM 明確標注“需要核實的部分”再讓閘門檢查它有沒有遵守這個要求。生成時先聲明“不確定的信息要標注占位符”LLM 通常會老實很多。4.3 性能問題大文本檢測速度太慢正則匹配在短文本上快得可以忽略但如果一次跑十幾萬字的報告重復編譯規(guī)則會導致性能下降。所以代碼里我是用了re.compile在__init__時一次性編譯后面循環(huán)調用時復用。另外一個影響性能的坑是使用過多的捕獲組和回溯。正則里寫(.*?)(?:xx|yy)(.*?)這類模式時在長文本上可能出現(xiàn)回溯爆炸。優(yōu)化方法主要有幾個使用非捕獲組(?:)替代捕獲組能用字符集就用字符集避免重疊分支導致回溯。比如匹配“據(jù)某某報道”時不要寫成據(jù).*?報道這種貪婪匹配很容易把一整段都吃進去更好的寫法是限定中間內(nèi)容長度r據(jù)[^。]{1,20}報道最后提一下規(guī)則維護方式。我會把規(guī)則庫放到獨立的 JSON 文件里方便非開發(fā)人員參與調規(guī)則。每條規(guī)則會記錄新增原因、誤報次數(shù)、有效命中次數(shù)。每隔一段時間跑一次歷史樣本把長期不觸發(fā)以及誤報率高的規(guī)則移出主規(guī)則庫。正則閘門最核心的價值不是代碼本身而是規(guī)則庫可持續(xù)迭代慢慢積累成一套適配自己業(yè)務的理解體系。我個人在實際操作中的體會是正則方案解決問題不在于“技術含量”而在于愿意花時間去收集那些讓內(nèi)容變“假”的信號。每發(fā)現(xiàn)一種新誤報就補一條規(guī)則每遇到一次漏攔就反推它的句式有什么特征。規(guī)則庫積累到一定程度后你甚至能反推出當前常用 LLM 的“表達習慣”知道哪類提示詞下它更愛編數(shù)據(jù)。在做內(nèi)容質量管理的時候這種掌控感比單純疊加智能檢測方案踏實得多。