平时用LLM大语言模型去解释文献里面的公式含义直接复制的格式word看不懂,基于这个web可以正常加载显示。
下面是读取的效果展示:下面程序保存为stl_read.py然后运行下面指令。
streamlit run stl_read.py
import streamlit as st
import base64
import re
from pathlib import Path
import pandas as pd
from streamlit_ace import st_ace
# 设置页面配置
st.set_page_config(
page_title="公式文档查看器",
page_icon="📝",
layout="wide",
initial_sidebar_state="expanded"
)
# 自定义CSS样式
st.markdown("""
<style>
.main {
background-color: #f8f9fa;
}
.stApp {
max-width: 1200px;
margin: 0 auto;
}
h1, h2, h3 {
color: #2c3e50;
}
.css-18e3th9 {
padding-top: 2rem;
}
.stMarkdown {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
code {
background-color: #f0f2f5;
padding: 0.2em 0.4em;
border-radius: 3px;
}
pre code {
display: block;
padding: 1em;
overflow-x: auto;
line-height: 1.45;
}
blockquote {
border-left: 4px solid #6c757d;
padding-left: 1em;
color: #6c757d;
margin-left: 0;
}
hr {
border: none;
height: 1px;
background-color: #e1e4e8;
margin: 2em 0;
}
table {
border-collapse: collapse;
width: 100%;
margin: 1em 0;
}
th, td {
border: 1px solid #e1e4e8;
padding: 0.6em 1em;
}
th {
background-color: #f0f2f5;
font-weight: 600;
}
img {
max-width: 100%;
height: auto;
display: block;
margin: 1em 0;
}
.katex {
font-size: 1.1em;
}
.uploaded-file-info {
background-color: #e8f4f8;
padding: 1rem;
border-radius: 5px;
margin-bottom: 1rem;
border-left: 5px solid #4a86e8;
}
.editor-container {
border: 1px solid #ddd;
border-radius: 5px;
margin-bottom: 1rem;
}
.section-title {
font-size: 1.2rem;
font-weight: 600;
margin-bottom: 0.5rem;
color: #2c3e50;
}
.info-card {
background-color: white;
padding: 1.5rem;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
margin-bottom: 1rem;
}
/* 隐藏 Streamlit 默认的菜单按钮和部署按钮 */
#MainMenu {visibility: hidden;}
.stDeployButton {display: none;}
header {visibility: hidden;}
footer {visibility: hidden;}
.block-container {padding-top: 2rem;}
</style>
""", unsafe_allow_html=True)
# 处理Markdown中的LaTeX公式
def process_latex(content):
"""
处理LaTeX公式以便在Streamlit中正确渲染
增强版函数,支持处理不同格式和位置的LaTeX公式
"""
# 处理1: 将 \[ 和 \] 之间的公式替换为 $$ 和 $$ (显示公式)
content = re.sub(r'\\\[(.*?)\\\]', r'$$\1$$', content, flags=re.DOTALL)
# 处理2: 将 \begin{equation} 和 \end{equation} 之间的公式替换为 $$ 和 $$
content = re.sub(r'\\begin\{equation\}(.*?)\\end\{equation\}', r'$$\1$$', content, flags=re.DOTALL)
# 处理3: 将 \begin{align} 和 \end{align} 之间的公式替换为 $$ 和 $$
content = re.sub(r'\\begin\{align\}(.*?)\\end\{align\}', r'$$\1$$', content, flags=re.DOTALL)
# 处理4: 将文本中的 \( 和 \) 之间的公式替换为 $ 和 $ (内联公式)
content = re.sub(r'\\\((.*?)\\\)', r'$\1$', content, flags=re.DOTALL)
# 处理5: 将文本中的 \frac、\partial 等LaTeX命令包装成内联公式
# 正则表达式匹配 \命令{参数} 格式但不在已有的 $ 或 $$ 中
def wrap_standalone_latex_cmd(match):
# 如果前后已经有 $ 或 $$,则不处理
if re.search(r'(\$|\$\$)[^\$]*' + re.escape(match.group(0)) + r'[^\$]*(\$|\$\$)', content):
return match.group(0)
return f"${match.group(0)}$"
# 匹配常见的LaTeX命令:
latex_cmd_pattern = r'\\(frac|partial|sum|int|prod|sqrt|alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega|infty|cdot|times|div|geq|leq|neq|approx|sim|pm|mp|in|subset|supset|cup|cap|rightarrow|leftarrow|Rightarrow|Leftarrow|mathbb|mathbf|mathcal|mathrm|text|hat|bar|dot|ddot|vec|overrightarrow|underline|overline|widehat|widetilde|overbrace|underbrace){1}(\{[^{}]*\}|\^[^{}]*|\_{1}[^{}]*)'
# 尝试匹配单独的LaTeX命令,并用$包裹
content = re.sub(latex_cmd_pattern, wrap_standalone_latex_cmd, content)
# 处理6: 特殊处理 (\frac{...}{...}) 的情况
# 匹配格式如 (\frac{a}{b}) 并替换为 ($\frac{a}{b}$)
content = re.sub(r'\(\\(frac|partial|sum|int)(\{[^{}]*\})(\{[^{}]*\})\)', r'($\\\1\2\3$)', content)
return content
# 获取文件元数据
def get_file_metadata(file):
return {
"filename": file.name,
"size": f"{file.size / 1024:.2f} KB",
"type": file.type
}
# 显示带有动画的标题
st.markdown("""
<div style="text-align: center; margin-bottom: 2rem;">
<h1 style="color: #4a86e8; font-size: 2.5rem; margin-bottom: 0.5rem;">公式文档查看器</h1>
<p style="color: #6c757d; font-size: 1.1rem;">查看和编辑公式文档,支持各种公式</p>
</div>
""", unsafe_allow_html=True)
# 创建侧边栏
with st.sidebar:
st.markdown("## 📋 控制面板")
# 文件上传组件
uploaded_file = st.file_uploader("上传公式文档", type=["md", "txt"],
help="上传包含公式的文档")
st.markdown("---")
st.markdown("## ⚙️ 显示设置")
# 显示设置
show_raw = st.checkbox("显示原始内容", value=False)
enable_editor = st.checkbox("启用编辑器", value=False) # 默认不选中
# 主题选择
theme = st.selectbox("颜色主题",
["亮色", "暗色", "蓝色", "绿色", "紫色"],
index=0)
# 应用主题
if theme == "暗色":
st.markdown("""
<style>
.main { background-color: #1e1e1e; color: #e0e0e0; }
h1, h2, h3 { color: #e0e0e0; }
.info-card { background-color: #2d2d2d; color: #e0e0e0; }
code { background-color: #333; color: #e0e0e0; }
th { background-color: #333; }
th, td { border-color: #444; }
.uploaded-file-info { background-color: #2d2d2d; border-left-color: #4a86e8; }
</style>
""", unsafe_allow_html=True)
elif theme == "蓝色":
st.markdown("""
<style>
.main { background-color: #f0f4f8; }
h1, h2, h3 { color: #1a5276; }
.info-card { background-color: white; border-left: 5px solid #2980b9; }
.uploaded-file-info { border-left-color: #2980b9; background-color: #ebf5fb; }
</style>
""", unsafe_allow_html=True)
elif theme == "绿色":
st.markdown("""
<style>
.main { background-color: #f0f8f4; }
h1, h2, h3 { color: #1e8449; }
.info-card { background-color: white; border-left: 5px solid #27ae60; }
.uploaded-file-info { border-left-color: #27ae60; background-color: #ebfaf0; }
</style>
""", unsafe_allow_html=True)
elif theme == "紫色":
st.markdown("""
<style>
.main { background-color: #f5f0f8; }
h1, h2, h3 { color: #6c3483; }
.info-card { background-color: white; border-left: 5px solid #8e44ad; }
.uploaded-file-info { border-left-color: #8e44ad; background-color: #f4ecf7; }
</style>
""", unsafe_allow_html=True)
st.markdown("---")
st.markdown("""
""")
# 主要内容
if uploaded_file is not None:
try:
# 读取文件
content = uploaded_file.getvalue().decode("utf-8")
# 处理LaTeX公式以便正确渲染
processed_content = process_latex(content)
# 获取元数据
metadata = get_file_metadata(uploaded_file)
# 在精美的卡片中显示文件信息
st.markdown(f"""
<div class="uploaded-file-info">
<div style="display: flex; justify-content: space-between; align-items: center;">
<div>
<h3 style="margin: 0;">📄 {metadata['filename']}</h3>
<p style="margin: 0.5rem 0 0 0;">大小: {metadata['size']} | 类型: {metadata['type']}</p>
</div>
<div style="text-align: right;">
<p style="margin: 0;">上传时间: {pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
</div>
</div>
</div>
""", unsafe_allow_html=True)
# 可选的原始内容显示
if show_raw:
st.markdown("### 原始内容")
st.code(content, language="markdown")
st.markdown("---")
# 编辑器(如果启用)
if enable_editor:
st.markdown('<p class="section-title">📝 编辑器</p>', unsafe_allow_html=True)
st.markdown('<div class="editor-container">', unsafe_allow_html=True)
edited_content = st_ace(
value=content,
language="markdown",
theme="github" if theme == "亮色" else "monokai",
height=300,
auto_update=True
)
st.markdown('</div>', unsafe_allow_html=True)
# 使用编辑后的内容进行渲染
processed_content = process_latex(edited_content)
# 渲染处理后的markdown内容
st.markdown('<div class="info-card">', unsafe_allow_html=True)
st.markdown("### 渲染内容")
st.markdown(processed_content)
st.markdown('</div>', unsafe_allow_html=True)
except Exception as e:
st.error(f"处理文件时出错: {str(e)}")
else:
# 当没有上传文件时显示欢迎信息和说明
st.markdown("""
<div class="info-card" style="text-align: center;">
<h2>欢迎使用公式文档查看器</h2>
<p>上传一个公式文档开始使用</p>
<div style="margin: 2rem 0;">
<svg width="100" height="100" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13 12H21.5L12.5 3L3.5 12H12V21H13V12Z" fill="#4a86e8"/>
</svg>
</div>
<p>支持各种格式的公式,可以提供完美显示体验。</p>
</div>
""", unsafe_allow_html=True)
# 功能卡片
col1, col2, col3 = st.columns(3)
with col1:
st.markdown("""
<div class="info-card" style="height: 200px;">
<h3 style="color: #4a86e8;">📐 全面支持</h3>
<p>支持内联公式和显示公式,自动识别公式命令和环境。</p>
</div>
""", unsafe_allow_html=True)
with col2:
st.markdown("""
<div class="info-card" style="height: 200px;">
<h3 style="color: #4a86e8;">🎨 多种主题</h3>
<p>提供亮色、暗色和彩色主题,满足不同的阅读偏好。</p>
</div>
""", unsafe_allow_html=True)
with col3:
st.markdown("""
<div class="info-card" style="height: 200px;">
<h3 style="color: #4a86e8;">✏️ 内置编辑器</h3>
<p>编辑和实时预览文档,方便调整和修改内容。</p>
</div>
""", unsafe_allow_html=True)
# 页脚
st.markdown("""
<div style="text-align: center; margin-top: 3rem; padding: 1rem; border-top: 1px solid #ddd;">
<p style="color: #6c757d;">公式文档查看器 © 2025</p>
</div>
""", unsafe_allow_html=True)