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

news2025/1/20 14:41:05

公式样例

渲染前

 \[
 \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')

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

国产文本编辑器EverEdit - 恢复最近的选区

1 恢复最近的选区 1.1 应用场景 如果用户选择了一些文本&#xff0c;特别是多选区选择&#xff0c;在选择的过程中出现失误&#xff0c;导致选区丢失&#xff0c;一般的做法是骂骂咧咧再选一次&#xff0c;使用EverEdit就没有这个烦恼&#xff0c;EverEdit内置了恢复最近的选区…

54,【4】BUUCTF WEB GYCTF2020Ezsqli

进入靶场 吓我一跳&#xff0c;但凡放个彭于晏我都不说啥了 提交个1看看 1 and 11 1# 还尝试了很多&#xff0c;不过都被过滤了&#xff0c;头疼 看看别人的WP 竟然要写代码去跑&#xff01;&#xff01;&#xff01;&#xff0c;不会啊&#xff0c;先用别人的代码吧&#xf…

【unity进阶篇】unity如何实现跨平台及unity最优最小包体打包方式(.NET、Mono和IL2CPP知识介绍)

考虑到每个人基础可能不一样&#xff0c;且并不是所有人都有同时做2D、3D开发的需求&#xff0c;所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇。 【C#篇】&#xff1a;主要讲解C#的基础语法&#xff0c;包括变量、数据类型、运算符、…

实力认证 | 海云安入选《信创安全产品及服务购买决策参考》

近日&#xff0c;国内知名安全调研机构GoUpSec发布了2024年中国网络安全行业《信创安全产品及服务购买决策参考》&#xff0c;报告从产品特点、产品优势、成功案例、安全策略等维度对各厂商信创安全产品及服务进行调研了解。 海云安凭借AI大模型技术在信创安全领域中的创新应用…

联想装系统后触摸板无法设置双指手势

我的一个电脑是联想小新air13&#xff0c;装Windows10系统后&#xff0c;没有找到设置触摸板手势的地方 也没有“装置设定值” 这个选项 经查询&#xff0c;需要去联想网站搜索驱动&#xff0c;下载了一个“Lenovo联想驱动管理” &#xff0c;更新了下触摸板驱动&#xff0c; …

ue5 制作,播放,停止动画蒙太奇

右键&#xff0c;动画蒙太奇 新建插槽 把默认插槽选择为&#xff0c;自己新建的插槽 然后拖一个动画进去 input换成玩家0 就可以接收键盘事件 pawn 自动控制玩家换成玩家0 找到动画蓝图 把它化成我们那边蒙太奇里面的槽 第三步&#xff1a;第三人称角色蓝图 按下F…

一文大白话讲清楚webpack基本使用——1——完成webpack的初步构建

文章目录 一文大白话讲清楚webpack基本使用——1——完成webpack的初步构建1. 先回忆webpack是个啥2. webpack四大核心2.1 Entry(入口)2.2 Output(输出)2.3 Loader(加载器)2.4 Plugin(插件) 3. 按部就班实现webpack3.1 初始化项目3.2 完成项目骨架搭建3.3 实现webpack构建 一文…

迁移学习-详解

一、fasttext工具介绍 1 fasttext介绍 1.1 fasttext作用 作为NLP工程领域常用的工具包, fasttext有两大作用: 进行文本分类 训练词向量 1.2 fasttext工具包的优势 正如它的名字, 在保持较高精度的情况下, 快速的进行训练和预测是fasttext的最大优势. fasttext优势的原因:…

Mac 删除ABC 输入法

参考链接&#xff1a;百度安全验证 Mac下删除系统自带输入法ABC&#xff0c;正解&#xff01;_mac删除abc输入法-CSDN博客 ABC 输入法和搜狗输入法等 英文有冲突~~ 切换后还会在英文状态&#xff0c;可以删除 &#xff1b;可能会对DNS 输入有影响&#xff0c;但是可以通过复…

读取GPS文件中的坐标

不同厂家产生的gps不同&#xff0c;但MALA, impulse等厂家还是比较规范&#xff0c;格式基本一致。 1 格式对比 厂家1&#xff1a;128930 1 31.865250637 118.631077136 -87.226619530 -17.247052234 -20.881583506 -19.300643625 9.146650245 -5.089975857 4.000000000 2024…

【github 使用相关】GitHub Desktop桌面端基础操作 WIP 分支 提交pr

WIP 是 “Work In Progress”&#xff08;进行中的工作&#xff09;的缩写&#xff0c;WIP分支通常用来存放尚未完成或不稳定的代码&#xff0c;开发者可在WIP进行实验逐步完成某项功能、进行团队开发、修复重要BUG和多任务处理。 在 GitHub Desktop 上管理 WIP&#xff08;Wo…

C语言之装甲车库车辆动态监控辅助记录系统

&#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 C语言之装甲车库车辆动态监控辅助记录系统 目录 一、前言 1.1 &#xff08;一&#xff09;…

日志模块新增配置日志根目录和项目模块功能

文章目录 1.日志模块新增监听器支持外部配置1.common-log4j2-starter项目结构2.修改log4j2.xml为log4j2-spring.xml&#xff08;这样可以解决读取外部配置但是提前创建目录的问题&#xff09;3.ApplicationEnvironmentPreparedListener.java 监听器读取配置4.spring.factories …

[JavaScript] 运算符详解

文章目录 算术运算符&#xff08;Arithmetic Operators&#xff09;注意事项&#xff1a; 比较运算符&#xff08;Comparison Operators&#xff09;注意事项&#xff1a; 逻辑运算符&#xff08;Logical Operators&#xff09;短路运算&#xff1a;逻辑运算符的返回值&#xf…

latin1_swedish_ci(latin1 不支持存储中文、日文、韩文等多字节字符)

文章目录 1、SHOW TABLE STATUS WHERE Name batch_version;2、latin1_swedish_ci使用场景注意事项修改字符集和排序规则修改表的字符集和排序规则修改列的字符集和排序规则修改数据库的默认字符集和排序规则 3、ALTER TABLE batch_version CONVERT TO CHARACTER SET utf8mb4 C…

【机器学习实战入门】使用OpenCV进行性别和年龄检测

Gender and Age Detection Python 项目 首先,向您介绍用于此高级 Python 项目的性别和年龄检测中的术语: 什么是计算机视觉? 计算机视觉是一门让计算机能够像人类一样观察和识别数字图像和视频的学科。它面临的挑战大多源于对生物视觉有限的了解。计算机视觉涉及获取、处…

计算机毕业设计PySpark+Hadoop+Hive机票预测 飞机票航班数据分析可视化大屏 航班预测系统 机票爬虫 飞机票推荐系统 大数据毕业设计

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

游戏引擎学习第84天

仓库:https://gitee.com/mrxiao_com/2d_game_2 我们正在试图弄清楚如何完成我们的世界构建 上周做了一些偏离计划的工作&#xff0c;开发了一个小型的背景位图合成工具&#xff0c;这个工具做得还不错&#xff0c;虽然是临时拼凑的&#xff0c;但验证了背景构建的思路。这个过…

RIME-CNN-LSTM-Attention多变量多步时序预测Matlab实现

SCI一区级 | Matlab实现RIME-CNN-LSTM-Multihead-Attention多变量多步时序预测 目录 SCI一区级 | Matlab实现RIME-CNN-LSTM-Multihead-Attention多变量多步时序预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现RIME-CNN-LSTM-Multihead-Attention霜冰算法…

SpringMVC——原理简介

狂神SSM笔记 DispatcherServlet——SpringMVC 的核心 SpringMVC 围绕DispatcherServlet设计。 DispatcherServlet的作用是将请求分发到不同的处理器&#xff08;即不同的Servlet&#xff09;。根据请求的url&#xff0c;分配到对应的Servlet接口。 当发起请求时被前置的控制…