7373OLLAMA_BASE = os .environ .get ("OLLAMA_BASE" , "http://localhost:11434" )
7474OLLAMA_MODEL = os .environ .get ("OLLAMA_MODEL" , "glm-ocr" )
7575OLLAMA_NUM_CTX = int (os .environ .get ("OLLAMA_NUM_CTX" , "16384" ))
76+ OLLAMA_NUM_PREDICT = int (os .environ .get ("OLLAMA_NUM_PREDICT" , "4096" ))
7677if OLLAMA_NUM_CTX <= 0 :
7778 raise RuntimeError ("OLLAMA_NUM_CTX must be a positive integer" )
79+ if OLLAMA_NUM_PREDICT <= 0 :
80+ raise RuntimeError ("OLLAMA_NUM_PREDICT must be a positive integer" )
7881OCR_REQUEST_TIMEOUT_MS = int (os .environ .get ("OCR_REQUEST_TIMEOUT_MS" , "300000" ))
7982if OCR_REQUEST_TIMEOUT_MS <= 0 :
8083 raise RuntimeError ("OCR_REQUEST_TIMEOUT_MS must be a positive integer" )
81- OCR_PROMPT = "识别图片中的全部内容,输出Markdown格式。表格请保留为Markdown或HTML表格,不要转为纯文本。跳过页眉页脚和页码。"
84+ OCR_PROMPT = (
85+ "请只转写图片中清晰可见的文字,并输出 Markdown。"
86+ "保留原有换行、列表和表格结构;表格请使用 Markdown 或 HTML 表格。"
87+ "不要解释、总结、补全、翻译或编造图片中不存在的内容。"
88+ "跳过页眉、页脚和页码;如果没有可识别文字,只输出空字符串。"
89+ )
8290
8391# LaTeX → Unicode mapping (loaded once at import time)
8492_LATEX_MAP_FILE = APP_DIR / "latex_unicode.json"
@@ -659,6 +667,8 @@ def _ollama_chat_payload(content: str, image_b64: str | None = None) -> dict:
659667 "stream" : False ,
660668 "options" : {
661669 "num_ctx" : OLLAMA_NUM_CTX ,
670+ "num_predict" : OLLAMA_NUM_PREDICT ,
671+ "temperature" : 0 ,
662672 },
663673 }
664674
@@ -667,13 +677,34 @@ def _postprocess(text: str) -> str:
667677 """Strip markdown fences and convert LaTeX to Unicode."""
668678 text = re .sub (r'^```\w*\n?' , '' , text .strip ())
669679 text = re .sub (r'\n?```$' , '' , text .strip ())
680+ text = re .sub (r'(?m)^\s*```\w*\s*$' , '' , text )
681+ text = _remove_empty_html_tables (text )
682+ text = _unwrap_html_paragraphs (text )
670683 # Remove standalone $$...$$ lines whose content duplicates nearby $...$ inline math
671684 text = _preserve_html_tables (text , _remove_duplicate_display_math )
672685 text = _latex_to_unicode (text )
673686 text = _preserve_html_tables (text , _dedup_lines )
674687 return text .strip ()
675688
676689
690+ def _remove_empty_html_tables (text : str ) -> str :
691+ """Remove hallucinated empty table shells from OCR output."""
692+ empty_table = re .compile (
693+ r'<table\b[^>]*>\s*'
694+ r'(?:<tbody>\s*)?'
695+ r'<tr>\s*(?:<t[dh]\b[^>]*>\s*</t[dh]>\s*)+</tr>'
696+ r'\s*(?:</tbody>\s*)?'
697+ r'</table>' ,
698+ flags = re .IGNORECASE ,
699+ )
700+ return empty_table .sub ('' , text )
701+
702+
703+ def _unwrap_html_paragraphs (text : str ) -> str :
704+ """Convert plain HTML paragraph wrappers to Markdown-friendly text."""
705+ return re .sub (r'</?p\b[^>]*>' , '' , text , flags = re .IGNORECASE )
706+
707+
677708def _preserve_html_tables (text : str , transform ) -> str :
678709 """Apply a text transform outside HTML table blocks only."""
679710 parts = re .split (r'(<table[\s\S]*?</table>)' , text , flags = re .IGNORECASE )
0 commit comments