1111from typing import Union
1212
1313import re
14+
15+
16+ _CLEANED_BLOCK_RE = re .compile (
17+ r"<cleaned_start>\s*(.*?)\s*<cleaned_end>" ,
18+ flags = re .IGNORECASE | re .DOTALL ,
19+ )
20+ _ANSWER_BLOCK_RE = re .compile (
21+ r"<answer>\s*(.*?)\s*</answer>" ,
22+ flags = re .IGNORECASE | re .DOTALL ,
23+ )
24+ _PROCESSING_STEPS_RE = re .compile (
25+ r"\s*Processing Steps:\s*"
26+ r"1\.\s*\[Tag Analysis\]\s*Classify markup tags\s*"
27+ r"2\.\s*\[Reference Extraction\]\s*Isolate images/tables\s*"
28+ r"3\.\s*\[Character Audit\]\s*Log special chars\s*"
29+ r"4\.\s*\[Structure Check\]\s*Validate hierarchy\s*"
30+ r"5\.\s*\[Final Output\]\s*Generate cleaned text.*$" ,
31+ flags = re .IGNORECASE | re .DOTALL ,
32+ )
33+ _PROCESSING_STEPS_WITHOUT_HEADER_RE = re .compile (
34+ r"\s*1\.\s*\[Tag Analysis\]\s*Classify markup tags\s*"
35+ r"2\.\s*\[Reference Extraction\]\s*Isolate images/tables\s*"
36+ r"3\.\s*\[Character Audit\]\s*Log special chars\s*"
37+ r"4\.\s*\[Structure Check\]\s*Validate hierarchy\s*"
38+ r"5\.\s*\[Final Output\]\s*Generate cleaned text.*$" ,
39+ flags = re .IGNORECASE | re .DOTALL ,
40+ )
41+ _ZH_PROCESSING_STEPS_RE = re .compile (
42+ r"\s*(?:处理步骤|处理流程|治理步骤)[::]\s*"
43+ r"1[.、]\s*\[(?:标签分析|标记分析)\].*?"
44+ r"2[.、]\s*\[(?:引用提取|参考提取)\].*?"
45+ r"3[.、]\s*\[(?:字符审核|字符审计)\].*?"
46+ r"4[.、]\s*\[(?:结构检查|结构校验)\].*?"
47+ r"5[.、]\s*\[(?:最终输出|最终结果)\].*$" ,
48+ flags = re .DOTALL ,
49+ )
50+ _ZH_PROCESSING_STEPS_WITHOUT_HEADER_RE = re .compile (
51+ r"\s*1[.、]\s*\[(?:标签分析|标记分析)\].*?"
52+ r"2[.、]\s*\[(?:引用提取|参考提取)\].*?"
53+ r"3[.、]\s*\[(?:字符审核|字符审计)\].*?"
54+ r"4[.、]\s*\[(?:结构检查|结构校验)\].*?"
55+ r"5[.、]\s*\[(?:最终输出|最终结果)\].*$" ,
56+ flags = re .DOTALL ,
57+ )
58+
59+
60+ def extract_cleaned_text (text , post_process = None ) -> str :
61+ """Extract model output while dropping prompt-instruction leakage."""
62+ text = "" if text is None else str (text )
63+
64+ cleaned_match = _CLEANED_BLOCK_RE .search (text )
65+ if cleaned_match :
66+ text = cleaned_match .group (1 )
67+ else :
68+ answer_match = _ANSWER_BLOCK_RE .search (text )
69+ if answer_match :
70+ text = answer_match .group (1 )
71+ text = text .replace ("<cleaned_start>" , "" ).replace ("<cleaned_end>" , "" )
72+
73+ text = _PROCESSING_STEPS_RE .sub ("" , text )
74+ text = _PROCESSING_STEPS_WITHOUT_HEADER_RE .sub ("" , text )
75+ text = _ZH_PROCESSING_STEPS_RE .sub ("" , text )
76+ text = _ZH_PROCESSING_STEPS_WITHOUT_HEADER_RE .sub ("" , text )
77+ text = text .strip ()
78+
79+ if post_process :
80+ text = post_process (text )
81+ return text
82+
83+
1484@prompt_restrict (
1585 KnowledgeCleanerPrompt
1686)
@@ -27,7 +97,7 @@ def __init__(self, llm_serving: LLMServingABC, lang="en", prompt_template : Unio
2797 if prompt_template :
2898 self .prompt_template = prompt_template
2999 else :
30- self .prompt_template = KnowledgeCleanerPrompt ()
100+ self .prompt_template = KnowledgeCleanerPrompt (lang = lang )
31101
32102 @staticmethod
33103 def get_desc (lang : str = "zh" ):
@@ -123,15 +193,16 @@ def run(
123193 formatted_prompts = self ._reformat_prompt (dataframe )
124194 cleaned = self .llm_serving .generate_from_input (formatted_prompts ,"" )
125195
126- #for each in cleaned, only save the content in <cleaned_start> and <cleaned_end>
196+ # Save only the final cleaned text, even if the model leaks prompt steps.
127197 cleaned_extracted = [
128- str (text ).split ('<cleaned_start>' )[1 ].split ('<cleaned_end>' )[0 ].strip ()
129- if '<cleaned_start>' in str (text ) and '<cleaned_end>' in str (text )
130- else str (text ).strip ()
198+ extract_cleaned_text (
199+ text ,
200+ getattr (self .prompt_template , "_post_process" , None ),
201+ )
131202 for text in cleaned
132203 ]
133204 dataframe [self .output_key ] = cleaned_extracted
134205 output_file = storage .write (dataframe )
135206 self .logger .info (f"Results saved to { output_file } " )
136207
137- return [output_key ]
208+ return [output_key ]
0 commit comments