当前位置: 首页 > article >正文

GLM-OCR Web UI定制开发:添加OCR结果导出Word/PDF/Markdown功能

GLM-OCR Web UI定制开发添加OCR结果导出Word/PDF/Markdown功能1. 引言你有没有遇到过这样的场景用GLM-OCR识别了一份重要的合同文档得到了准确的文本结果然后...然后你需要把这些文本复制到Word里重新排版或者手动整理成报告格式。这个过程不仅耗时还容易出错。GLM-OCR确实是个强大的工具它能准确识别文本、表格甚至公式但它的Web界面有个明显的短板——识别结果只能显示在页面上想要保存下来进一步使用就得手动复制粘贴。对于需要批量处理文档或者生成正式报告的用户来说这个限制相当影响效率。今天我就来分享一个实用的定制开发方案为GLM-OCR的Web UI添加OCR结果导出功能支持一键导出为Word文档、PDF文件和Markdown格式。这个功能实现后你可以把识别出的合同直接保存为格式规范的Word文档将表格识别结果导出为PDF方便打印和分享把技术文档转换为Markdown格式直接用于博客或文档系统接下来我会手把手带你完成这个功能的开发从需求分析到代码实现再到实际测试整个过程都会详细讲解。即使你不是专业的Web开发人员只要跟着步骤走也能顺利完成这个定制化功能。2. 项目环境准备2.1 了解现有项目结构在开始开发之前我们先看看GLM-OCR项目的现有结构。根据项目说明主要文件如下/root/GLM-OCR/ ├── serve_gradio.py # Gradio 服务脚本 ├── start_vllm.sh # 启动脚本 ├── USAGE.md # 详细文档 └── logs/ # 运行日志我们需要修改的是serve_gradio.py文件这是Web界面的核心代码。Gradio是一个Python库可以快速构建机器学习应用的Web界面GLM-OCR就是用这个库搭建的用户界面。2.2 安装必要的依赖包导出功能需要一些额外的Python库支持。我们先激活项目使用的conda环境然后安装必要的包# 激活conda环境 source /opt/miniconda3/bin/activate py310 # 安装导出功能所需的库 /opt/miniconda3/envs/py310/bin/pip install python-docx reportlab markdown这三个库的作用分别是python-docx用于生成Word文档reportlab用于生成PDF文件markdown用于处理Markdown格式转换如果你还需要其他格式的支持比如Excel可以额外安装openpyxl/opt/miniconda3/envs/py310/bin/pip install openpyxl2.3 备份原始文件在修改代码之前做个备份是个好习惯cd /root/GLM-OCR cp serve_gradio.py serve_gradio.py.backup这样如果修改过程中出现问题我们可以随时恢复原始版本。3. 导出功能设计与实现3.1 功能需求分析我们要实现的导出功能需要满足以下几个核心需求支持多种格式至少包括Word、PDF、Markdown三种常用格式保持内容结构文本、表格、公式等不同内容类型要正确转换操作简单用户点击按钮就能导出不需要复杂的配置文件命名合理自动生成有意义的文件名比如基于上传图片的名称错误处理完善导出过程中出现问题时给用户明确的提示基于这些需求我设计了下面的实现方案。3.2 创建导出工具模块为了保持代码的清晰和可维护性我们创建一个单独的导出工具模块。在/root/GLM-OCR目录下新建一个文件export_utils.py GLM-OCR 导出工具模块 支持将OCR结果导出为Word、PDF、Markdown格式 import os import tempfile from datetime import datetime from docx import Document from docx.shared import Inches, Pt from docx.enum.text import WD_ALIGN_PARAGRAPH from reportlab.lib.pagesizes import letter from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib.units import inch from reportlab.lib import colors import markdown from io import BytesIO class OCRExporter: OCR结果导出器 def __init__(self, ocr_result, image_nameNone): 初始化导出器 参数: ocr_result: OCR识别结果文本 image_name: 原始图片名称用于生成导出文件名 self.ocr_result ocr_result self.image_name image_name or ocr_result # 清理文件名移除扩展名和特殊字符 if self.image_name: base_name os.path.splitext(os.path.basename(self.image_name))[0] self.base_name .join(c for c in base_name if c.isalnum() or c in ( , -, _)) else: self.base_name ocr_result def export_to_word(self, output_pathNone): 导出为Word文档 参数: output_path: 输出文件路径如果为None则生成临时文件 返回: 文件路径 if output_path is None: # 生成临时文件 timestamp datetime.now().strftime(%Y%m%d_%H%M%S) output_path f/tmp/{self.base_name}_{timestamp}.docx # 创建Word文档 doc Document() # 添加标题 title doc.add_heading(fOCR识别结果 - {self.base_name}, 0) title.alignment WD_ALIGN_PARAGRAPH.CENTER # 添加生成时间 time_str datetime.now().strftime(%Y年%m月%d日 %H:%M:%S) time_para doc.add_paragraph(f生成时间: {time_str}) time_para.alignment WD_ALIGN_PARAGRAPH.CENTER doc.add_paragraph() # 空行 # 处理OCR结果 lines self.ocr_result.strip().split(\n) for line in lines: if line.strip(): # 跳过空行 # 简单判断是否为表格行包含多个制表符或连续空格 if \t in line or in line: # 尝试按制表符或空格分割 if \t in line: cells line.split(\t) else: cells line.split( ) # 创建表格 table doc.add_table(rows1, colslen(cells)) table.style Light Grid Accent 1 # 填充表格数据 for i, cell in enumerate(cells): table.cell(0, i).text cell.strip() else: # 普通文本段落 para doc.add_paragraph(line.strip()) # 设置段落格式 para_format para.paragraph_format para_format.line_spacing 1.5 # 保存文档 doc.save(output_path) return output_path def export_to_pdf(self, output_pathNone): 导出为PDF文档 参数: output_path: 输出文件路径如果为None则生成临时文件 返回: 文件路径 if output_path is None: # 生成临时文件 timestamp datetime.now().strftime(%Y%m%d_%H%M%S) output_path f/tmp/{self.base_name}_{timestamp}.pdf # 创建PDF文档 doc SimpleDocTemplate(output_path, pagesizeletter) styles getSampleStyleSheet() # 自定义样式 title_style ParagraphStyle( CustomTitle, parentstyles[Heading1], fontSize16, spaceAfter12, alignment1 # 居中 ) content_style ParagraphStyle( CustomContent, parentstyles[Normal], fontSize10, spaceAfter6, leading14 # 行距 ) # 构建内容 story [] # 添加标题 title_text fOCR识别结果 - {self.base_name} story.append(Paragraph(title_text, title_style)) story.append(Spacer(1, 12)) # 添加生成时间 time_str datetime.now().strftime(%Y年%m月%d日 %H:%M:%S) story.append(Paragraph(f生成时间: {time_str}, styles[Normal])) story.append(Spacer(1, 24)) # 处理OCR结果 lines self.ocr_result.strip().split(\n) for line in lines: if line.strip(): # 简单判断是否为表格行 if \t in line or in line: # 创建表格数据 if \t in line: cells line.split(\t) else: cells line.split( ) # 创建表格 table_data [[cell.strip() for cell in cells]] table Table(table_data) # 设置表格样式 table.setStyle(TableStyle([ (BACKGROUND, (0, 0), (-1, 0), colors.grey), (TEXTCOLOR, (0, 0), (-1, 0), colors.whitesmoke), (ALIGN, (0, 0), (-1, -1), CENTER), (FONTNAME, (0, 0), (-1, 0), Helvetica-Bold), (FONTSIZE, (0, 0), (-1, 0), 10), (BOTTOMPADDING, (0, 0), (-1, 0), 12), (BACKGROUND, (0, 1), (-1, -1), colors.beige), (GRID, (0, 0), (-1, -1), 1, colors.black) ])) story.append(table) story.append(Spacer(1, 12)) else: # 普通文本 story.append(Paragraph(line.strip(), content_style)) # 生成PDF doc.build(story) return output_path def export_to_markdown(self, output_pathNone): 导出为Markdown文档 参数: output_path: 输出文件路径如果为None则生成临时文件 返回: 文件路径 if output_path is None: # 生成临时文件 timestamp datetime.now().strftime(%Y%m%d_%H%M%S) output_path f/tmp/{self.base_name}_{timestamp}.md # 构建Markdown内容 md_content f# OCR识别结果 - {self.base_name} **生成时间**: {datetime.now().strftime(%Y年%m%d日 %H:%M:%S)} --- ## 识别内容 # 处理OCR结果 lines self.ocr_result.strip().split(\n) for line in lines: if line.strip(): # 判断是否为表格行 if \t in line: # Markdown表格格式 cells line.split(\t) md_content | | .join(cell.strip() for cell in cells) |\n elif in line and len(line.split( )) 1: # 多个空格分隔的表格 cells [c.strip() for c in line.split( ) if c.strip()] if len(cells) 1: md_content | | .join(cells) |\n else: # 普通文本 md_content line.strip() \n\n # 保存Markdown文件 with open(output_path, w, encodingutf-8) as f: f.write(md_content) return output_path def export(self, format_type, output_pathNone): 通用导出方法 参数: format_type: 导出格式支持 word, pdf, markdown output_path: 输出文件路径 返回: 文件路径 format_type format_type.lower() if format_type word: return self.export_to_word(output_path) elif format_type pdf: return self.export_to_pdf(output_path) elif format_type markdown: return self.export_to_markdown(output_path) else: raise ValueError(f不支持的格式: {format_type}) def test_export(): 测试导出功能 # 测试数据 test_result 这是一个测试文档 表格示例: 姓名 年龄 职业 张三 25 工程师 李四 30 设计师 王五 28 产品经理 这是普通文本段落包含一些重要的信息。 公式示例: E mc² 文档结束。 # 测试各种格式导出 exporter OCRExporter(test_result, test_document.jpg) print(测试Word导出...) word_file exporter.export_to_word() print(fWord文件已生成: {word_file}) print(\n测试PDF导出...) pdf_file exporter.export_to_pdf() print(fPDF文件已生成: {pdf_file}) print(\n测试Markdown导出...) md_file exporter.export_to_markdown() print(fMarkdown文件已生成: {md_file}) return word_file, pdf_file, md_file if __name__ __main__: test_export()这个导出工具模块提供了完整的导出功能支持三种格式并且有基本的表格识别和格式处理能力。3.3 修改Gradio界面现在我们需要修改serve_gradio.py文件在现有的Web界面中添加导出功能。打开文件找到合适的位置添加导出相关的代码。首先在文件开头导入我们刚创建的导出工具# 在现有import语句后面添加 import os import tempfile from export_utils import OCRExporter然后找到创建Gradio界面的部分。通常这个文件会有一个create_ui()函数或者类似的界面创建代码。我们需要在识别结果的输出区域添加导出按钮。假设现有的界面代码大致是这样的结构def create_ui(): with gr.Blocks() as demo: gr.Markdown(# GLM-OCR 文档识别系统) with gr.Row(): with gr.Column(): image_input gr.Image(label上传图片, typefilepath) prompt_input gr.Textbox(label任务类型, valueText Recognition:, interactiveTrue) submit_btn gr.Button(开始识别, variantprimary) with gr.Column(): output_text gr.Textbox(label识别结果, lines20, interactiveFalse) # 在这里添加导出功能 with gr.Row(): with gr.Column(): gr.Markdown(### 导出选项) format_select gr.Dropdown( choices[Word文档 (.docx), PDF文件 (.pdf), Markdown (.md)], label选择导出格式, valueWord文档 (.docx) ) export_btn gr.Button(导出结果, variantsecondary) download_file gr.File(label下载文件, interactiveFalse) # 导出按钮点击事件 def export_result(ocr_text, format_choice, image_info): if not ocr_text or ocr_text.strip() : return None, 请先进行OCR识别 try: # 从格式选择中提取格式类型 format_map { Word文档 (.docx): word, PDF文件 (.pdf): pdf, Markdown (.md): markdown } format_type format_map.get(format_choice, word) # 获取图片名称如果有 image_name None if image_info and isinstance(image_info, dict) and name in image_info: image_name image_info[name] elif isinstance(image_info, str): image_name os.path.basename(image_info) # 创建导出器并导出 exporter OCRExporter(ocr_text, image_name) export_file exporter.export(format_type) # 返回文件路径 return export_file, 导出成功 except Exception as e: return None, f导出失败: {str(e)} # 连接按钮事件 export_btn.click( fnexport_result, inputs[output_text, format_select, image_input], outputs[download_file, gr.Textbox(label导出状态, visibleTrue)] ) # 原有的识别功能保持不变 # ... 原有的识别逻辑代码 ... return demo这里的关键点在界面中添加了导出格式选择下拉框添加了导出按钮添加了文件下载组件实现了导出函数处理格式转换和文件生成将导出按钮与导出函数绑定3.4 完整修改示例由于我不知道serve_gradio.py的具体内容这里提供一个完整的修改示例。你可以根据实际情况调整 GLM-OCR Gradio服务脚本 - 增强版添加导出功能 import gradio as gr import torch from transformers import AutoModelForCausalLM, AutoTokenizer from PIL import Image import argparse import os import sys from datetime import datetime # 添加导出工具导入 from export_utils import OCRExporter def load_model(model_path): 加载模型 print(f正在加载模型: {model_path}) # 原有的模型加载代码 tokenizer AutoTokenizer.from_pretrained( model_path, trust_remote_codeTrue ) model AutoModelForCausalLM.from_pretrained( model_path, torch_dtypetorch.float16, device_mapauto, trust_remote_codeTrue ) print(模型加载完成) return model, tokenizer def process_image(image_path, prompt, model, tokenizer): 处理图片并返回OCR结果 try: # 打开图片 image Image.open(image_path).convert(RGB) # 构建输入 query fimage\n{prompt} inputs tokenizer.build_conversation_input_ids( tokenizer, queryquery, images[image], template_versionchatml ) inputs { input_ids: inputs[input_ids].unsqueeze(0).cuda(), token_type_ids: inputs[token_type_ids].unsqueeze(0).cuda(), attention_mask: inputs[attention_mask].unsqueeze(0).cuda(), images: [[inputs[images][0].cuda().to(torch.float16)]] } # 生成输出 with torch.no_grad(): outputs model.generate( **inputs, max_new_tokens1024, do_sampleFalse ) # 解码输出 response tokenizer.decode(outputs[0], skip_special_tokensTrue) # 提取OCR结果移除prompt部分 if prompt in response: result response.split(prompt)[-1].strip() else: result response.strip() return result except Exception as e: return f处理失败: {str(e)} def export_ocr_result(ocr_text, format_choice, image_info): 导出OCR结果到指定格式 if not ocr_text or ocr_text.strip() : return None, 请先进行OCR识别 try: # 映射格式选择到实际格式 format_map { Word文档 (.docx): word, PDF文件 (.pdf): pdf, Markdown (.md): markdown } format_type format_map.get(format_choice, word) # 获取图片名称 image_name None if image_info: if isinstance(image_info, str): image_name os.path.basename(image_info) elif hasattr(image_info, name): image_name image_info.name # 创建导出器 exporter OCRExporter(ocr_text, image_name) # 导出文件 export_file exporter.export(format_type) return export_file, 导出成功文件已准备好下载。 except Exception as e: return None, f导出失败: {str(e)} def create_ui(model, tokenizer): 创建Gradio用户界面 def process_wrapper(image, prompt): 包装处理函数处理Gradio的输入 if image is None: return 请上传图片 # 保存临时图片文件 temp_dir /tmp/glm_ocr os.makedirs(temp_dir, exist_okTrue) temp_path os.path.join(temp_dir, ftemp_{datetime.now().strftime(%Y%m%d_%H%M%S)}.png) if hasattr(image, save): image.save(temp_path) else: # 如果是文件路径 import shutil shutil.copy(image, temp_path) # 处理图片 result process_image(temp_path, prompt, model, tokenizer) # 清理临时文件 try: os.remove(temp_path) except: pass return result with gr.Blocks(titleGLM-OCR 文档识别系统, themegr.themes.Soft()) as demo: gr.Markdown( # GLM-OCR 文档识别系统 支持文本识别、表格识别、公式识别等多种OCR功能。 ) with gr.Row(): with gr.Column(scale1): # 图片上传区域 image_input gr.Image( label上传文档图片, typepil, sources[upload], height400 ) # 任务选择 task_select gr.Dropdown( choices[ Text Recognition:, Table Recognition:, Formula Recognition: ], valueText Recognition:, label选择识别任务, interactiveTrue ) # 自定义提示词 custom_prompt gr.Textbox( label自定义提示词可选, placeholder留空使用默认提示词, lines2 ) # 识别按钮 recognize_btn gr.Button( 开始识别, variantprimary, sizelg ) with gr.Column(scale2): # 识别结果显示 output_text gr.Textbox( label识别结果, lines25, interactiveTrue, show_copy_buttonTrue ) # 导出功能区域 with gr.Group(): gr.Markdown(### 导出功能) with gr.Row(): format_select gr.Dropdown( choices[ Word文档 (.docx), PDF文件 (.pdf), Markdown (.md) ], valueWord文档 (.docx), label选择导出格式, scale3 ) export_btn gr.Button( 导出结果, variantsecondary, scale1 ) # 状态提示 export_status gr.Textbox( label导出状态, interactiveFalse, visibleFalse ) # 文件下载 download_file gr.File( label下载文件, interactiveFalse, visibleFalse ) # 识别按钮事件 def on_recognize(image, task, custom_text): if image is None: return 请上传图片 # 使用自定义提示词或默认提示词 prompt custom_text.strip() if custom_text.strip() else task return process_wrapper(image, prompt) recognize_btn.click( fnon_recognize, inputs[image_input, task_select, custom_prompt], outputsoutput_text ) # 导出按钮事件 def on_export(ocr_text, format_choice, image): if not ocr_text or ocr_text.strip() : return gr.update(visibleFalse), gr.update(value请先进行OCR识别, visibleTrue), gr.update(visibleFalse) file_path, status export_ocr_result(ocr_text, format_choice, image) if file_path: return gr.update(valuefile_path, visibleTrue), gr.update(valuestatus, visibleTrue), gr.update(visibleTrue) else: return gr.update(visibleFalse), gr.update(valuestatus, visibleTrue), gr.update(visibleFalse) export_btn.click( fnon_export, inputs[output_text, format_select, image_input], outputs[download_file, export_status, gr.Textbox(visibleTrue)] # 添加一个占位符保持输出数量一致 ) # 示例部分 with gr.Accordion(使用示例, openFalse): gr.Markdown( **文本识别示例:** - 上传包含文字的图片 - 选择Text Recognition: - 点击开始识别 **表格识别示例:** - 上传包含表格的图片 - 选择Table Recognition: - 点击开始识别 **公式识别示例:** - 上传包含数学公式的图片 - 选择Formula Recognition: - 点击开始识别 **导出功能:** 1. 先进行OCR识别获取结果 2. 选择要导出的格式Word/PDF/Markdown 3. 点击导出结果按钮 4. 下载生成的文件 ) # 提示信息 gr.Markdown( --- **提示:** - 支持PNG、JPG、WEBP格式图片 - 首次识别需要加载模型请耐心等待 - 导出功能需要先进行OCR识别 - 导出的文件保存在临时目录请及时下载 ) return demo def main(): 主函数 parser argparse.ArgumentParser() parser.add_argument(--model-path, typestr, default/root/ai-models/ZhipuAI/GLM-OCR, help模型路径) parser.add_argument(--server-name, typestr, default0.0.0.0, help服务器地址) parser.add_argument(--server-port, typeint, default7860, help服务器端口) parser.add_argument(--share, actionstore_true, help是否创建公开分享链接) args parser.parse_args() # 检查模型路径 if not os.path.exists(args.model_path): print(f错误: 模型路径不存在: {args.model_path}) sys.exit(1) # 加载模型 model, tokenizer load_model(args.model_path) # 创建界面 demo create_ui(model, tokenizer) # 启动服务 demo.launch( server_nameargs.server_name, server_portargs.server_port, shareargs.share, show_errorTrue ) if __name__ __main__: main()这个完整的示例包含了原有的OCR识别功能新增的导出功能改进的用户界面布局完整的错误处理使用说明和示例4. 功能测试与优化4.1 测试导出功能修改完成后我们需要测试导出功能是否正常工作。首先启动服务cd /root/GLM-OCR ./start_vllm.sh服务启动后在浏览器中打开http://localhost:7860你会看到新的界面多了一个导出功能区域。测试步骤上传一张包含文字的图片点击开始识别按钮等待识别完成查看结果选择导出格式比如Word文档点击导出结果按钮下载生成的文件并打开验证4.2 常见问题解决在测试过程中可能会遇到一些问题这里提供一些解决方案问题1导出按钮点击后没反应可能原因JavaScript错误或函数调用问题 解决方法检查浏览器控制台是否有错误信息确认export_utils.py文件在正确位置检查Python依赖是否安装完整问题2导出的文件格式不正确可能原因文件内容处理逻辑有问题 解决方法检查OCRExporter类中的格式处理逻辑确保文本内容正确传递验证文件扩展名是否正确问题3中文内容显示乱码可能原因编码问题 解决方法确保所有文件操作使用UTF-8编码在Word和PDF生成时指定中文字体修改export_utils.py添加中文字体支持4.3 添加中文字体支持为了让导出的Word和PDF正确显示中文我们需要修改导出工具添加中文字体支持。更新export_utils.py中的相关方法# 在OCRExporter类的export_to_word方法中添加中文字体支持 def export_to_word(self, output_pathNone): 导出为Word文档支持中文 if output_path is None: timestamp datetime.now().strftime(%Y%m%d_%H%M%S) output_path f/tmp/{self.base_name}_{timestamp}.docx # 创建Word文档 doc Document() # 添加中文字体支持 from docx.oxml.ns import qn from docx.shared import RGBColor # 设置文档默认字体 doc.styles[Normal].font.name 微软雅黑 doc.styles[Normal]._element.rPr.rFonts.set(qn(w:eastAsia), 微软雅黑) # ... 其余代码保持不变 ...对于PDF需要确保系统中有中文字体或者使用支持中文的字体文件。4.4 性能优化建议如果处理大量文档或大文件时性能不佳可以考虑以下优化异步处理将导出操作改为异步避免阻塞界面进度提示添加导出进度提示批量导出支持批量处理多个识别结果缓存机制对相同内容使用缓存避免重复生成5. 高级功能扩展5.1 添加更多导出格式除了基本的三种格式你还可以添加更多导出选项# 在export_utils.py中添加新格式支持 def export_to_txt(self, output_pathNone): 导出为纯文本文件 if output_path is None: timestamp datetime.now().strftime(%Y%m%d_%H%M%S) output_path f/tmp/{self.base_name}_{timestamp}.txt with open(output_path, w, encodingutf-8) as f: f.write(fOCR识别结果 - {self.base_name}\n) f.write(f生成时间: {datetime.now().strftime(%Y年%m月%d日 %H:%M:%S)}\n) f.write( * 50 \n\n) f.write(self.ocr_result) return output_path def export_to_html(self, output_pathNone): 导出为HTML文件 if output_path is None: timestamp datetime.now().strftime(%Y%m%d_%H%M%S) output_path f/tmp/{self.base_name}_{timestamp}.html html_content f!DOCTYPE html html head meta charsetUTF-8 titleOCR识别结果 - {self.base_name}/title style body {{ font-family: Arial, sans-serif; margin: 40px; }} .header {{ text-align: center; margin-bottom: 30px; }} .content {{ line-height: 1.6; }} table {{ border-collapse: collapse; width: 100%; margin: 20px 0; }} th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }} th {{ background-color: #f2f2f2; }} /style /head body div classheader h1OCR识别结果 - {self.base_name}/h1 p生成时间: {datetime.now().strftime(%Y年%m月%d日 %H:%M:%S)}/p /div div classcontent {self._ocr_to_html()} /div /body /html with open(output_path, w, encodingutf-8) as f: f.write(html_content) return output_path def _ocr_to_html(self): 将OCR结果转换为HTML lines self.ocr_result.strip().split(\n) html_lines [] for line in lines: if line.strip(): # 判断是否为表格行 if \t in line: cells line.split(\t) if len(html_lines) 0 or not html_lines[-1].startswith(table): html_lines.append(table) html_lines.append(tr) html_lines.extend(fth{cell.strip()}/th for cell in cells) html_lines.append(/tr) else: html_lines.append(tr) html_lines.extend(ftd{cell.strip()}/td for cell in cells) html_lines.append(/tr) else: # 结束表格如果有 if html_lines and html_lines[-1].startswith(/tr): html_lines.append(/table) # 添加段落 html_lines.append(fp{line.strip()}/p) # 确保表格闭合 if html_lines and html_lines[-1].startswith(/tr): html_lines.append(/table) return \n.join(html_lines)然后在界面中添加这些新格式的选项。5.2 添加批量导出功能如果需要处理多个文档可以添加批量导出功能def batch_export(ocr_results, format_type, output_dirNone): 批量导出多个OCR结果 参数: ocr_results: 列表每个元素是(图片名, OCR文本)的元组 format_type: 导出格式 output_dir: 输出目录 返回: 压缩包路径 import zipfile if output_dir is None: output_dir /tmp/ocr_batch_export os.makedirs(output_dir, exist_okTrue) exported_files [] for i, (image_name, ocr_text) in enumerate(ocr_results): exporter OCRExporter(ocr_text, image_name) file_path exporter.export(format_type, os.path.join(output_dir, fdocument_{i1})) exported_files.append(file_path) # 创建压缩包 zip_path os.path.join(output_dir, batch_export.zip) with zipfile.ZipFile(zip_path, w) as zipf: for file_path in exported_files: zipf.write(file_path, os.path.basename(file_path)) return zip_path5.3 添加自定义模板功能对于需要固定格式的报告可以添加模板功能def export_with_template(self, template_path, output_pathNone): 使用模板导出 参数: template_path: 模板文件路径支持.docx output_path: 输出文件路径 from docx import Document # 加载模板 doc Document(template_path) # 在模板中查找替换标记并替换为OCR内容 # 这里需要根据实际模板设计替换逻辑 if output_path is None: timestamp datetime.now().strftime(%Y%m%d_%H%M%S) output_path f/tmp/{self.base_name}_template_{timestamp}.docx doc.save(output_path) return output_path6. 总结通过本文的步骤我们成功为GLM-OCR的Web UI添加了强大的导出功能。现在这个OCR工具不仅能够准确识别文档内容还能将识别结果一键导出为多种常用格式大大提升了实用性和工作效率。6.1 实现的核心功能多格式支持实现了Word、PDF、Markdown三种主流格式的导出智能格式处理能够识别文本中的表格结构并正确转换用户友好界面在原有界面上无缝集成操作简单直观错误处理完善对各种异常情况都有相应的处理机制中文字体支持确保中文内容正确显示6.2 主要改进点实用性提升从只能查看结果到可以导出使用完成了工具闭环用户体验优化添加了状态提示、错误反馈等细节代码结构清晰将导出功能模块化便于维护和扩展兼容性良好与原有功能完全兼容不影响正常使用6.3 使用建议日常使用对于简单的文档识别直接使用Web界面导出即可批量处理如果需要处理大量文档可以考虑扩展批量导出功能定制需求对于有特殊格式要求的场景可以开发自定义模板功能性能优化如果导出速度较慢可以考虑添加异步处理和进度提示6.4 扩展可能性这个导出功能框架具有良好的扩展性未来可以根据需要添加更多格式支持如Excel、PowerPoint、JSON等云端存储集成直接导出到云盘或协作平台API接口提供REST API供其他系统调用自动化工作流与自动化工具集成实现全自动文档处理通过这次定制开发我们不仅解决了GLM-OCR的实际使用痛点也展示了如何基于开源项目进行功能扩展的思路和方法。希望这个方案对你有所帮助也欢迎在此基础上继续优化和创新。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

相关文章:

GLM-OCR Web UI定制开发:添加OCR结果导出Word/PDF/Markdown功能

GLM-OCR Web UI定制开发:添加OCR结果导出Word/PDF/Markdown功能 1. 引言 你有没有遇到过这样的场景?用GLM-OCR识别了一份重要的合同文档,得到了准确的文本结果,然后...然后你需要把这些文本复制到Word里重新排版,或者…...

Python绘制饼图

制作一个“饼条图”,其中饼图的第一片被“炸开”成条形图,并进一步细分该片的特征。示例演示了如何使用具有多组坐标轴的图形,并使用坐标轴的patches列表添加两个ConnectionPatches以连接子图。 import matplotlib.pyplot as plt import num…...

Windows 11部署通义千问1.8B对话机器人:WSL2+GPU支持,开箱即用教程

Windows 11部署通义千问1.8B对话机器人:WSL2GPU支持,开箱即用教程 1. 环境准备与WSL2安装 想在Windows 11上轻松运行AI对话模型?WSL2(Windows Subsystem for Linux)是最佳解决方案。它让你无需双系统或虚拟机,直接在Windows中运…...

深度剖析:Hotkey Detective如何高效解决Windows热键冲突问题

深度剖析:Hotkey Detective如何高效解决Windows热键冲突问题 【免费下载链接】hotkey-detective A small program for investigating stolen hotkeys under Windows 8 项目地址: https://gitcode.com/gh_mirrors/ho/hotkey-detective 在Windows系统开发和使用…...

SPSS Modeler缺失值处理实战:从数据审核到自动插补的完整流程

SPSS Modeler缺失值处理实战:从数据审核到自动插补的完整流程 数据质量是分析结果的基石,而缺失值处理则是数据清洗中最常见的挑战之一。想象一下,你正面对一份客户数据集,准备进行购买行为预测,却发现关键字段如年龄、…...

从零到一:基于STM32的自动量程电压表开发全流程解析

1. 项目背景与需求分析 第一次接触自动量程电压表项目时,我和大多数嵌入式新手一样充满困惑。这个看似简单的设备,实际上涉及模拟电路设计、AD转换原理、嵌入式编程等多个领域的知识融合。选择STM32作为主控芯片,主要考虑到它内置12位ADC的特…...

LoRA训练助手+VMware虚拟机:安全隔离的训练环境搭建

LoRA训练助手VMware虚拟机:安全隔离的训练环境搭建 1. 引言 你是不是遇到过这样的情况:想要尝试LoRA模型训练,但又担心影响主机系统的稳定性?或者担心训练过程中的数据安全问题?其实很多刚接触AI训练的小伙伴都有类似…...

学术投稿管理2.0:Elsevier Tracker如何重构科研工作流

学术投稿管理2.0:Elsevier Tracker如何重构科研工作流 【免费下载链接】Elsevier-Tracker 项目地址: https://gitcode.com/gh_mirrors/el/Elsevier-Tracker 一、投稿困境:那些正在消耗你科研精力的隐形黑洞 凌晨两点十七分,王教授的…...

PETRV2-BEV模型训练避坑指南:星图AI平台环境配置详解

PETRV2-BEV模型训练避坑指南:星图AI平台环境配置详解 1. 环境准备与快速部署 1.1 创建并激活conda环境 在星图AI平台上训练PETRV2-BEV模型前,首先需要确保正确的Python环境。平台已预置了包含PaddlePaddle框架的conda环境: conda activat…...

【MCP 2.0安全红线清单】:23个协议层致命漏洞、7类典型误配置及零信任加固路径(2024权威审计实录)

第一章:MCP 2.0安全红线清单的演进逻辑与审计范式MCP(Managed Cloud Platform)2.0安全红线清单并非对旧版规则的简单扩容,而是以“攻击面收敛—策略可证—执行可溯”为内核重构的动态治理框架。其演进逻辑根植于云原生环境下的三大…...

Qwen3-32B效果展示:RTX4090D上多轮技术问答、代码解释、算法推导真实对话

Qwen3-32B效果展示:RTX4090D上多轮技术问答、代码解释、算法推导真实对话 1. 开篇:强大的私有化部署方案 Qwen3-32B-Chat 私有部署镜像专为RTX4090D 24G显存环境深度优化,基于CUDA12.4和驱动550.90.07打造。这个开箱即用的解决方案内置完整运…...

高空作业场景下人员安全带安全帽脚手架梯子检测数据集VOC+YOLO格式12661张6类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件)图片数量(jpg文件个数):12661标注数量(xml文件个数):12661标注数量(txt文件个数):12661标注类…...

IndexTTS2 V23快速体验:上传参考音频,一键克隆带情感的语音风格

IndexTTS2 V23快速体验:上传参考音频,一键克隆带情感的语音风格 1. 引言:语音克隆技术的新突破 想象一下,你只需要录制一段10秒的语音,就能让AI完美复刻你的声音风格和情感表达。这正是IndexTTS2 V23版本带来的革命性…...

Qwen3-ASR-1.7B在Kubernetes上的弹性部署方案

Qwen3-ASR-1.7B在Kubernetes上的弹性部署方案 1. 引言 语音识别技术正在快速改变我们与机器交互的方式,而Qwen3-ASR-1.7B作为阿里开源的先进语音识别模型,支持52种语言和方言,在准确性和效率方面都表现出色。但在实际生产环境中&#xff0c…...

引言:为什么 XGBoost 是机器学习领域的“大杀器”?

在机器学习的结构化数据领域,有一个算法几乎无人不知,它就是 XGBoost(Extreme Gradient Boosting,极端梯度提升)。自诞生以来,XGBoost 就以其卓越的性能和效率,横扫了无数的数据科学竞赛&#x…...

从“价值供给”到“语法奠基”:江畅、韩燕丽与岐金兰论中国自主知识体系的生成路径

从“价值供给”到“语法奠基”:江畅、韩燕丽与岐金兰论中国自主知识体系的生成路径笔者:岐金兰(人机协作2026.3.20)摘要:中国自主知识体系的构建,正经历从“价值供给”到“语法奠基”的深层转向。江畅以“道…...

从 BERT 到 RoPE:NLP 模型长文本处理的进化之路

1. 引言:长文本处理的困境在自然语言处理(NLP)的早期阶段,模型如 RNN(循环神经网络)和 LSTM(长短期记忆网络)虽然在处理序列数据方面取得了进展,但其固有的顺序计算特性导…...

Lumia设备定制自由:WPinternals系统潜能释放指南

Lumia设备定制自由:WPinternals系统潜能释放指南 【免费下载链接】WPinternals Tool to unlock the bootloader and enable Root Access on Windows Phones 项目地址: https://gitcode.com/gh_mirrors/wp/WPinternals 作为一款开源工具,WPinterna…...

Ubuntu网络服务重启全攻略:从NetworkManager到nmcli的5种方法(附常见问题排查)

Ubuntu网络服务重启全攻略:从基础到高阶的完整解决方案 当你正在远程服务器上调试一个关键任务,突然网络连接中断,那种感觉就像在黑暗中摸索。作为Ubuntu系统管理员或开发者,掌握网络服务重启的多种方法不仅是一项技能&#xff0c…...

点云分割实战:LCCP算法在3D物体识别中的5个调参技巧(附代码)

LCCP点云分割实战:5个关键参数调优策略与工业级代码实现 在自动驾驶车辆识别路沿石、工业机器人抓取杂乱零件、AR设备重建室内场景时,我们常常需要处理海量的三维点云数据。这些看似无序的XYZ坐标点背后,隐藏着物体表面的几何特征与空间关系。…...

Qwen-VL多场景落地:Qwen-Image镜像支持农业病虫害图像识别+防治建议生成

Qwen-VL多场景落地:Qwen-Image镜像支持农业病虫害图像识别防治建议生成 1. 农业场景中的技术痛点 在传统农业生产中,病虫害识别和防治一直是个难题。农民朋友经常面临几个困扰: 识别困难:病虫害种类繁多,非专业人士…...

Coze智能体网页部署避坑指南:从Token获取到会话隔离的完整解决方案

Coze智能体企业级网页部署实战:安全架构与性能优化全解析 引言:为什么企业部署需要超越基础教程? 当大多数开发者还在关注如何快速嵌入聊天窗口时,企业级应用已经面临更复杂的挑战:如何确保万级并发下的稳定响应&…...

Midscene低代码实战:5分钟搞定Android自动化测试(附WPS登录案例)

Midscene低代码实战:5分钟构建Android自动化测试工作流 在移动应用开发领域,自动化测试已成为保障产品质量的关键环节。然而传统自动化测试工具的高门槛让许多中小企业望而却步——需要专业测试工程师编写复杂脚本、频繁维护定位逻辑、应对设备兼容性问题…...

深入解析Gradle Wrapper:从生成到更新的全流程实践

1. Gradle Wrapper的核心价值与工作原理 第一次接触Gradle Wrapper时,我和很多开发者一样有个疑问:为什么已经有了Gradle还要用Wrapper?直到在团队协作时遇到"本地能跑,别人电脑就报错"的问题才明白它的价值。简单来说&…...

Qwen3-32B-Chat效果对比:不同FlashAttention版本对RTX4090D推理性能影响

Qwen3-32B-Chat效果对比:不同FlashAttention版本对RTX4090D推理性能影响 1. 测试环境与配置 1.1 硬件配置 本次测试使用以下硬件环境: 显卡:NVIDIA RTX 4090D 24GB显存内存:128GB DDR5CPU:Intel i9-13900K (10核心…...

Qwen3-32B-Chat RTX4090D部署案例:政府政策文件智能摘要系统落地

Qwen3-32B-Chat RTX4090D部署案例:政府政策文件智能摘要系统落地 1. 项目背景与需求 在政务信息化建设中,政策文件的快速理解和精准摘要一直是重要需求。传统人工处理方式面临效率低、成本高、标准不统一等问题。基于大语言模型的智能摘要系统能够实现…...

协议层漏洞闭环管理全链路,从MCP 2.0安全基线到实时动态策略下发的4级防护体系

第一章:协议层漏洞闭环管理全链路概述协议层漏洞闭环管理并非孤立的技术动作,而是一套覆盖识别、分析、验证、修复与回归验证的端到端工程实践体系。其核心目标是将网络协议(如 TCP/IP、TLS、HTTP/2、DNS、SIP 等)在实现、配置或交…...

DOTA数据集:遥感图像检测的黄金标准与实战指南

1. DOTA数据集:遥感图像检测的黄金标准 第一次接触DOTA数据集是在2018年,当时我正在做一个卫星图像分析项目。那时候可选的遥感数据集很少,DOTA的出现就像一场及时雨。这个数据集的全称是Dataset for Object deTection in Aerial images&…...

AIGlasses_for_navigation多场景落地:大型展会人流密集区导航降噪方案

AIGlasses_for_navigation多场景落地:大型展会人流密集区导航降噪方案 1. 引言:当导航遇上人山人海 想象一下这个场景:你正参加一个大型科技展会,展馆面积超过十万平米,参展商上千家,参观者摩肩接踵。你急…...

GISBox实战:把无人机拍的LAS点云,变成网页上能飞的3DTiles模型

GISBox实战:从无人机LAS点云到Web端3DTiles的完整工作流 去年参与某智慧园区项目时,客户要求在48小时内将无人机采集的200GB点云数据转化为可交互的Web三维模型。当团队还在讨论传统处理流程的时间成本时,GISBox让我们用3小时就完成了从原始数…...