python(25) : 含有大模型生成的公式的文本渲染成图片并生成word文档(支持flask接口调用)

公式样例

渲染前

   \[
   \sqrt{1904.615384} \approx 43.64
   \]

渲染后

安装依赖


pip install matplotlib  -i https://mirrors.aliyun.com/pypi/simple/ requests

pip install sympy  -i https://mirrors.aliyun.com/pypi/simple/ requests

pip install python-docx -i https://mirrors.aliyun.com/pypi/simple/ requests

代码

# -*- coding: utf-8 -*-

# ====> 数学公式导出处理 <==== #

import os
import traceback

import matplotlib
from docx import Document

from common.conf import doc_handle_path
from common.util import generate_time_random_code

start_marker = "\["
end_marker = "\]"

output_tmp_folder = f'{doc_handle_path}math_2_img{os.sep}'
if not os.path.exists(output_tmp_folder):
    os.mkdir(output_tmp_folder)


def is_have_math(text):
    s_count = text.count('\[')
    e_count = text.count('\]')
    if s_count >= e_count or e_count >= s_count:
        return True
    return False


def find_and_replace(text, start_marker="\[", end_marker="\]"):
    """
    查找并替换由_start和_end包围的文本。

    :param text: 需要处理的原始文本
    :param start_marker: 标记开始的字符串,默认为"_start"
    :param end_marker: 标记结束的字符串,默认为"_end"
    :return: 替换后的文本
    """

    result_parts = []  # 存储结果片段
    current_position = 0  # 当前处理到的位置

    while True:
        start_pos = text.find(start_marker, current_position)
        if start_pos == -1:
            # 没有找到更多的_start标记,将剩余部分添加到结果中并退出循环
            result_parts.append(text[current_position:])
            break

        # 添加_start之前的部分到结果中
        result_parts.append(text[current_position:start_pos])

        # 查找对应的_end标记
        end_pos = text.find(end_marker, start_pos + len(start_marker))
        if end_pos == -1:
            # 如果没有找到_end标记,则将剩余部分全部添加到结果中并退出
            result_parts.append(text[start_pos:])
            break

        # 提取并处理_start和_end之间的文本
        content = text[start_pos + len(start_marker):end_pos]
        processed_content = '111'  # 定义你自己的处理逻辑
        print(content)

        # 将处理后的内容添加到结果中
        result_parts.append(processed_content)

        # 更新当前处理位置为_end之后
        current_position = end_pos + len(end_marker)

    # 返回拼接后的最终结果
    return ''.join(result_parts)


def replace_first_closing_brace(text, split_marker=r'\(\boxed{', start_tag='[', end_tag=']'):
    """
    根据split_marker切割文本,并将每个元素的第一个"}"替换为replacement字符。

    :param text: 需要处理的原始文本
    :param split_marker: 用于切割文本的标记,默认为'\(\boxed{'
    :param replacement: 用来替换第一个'}'的字符,默认为'_'
    :return: 处理后的文本
    """

    # 如果没有split_marker,则直接返回原text
    if split_marker not in text:
        return text

    # 根据split_marker切割文本
    parts = text.split(split_marker)

    # 第一个元素是split_marker之前的内容,不需要处理
    processed_parts = [parts[0]]

    for part in parts[1:]:
        # 找到第一个"}"的位置并替换为replacement
        closing_brace_index = part.find('}')
        if closing_brace_index != -1:
            new_part = part[:closing_brace_index] + end_tag + part[closing_brace_index + 3:]
        else:
            new_part = part  # 如果没有找到"}",则保持原样
        processed_parts.append(new_part)

    # 将处理后的部分重新组合成新的字符串
    result = split_marker.join(processed_parts)

    if split_marker in result:
        result = result.replace(split_marker, start_tag)
    return result


def math_generate_docx(text, path):
    # 创建新的Document对象
    document = Document()

    # 添加标题
    # document.add_heading('Document Title', 0)

    current_position = 0  # 当前处理到的位置
    imgs = []

    while True:
        start_pos = text.find(start_marker, current_position)
        if start_pos == -1:
            # 没有找到更多的_start标记,将剩余部分添加到结果中并退出循环
            other_text = replace_first_closing_brace(text[current_position:])
            document.add_paragraph(other_text)
            break

        # 添加_start之前的部分到结果中
        document.add_paragraph(text[current_position:start_pos])
        # 查找对应的_end标记
        end_pos = text.find(end_marker, start_pos + len(start_marker))
        if end_pos == -1:
            # 如果没有找到_end标记,则将剩余部分全部添加到结果中并退出
            document.add_paragraph(text[start_pos:])
            break

        # 提取并处理_start和_end之间的文本
        content = text[start_pos + len(start_marker):end_pos]
        math_img_path = math_2_img(content)
        if math_img_path:
            imgs.append(math_img_path)
            document.add_picture(math_img_path)
        else:
            document.add_paragraph(content)

        # 更新当前处理位置为_end之后
        current_position = end_pos + len(end_marker)

    # 保存文档到本地
    document.save(path)

    for img in imgs:
        if os.path.exists(img):
            os.remove(img)


def math_2_img(text):
    text = text.replace('\n', '')
    formula = r"$" + text + "$"
    matplotlib.use('Agg')
    import matplotlib.pyplot as plt
    try:
        # 创建一个只包含公式的图像
        plt.figure(figsize=(6, 1))  # 调整大小以适应公式
        plt.text(0.5, 0.5, formula, fontsize=20, ha='center', va='center')
        plt.axis('off')  # 关闭坐标轴

        # 保存图像到本地
        output_tmp_path = f'{output_tmp_folder}{generate_time_random_code(5)}.png'
        plt.savefig(output_tmp_path, bbox_inches='tight', pad_inches=0.1, dpi=300)
    except:
        traceback.print_exc()
        return None
    plt.close()
    return output_tmp_path


if __name__ == '__main__':
    s = r"""
 为了解决这个问题,我们将按照以下步骤进行:

1. 计算58和64的乘积。
2. 将结果除以3.12。
3. 将结果乘以1.6。
4. 对结果取平方根。

让我们从第一步开始:

1. 计算58和64的乘积:
   \[
   58 \times 64 = 3712
   \]

2. 将3712除以3.12:
   \[
   \frac{3712}{3.12} \approx 1190.384615
   \]

3. 将1190.384615乘以1.6:
   \[
   1190.384615 \times 1.6 \approx 1904.615384
   \]

4. 对1904.615384取平方根:
   \[
   \sqrt{1904.615384} \approx 43.64
   \]

因此,最后的得数是 \(\boxed{43.64}\)。   
"""
    math_generate_docx(s, 'example.docx')

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/955656.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024CVPR《HomoFormer》

这篇论文提出了一种名为HomoFormer的新型Transformer模型,用于图像阴影去除。论文的主要贡献和创新点如下: 1. 研究背景与动机 阴影去除的挑战:阴影在自然场景图像中普遍存在,影响图像质量并限制后续计算机视觉任务的性能。阴影的空间分布不均匀且模式多样,导致传统的卷积…

PE文件:节表-添加节

在所有节的空白区域都不够存放我们想要添加的数据时&#xff0c;这个时候可以通过添加节来扩展我们可操作的空间去存储新的数据&#xff08;如导入表、代码或资源&#xff09;。 过程步骤 1.判断是否有足够的空间添加节表 PE文件的节表紧跟在PE头之后&#xff0c;每个节表的…

窥探QCC518x/308x系列与手机之间的蓝牙HCI记录与分析 - 手机篇

今天要介绍给大家的是, 当我们在开发高通耳机时如果遇到与手机之间相容性问题, 通常会用Frontline或Ellisys的Bluetooth Analyzer来截取资料分析, 如果手边没有这样的仪器, 要如何窥探Bluetooth的HCI log.这次介绍的是手机篇. 这次跟QCC518x/QCC308x测试的手机是Samsung S23 U…

【MySQL】数据库约束和多表查询

目录 1.前言 2.数据库约束 2.1约束类型 2.2?NULL约束 2.3 NUIQUE&#xff1a;唯一约束 2.4?DEFAULT&#xff1a;默认值约束 2.5?PRIMARY KEY&#xff1a;主键约束 2.6 FOREIGN KEY&#xff1a;外键约束 1.7?CHECK约束 3.表的设计? 3.1一对一 3.2一对多 3.3多…

Unity HybridCLR Settings热更设置

需要热更的程序集放到 热更新Assembly Definitions中。 记得补充元数据AOT dlls 打包完成后遇到TypeLoadException: could not load type 时 可能需要在Assets/link.xml中增加对应的设置 <assembly fullname"your assembly" preserve"all"/> link…

LLM - 大模型 ScallingLaws 的迁移学习与混合训练(PLM) 教程(3)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/145212097 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 Scalin…

【Python】Selenium根据网页页面长度,模拟向下滚动鼠标,直到网页底部的操作

最近在弄selenium的爬取的过程中&#xff0c;我发现一些网站上的表格&#xff0c;是需要手动拉到底部才能加载完成的。 如果没有拉到底部&#xff0c;那么在获取网页表格的时候&#xff0c;表格就会只有显示的一部分&#xff0c;页面就不完整。 所以我就整理了一些模拟滚动鼠…

vue2制作长方形容器,正方形网格散点图,并且等比缩放拖动

需求&#xff1a;有个长方形的容器&#xff0c;但是需要正方形的网格线&#xff0c;网格线是等比缩放的并且可以无线拖动的&#xff0c;并且添加自适应缩放和动态切换&#xff0c;工具是plotly.js,已完成功能如下 1.正方形网格 2.散点分组 3.自定义悬浮框的数据 4.根据窗口大小…

Lora理解QLoRA

Parameter-Efficient Fine-Tuning (PEFT) &#xff1a;节约开销的做法&#xff0c;fine-tune少量参数&#xff0c;而不是整个模型&#xff1b; Low-Rank Adaptation (LoRA) &#xff1a;是PEFT的一种&#xff1b;冻结原参数矩阵&#xff0c;只更新2个小参数矩阵。 原文经过对比…

Elasticsearch:Jira 连接器教程第二部分 - 6 个优化技巧

作者&#xff1a;来自 Elastic Gustavo Llermaly 将 Jira 连接到 Elasticsearch 后&#xff0c;我们现在将回顾最佳实践以升级此部署。 在本系列的第一部分中&#xff0c;我们配置了 Jira 连接器并将对象索引到 Elasticsearch 中。在第二部分中&#xff0c;我们将回顾一些最佳实…

联发科MTK6762/MT6762安卓核心板_4G智能模块应用

MT6762安卓核心板是一款工业级高性能、可运行 android9.0 操作系统的 4G智能模块。MT6762平台打造具备 AI 体验、先进双摄像头拍摄效果且具备丰富连接功能的智能手机主板。 MT6762安卓核心板 是一款髙性能低功耗的 4G 全网通安卓智能模块。此模块支持 2G/3G/4G 移动&#xff0c…

vue3+ts+uniapp 微信小程序(第一篇)—— 微信小程序定位授权,位置信息权限授权

文章目录 简介一、先看效果1.1 授权定位前&#xff0c;先弹出隐私协议弹框1.2 上述弹框点击同意&#xff0c;得到如下弹框1.3 点击三个点&#xff0c;然后点设置 1.4 在1.2步骤下&#xff0c;无论同意或者拒绝 二、manifest.json 文件配置三、微信公众平台配置3.1 登录进入微信…

网安快速入门之Windows命令

在Windows中 我们今天介绍几个命令&#xff1a; help copy dir cd type del ipconfig net netstat tasklist sc1. help 显示命令的帮助信息。或者显示Windows内置命令。 常用参数&#xff1a; <命令>&#xff1a;查看指定命令的帮助。 示例&#xff1a;help copy 显…

Red Hat8:搭建FTP服务器

目录 一、匿名FTP访问 1、新建挂载文件 2、挂载 3、关闭防火墙 4、搭建yum源 5、安装VSFTPD 6、 打开配置文件 7、设置配置文件如下几个参数 8、重启vsftpd服务 9、进入图形化界面配置网络 10、查看IP地址 11、安装ftp服务 12、遇到拒绝连接 13、测试 二、本地…

Git 安装 操作 命令 远程仓库 多人协作

Git作用 Git诞生史 很多人都知道&#xff0c;Linus在1991年创建了开源的Linux&#xff0c;从此&#xff0c;Linux系统不断发展&#xff0c;已经成为最大的服务器系统软件了。Linus虽然创建了Linux&#xff0c;但Linux的壮大是靠全世界热心的志愿者参与的&#xff0c;这么多人在…

Vue快速开发之环境搭建nodejs与运行第一个Vue项目

步骤一:下载node.js 注意: 建议下载v12.16.0版本以上的,因为版本低无法创建Vue的脚手架。文件选择:下载方式1: 从官网下载:http://nodejs.cn/download/ 下载方式2: 从我发现的一个网站下载,选择自己想要的版本 https://nodejs.org/download/release/ 比如我下载的时v2…

AUTOSAR通信篇 - PDU和收发数据

点击订阅专栏不迷路 文章目录 一、概述二、OSI模型与AUTOSAR层级关系三、I-PDU、N-PDU、L-PDU及其关系3.1. L-PDU3.2. N-PDU3.3. I-PDU 四、数据流4.1. 普通数据流4.2. 诊断数据流4.3. 动态PDU数据流4.4. 安全通信数据流4.5. XCP数据流 返回总目录 一、概述 在学习Autosar通信…

.Net8 Avalonia跨平台UI框架——<vlc:VideoView>控件播放海康监控、摄像机视频(Windows / Linux)

一、UI效果 二、新建用户控件&#xff1a;VideoViewControl.axaml 需引用&#xff1a;VideoLAN.LibVLC.Windows包 Linux平台需安装&#xff1a;VLC 和 LibVLC &#xff08;sudo apt-get update、sudo apt-get install vlc libvlccore-dev libvlc-dev&#xff09; .axaml 代码 注…

哈尔滨有双线服务器租用吗?

哈尔滨有双线服务器租用吗&#xff1f;双线服务器是一种针对哈尔滨特有的网络环境优化的服务器解决方案&#xff0c;它能够同时支持中国电信和中国联通或移动其中两家主要ISP&#xff08;互联网服务提供商&#xff09;的连接。 由于中国南方地区多采用电信网络&#xff0c;而北…

58,【8】BUUCTF [PwnThyBytes 2019]Baby_SQL1

进入靶场 和2次注入的页面很像 不过养成查看源代码的好习惯 先访问source.zip 下载后解压&#xff0c;发现两个文件 第一个文件夹打开又有4个PHP文件 那还是先看index.php文件好了 有PHP和HTML两部分&#xff0c;下面是PHP部分代码&#xff08;HTML太长了&#xff0c;先放一…