Add FireRed OCR comparison and preserve attribution layout
This commit is contained in:
@@ -143,3 +143,73 @@ def test_corrections_require_source_and_exact_expected_text():
|
||||
applied=apply_corrections(pages,patch,'source')
|
||||
assert pages[0]['lines'][0]['text']=='牲畜' and len(applied)==1
|
||||
with pytest.raises(ValueError,match='Stale'):apply_corrections(pages,patch,'source')
|
||||
|
||||
|
||||
def test_signature_and_date_keep_separate_right_aligned_paragraphs():
|
||||
page={'number':1,'lines':[{'id':'body','text':'正文最后一段。','bbox':[.1,.4,.85,.44]}, {'id':'name','text':'作者甲','bbox':[.72,.50,.84,.52]}, {'id':'date','text':'2020.2.16','bbox':[.70,.54,.84,.56]}]}
|
||||
blocks,_=paragraphs(page,'zh-CN',set())
|
||||
assert [b['text'] for b in blocks][-2:]==['作者甲','2020.2.16']
|
||||
assert all(b.get('alignment')=='right' and b.get('role')=='attribution' for b in blocks[-2:])
|
||||
from src.pdf_import.markdown_layout import markdown_blocks
|
||||
md=markdown_blocks({'number':1,'markdown':'识别后的正文最后一段。\n\n作者甲\n\n2020.2.16'},'zh-CN',page)
|
||||
assert md[0]['text']=='识别后的正文最后一段。'
|
||||
assert all(b.get('alignment')=='right' for b in md[-2:])
|
||||
assert md[-1]['geometry_source']=='reference-vision-text-alignment'
|
||||
assert md[-1]['line_ids']==[] # Never pretend FireRed emitted coordinates or Vision text.
|
||||
|
||||
|
||||
def test_firered_http_cache_and_truncation_rejection(tmp_path,monkeypatch):
|
||||
from PIL import Image
|
||||
import io
|
||||
import src.pdf_import.firered as firered
|
||||
calls=[]
|
||||
def response(request,timeout):
|
||||
payload=json.loads(request.data);calls.append(payload)
|
||||
return io.BytesIO(json.dumps({'model':'firered-ocr','choices':[{'finish_reason':'stop','message':{'content':'原文段落。\n\n作者甲'}}],'usage':{'completion_tokens':10}}).encode())
|
||||
monkeypatch.setattr(firered,'urlopen',response)
|
||||
image=tmp_path/'page.png';Image.new('RGB',(40,60),'white').save(image)
|
||||
engine=firered.FireRedOCR(tmp_path,'zh-CN',base_url='http://ocr.test:8001')
|
||||
result=engine.recognize(image);assert result['markdown'].startswith('原文段落') and result['lines']==[]
|
||||
assert engine.recognize(image)==result and len(calls)==1
|
||||
assert calls[0]['model']=='firered-ocr' and calls[0]['temperature']==0
|
||||
def truncated(request,timeout):
|
||||
return io.BytesIO(json.dumps({'choices':[{'finish_reason':'length','message':{'content':'仅一部分'}}]}).encode())
|
||||
monkeypatch.setattr(firered,'urlopen',truncated)
|
||||
rejected=firered.FireRedOCR(tmp_path/'rejected','zh-CN',base_url='http://ocr.test:8001')
|
||||
with pytest.raises(RuntimeError,match='incomplete'):rejected.recognize(image)
|
||||
assert list((tmp_path/'rejected/firered-raw').glob('*.rejected.json'))
|
||||
|
||||
|
||||
def test_snippet_comparison_excludes_page_context_and_counts_missing_characters():
|
||||
from scripts.compare_pdf_ocr import snippet_errors
|
||||
assert snippet_errors('原始正文','页眉原始正文页脚')['errors']==0
|
||||
result=snippet_errors('拥有识字能力','页眉有识字能力页脚')
|
||||
assert result['errors']==1
|
||||
assert sum(result[k] for k in ['substitutions','deletions','insertions'])==1
|
||||
|
||||
|
||||
def test_markdown_ocr_is_exported_as_text_not_an_image(native_pdf,tmp_path,monkeypatch):
|
||||
import src.pdf_import.firered as firered
|
||||
from src.pdf_import.converter import digest,save_json
|
||||
class FakeOCR:
|
||||
identity='markdown-fixture'
|
||||
def __init__(self,*args,**kwargs):pass
|
||||
def recognize(self,image):return {'lines':[],'markdown':'这是重新识别后的完整正文段落,保留新模型文字而不是旧模型的文字内容。\n\n作者甲\n\n2020.2.16'}
|
||||
def close(self):pass
|
||||
monkeypatch.setattr(firered,'FireRedOCR',FakeOCR)
|
||||
source=native_pdf(image=True);work=tmp_path/'work';geom=tmp_path/'geometry';save_json(geom/'source.json',{'sha256':digest(source)})
|
||||
for n in [1,2]:
|
||||
save_json(geom/'pages'/f'{n:04d}.json',{'number':n,'stamp':{'source':digest(source)},'lines':[{'id':f'p{n}-a','text':'这是旧模型的正文段落。','bbox':[.1,.2,.9,.3]},{'id':f'p{n}-b','text':'作者甲','bbox':[.72,.5,.84,.52]},{'id':f'p{n}-c','text':'2020.2.16','bbox':[.7,.54,.84,.56]}]})
|
||||
out=tmp_path/'md.epub';convert(source,out,work,engine='firered',ocr_url='http://ocr.test',geometry_work=geom)
|
||||
with zipfile.ZipFile(out) as z:
|
||||
text=''.join(z.read(n).decode() for n in z.namelist() if '/chapters/' in n)
|
||||
assert '重新识别后的完整正文' in text and 'class="attribution"' in text
|
||||
assert '作者甲2020' not in text
|
||||
assert audit_epub(out)['issues']==[]
|
||||
|
||||
|
||||
def test_markdown_does_not_erase_uncertain_sentence_spacing():
|
||||
from src.pdf_import.markdown_layout import markdown_blocks
|
||||
blocks=markdown_blocks({'number':1,'markdown':'前一句 后一句'},'zh-CN')
|
||||
assert blocks[0]['text']=='前一句 后一句'
|
||||
assert blocks[0]['bbox'] is None
|
||||
|
||||
Reference in New Issue
Block a user