Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,85 +1,191 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
from transformers import pipeline
|
| 3 |
from PIL import Image, ImageEnhance
|
|
|
|
| 4 |
|
|
|
|
| 5 |
|
|
|
|
| 6 |
vision_pipe = pipeline(
|
| 7 |
"image-to-text",
|
| 8 |
-
model="
|
| 9 |
device=-1 # CPU
|
| 10 |
)
|
| 11 |
|
|
|
|
| 12 |
text_pipe = pipeline(
|
| 13 |
"text2text-generation",
|
| 14 |
model="google/flan-t5-base",
|
| 15 |
max_length=256,
|
| 16 |
-
|
|
|
|
|
|
|
| 17 |
)
|
| 18 |
|
| 19 |
|
| 20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
if image is None:
|
| 22 |
return None, "请先上传图表。", "", None, "", ""
|
| 23 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
raw_caption = vision_pipe(image)[0]["generated_text"]
|
| 25 |
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
"
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
academic_desc = text_pipe(prompt_academic)[0]["generated_text"]
|
| 37 |
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
caption_text = text_pipe(caption_prompt)[0]["generated_text"]
|
| 45 |
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
summary_text = text_pipe(summary_prompt)[0]["generated_text"]
|
| 54 |
|
|
|
|
| 55 |
if language == "中文":
|
| 56 |
academic_desc_out = text_pipe(
|
| 57 |
-
f"Translate
|
| 58 |
)[0]["generated_text"]
|
| 59 |
caption_text = text_pipe(
|
| 60 |
-
f"Translate
|
| 61 |
)[0]["generated_text"]
|
| 62 |
summary_text = text_pipe(
|
| 63 |
-
f"Translate
|
| 64 |
)[0]["generated_text"]
|
| 65 |
else:
|
| 66 |
academic_desc_out = academic_desc
|
| 67 |
|
|
|
|
| 68 |
img_rgb = image.convert("RGB")
|
| 69 |
enhancer_c = ImageEnhance.Contrast(img_rgb)
|
| 70 |
-
img_c = enhancer_c.enhance(1.4)
|
| 71 |
enhancer_b = ImageEnhance.Brightness(img_c)
|
| 72 |
-
enhanced_image = enhancer_b.enhance(1.1)
|
| 73 |
|
| 74 |
return image, raw_caption, academic_desc_out, enhanced_image, caption_text, summary_text
|
| 75 |
-
|
|
|
|
|
|
|
| 76 |
|
| 77 |
with gr.Blocks() as demo:
|
| 78 |
-
gr.Markdown("# ChartSmith – AI 论文图表生成助手(
|
| 79 |
|
| 80 |
with gr.Row():
|
| 81 |
with gr.Column():
|
| 82 |
img_in = gr.Image(type="pil", label="上传你的学术图表(截图也可以)")
|
|
|
|
| 83 |
style = gr.Dropdown(
|
| 84 |
["Formal academic", "Infographic", "Magazine-style"],
|
| 85 |
value="Formal academic",
|
|
@@ -90,14 +196,14 @@ with gr.Blocks() as demo:
|
|
| 90 |
with gr.Column():
|
| 91 |
orig_img = gr.Image(label="原始图表")
|
| 92 |
raw_caption_box = gr.Textbox(label="Step 2: 初步自动描述(Vision-LLM)")
|
| 93 |
-
academic_box = gr.Textbox(label="Step 3: 学术化解释(
|
| 94 |
enhanced_img = gr.Image(label="Step 4: 简单增强后的图示(对比度+亮度提升)")
|
| 95 |
caption_box = gr.Textbox(label="Step 5: 自动生成图注(Caption)")
|
| 96 |
summary_box = gr.Textbox(label="Step 5: 图表相关简短摘要 / 讨论")
|
| 97 |
|
| 98 |
btn.click(
|
| 99 |
analyze_and_enhance,
|
| 100 |
-
inputs=[img_in, style, language],
|
| 101 |
outputs=[orig_img, raw_caption_box, academic_box, enhanced_img, caption_box, summary_box]
|
| 102 |
)
|
| 103 |
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
from transformers import pipeline
|
| 3 |
from PIL import Image, ImageEnhance
|
| 4 |
+
from pypdf import PdfReader
|
| 5 |
|
| 6 |
+
# ===================== 1. 加载模型(CPU + flan-t5-base) =====================
|
| 7 |
|
| 8 |
+
# 图像 -> 文本说明:图像描述模型
|
| 9 |
vision_pipe = pipeline(
|
| 10 |
"image-to-text",
|
| 11 |
+
model="microsoft/git-base",
|
| 12 |
device=-1 # CPU
|
| 13 |
)
|
| 14 |
|
| 15 |
+
# 文本改写 / 生成:flan-t5-base,带防重复参数
|
| 16 |
text_pipe = pipeline(
|
| 17 |
"text2text-generation",
|
| 18 |
model="google/flan-t5-base",
|
| 19 |
max_length=256,
|
| 20 |
+
num_beams=4,
|
| 21 |
+
no_repeat_ngram_size=3, # 避免重复句子
|
| 22 |
+
device=-1 # CPU
|
| 23 |
)
|
| 24 |
|
| 25 |
|
| 26 |
+
# ===================== 2. 从论文 PDF 提取上下文 =====================
|
| 27 |
+
|
| 28 |
+
def extract_paper_context(paper_file):
|
| 29 |
+
"""
|
| 30 |
+
paper_file: gr.File 传进来的对象,一般是临时文件路径(str)
|
| 31 |
+
返回:截断后的论文文本字符串
|
| 32 |
+
"""
|
| 33 |
+
if paper_file is None:
|
| 34 |
+
return ""
|
| 35 |
+
|
| 36 |
+
try:
|
| 37 |
+
# gradio 通常会传一个路径字符串
|
| 38 |
+
path = paper_file if isinstance(paper_file, str) else paper_file.name
|
| 39 |
+
reader = PdfReader(path)
|
| 40 |
+
text = ""
|
| 41 |
+
# 只取前几页,避免太长
|
| 42 |
+
for i, page in enumerate(reader.pages[:3]):
|
| 43 |
+
page_text = page.extract_text() or ""
|
| 44 |
+
text += page_text + "\n"
|
| 45 |
+
# 截断,防止太长
|
| 46 |
+
text = text.strip()[:4000]
|
| 47 |
+
return text
|
| 48 |
+
except Exception as e:
|
| 49 |
+
print("Error reading PDF:", e)
|
| 50 |
+
return ""
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def summarize_paper_context(raw_text):
|
| 54 |
+
"""
|
| 55 |
+
用 flan-t5-base 把论文原文压缩成跟图相关的上下文总结
|
| 56 |
+
"""
|
| 57 |
+
if not raw_text:
|
| 58 |
+
return ""
|
| 59 |
+
|
| 60 |
+
prompt = f"""
|
| 61 |
+
You are given part of a scientific paper.
|
| 62 |
+
Summarize in 4-6 sentences the context that is most relevant for understanding one specific result figure.
|
| 63 |
+
Focus on:
|
| 64 |
+
- the research question or hypothesis,
|
| 65 |
+
- the main variables or conditions,
|
| 66 |
+
- what is being compared or measured.
|
| 67 |
+
|
| 68 |
+
Paper text:
|
| 69 |
+
{raw_text}
|
| 70 |
+
|
| 71 |
+
Relevant context summary:
|
| 72 |
+
"""
|
| 73 |
+
summary = text_pipe(prompt)[0]["generated_text"]
|
| 74 |
+
return summary
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
# ===================== 3. 核心工作流函数 =====================
|
| 78 |
+
|
| 79 |
+
def analyze_and_enhance(image, style, language, paper_file):
|
| 80 |
if image is None:
|
| 81 |
return None, "请先上传图表。", "", None, "", ""
|
| 82 |
|
| 83 |
+
# -------- (可选) 从论文中抽取上下文 --------
|
| 84 |
+
paper_raw = extract_paper_context(paper_file)
|
| 85 |
+
paper_context = summarize_paper_context(paper_raw) if paper_raw else ""
|
| 86 |
+
|
| 87 |
+
# -------- Step 2: Vision-LLM → 初步自动描述 --------
|
| 88 |
raw_caption = vision_pipe(image)[0]["generated_text"]
|
| 89 |
|
| 90 |
+
# 如果 vision 没认出是图表,就用一个安全的默认描述,避免 T5 乱写
|
| 91 |
+
rc = raw_caption.lower()
|
| 92 |
+
if not any(k in rc for k in ["bar", "chart", "graph", "plot", "curve", "line"]):
|
| 93 |
+
raw_caption = "a bar chart comparing multiple experimental groups under different conditions"
|
| 94 |
+
|
| 95 |
+
# -------- Step 3: LLM → 学术化扩写(结合论文上下文) --------
|
| 96 |
+
if paper_context:
|
| 97 |
+
context_part = f"""
|
| 98 |
+
Here is the relevant context from the paper that may help you interpret the figure:
|
| 99 |
+
|
| 100 |
+
{paper_context}
|
| 101 |
+
"""
|
| 102 |
+
else:
|
| 103 |
+
context_part = "\n(No additional paper context is available; rely only on the figure description.)\n"
|
| 104 |
+
|
| 105 |
+
prompt_academic = f"""
|
| 106 |
+
You are writing the Results section of a scientific paper.
|
| 107 |
+
|
| 108 |
+
{context_part}
|
| 109 |
+
|
| 110 |
+
Based on the brief description of a figure below, write a structured academic
|
| 111 |
+
description of the figure in 3–4 sentences. Follow this structure:
|
| 112 |
+
|
| 113 |
+
1. Identify the general type of figure (e.g., bar chart, line graph).
|
| 114 |
+
2. Describe in generic terms what is shown on the horizontal axis
|
| 115 |
+
(e.g., experimental conditions, groups, time points).
|
| 116 |
+
3. Describe in generic terms what is shown on the vertical axis
|
| 117 |
+
(e.g., response level, measurement value, percentage).
|
| 118 |
+
4. Describe the overall trend (increase, decrease, or differences between groups).
|
| 119 |
+
5. Summarize the main comparison or key pattern, making sure it is consistent
|
| 120 |
+
with the paper context above.
|
| 121 |
+
|
| 122 |
+
Do NOT repeat any sentence. Do NOT invent specific numerical values or disease names.
|
| 123 |
+
Keep it factual, generic, and neutral.
|
| 124 |
+
|
| 125 |
+
Figure description: {raw_caption}
|
| 126 |
+
"""
|
| 127 |
academic_desc = text_pipe(prompt_academic)[0]["generated_text"]
|
| 128 |
|
| 129 |
+
# -------- Step 5: 生成图注 Caption --------
|
| 130 |
+
caption_prompt = f"""
|
| 131 |
+
Write a concise 1–2 sentence figure caption for an academic paper
|
| 132 |
+
based on the following description of a figure.
|
| 133 |
+
The caption should mention the type of figure and highlight the main comparison
|
| 134 |
+
or trend, and it should be consistent with the paper context above.
|
| 135 |
+
Do not include fabricated numbers.
|
| 136 |
+
|
| 137 |
+
Description: {academic_desc}
|
| 138 |
+
|
| 139 |
+
Caption:
|
| 140 |
+
"""
|
| 141 |
caption_text = text_pipe(caption_prompt)[0]["generated_text"]
|
| 142 |
|
| 143 |
+
# -------- Step 5: 生成简短摘要 / 讨论 Paragraph --------
|
| 144 |
+
summary_prompt = f"""
|
| 145 |
+
Write a short 3–4 sentence paragraph for the Results section of a scientific paper,
|
| 146 |
+
explaining the key trend and message of this figure. Assume the reader has NOT seen
|
| 147 |
+
the figure and rely only on the description below and the paper context.
|
| 148 |
+
Do not repeat sentences or invent exact numerical values.
|
| 149 |
+
|
| 150 |
+
Description: {academic_desc}
|
| 151 |
+
|
| 152 |
+
Paragraph:
|
| 153 |
+
"""
|
| 154 |
summary_text = text_pipe(summary_prompt)[0]["generated_text"]
|
| 155 |
|
| 156 |
+
# -------- 语言切换(英文 / 中文) --------
|
| 157 |
if language == "中文":
|
| 158 |
academic_desc_out = text_pipe(
|
| 159 |
+
f"Translate the following academic description into Chinese:\n{academic_desc}"
|
| 160 |
)[0]["generated_text"]
|
| 161 |
caption_text = text_pipe(
|
| 162 |
+
f"Translate the following figure caption into Chinese:\n{caption_text}"
|
| 163 |
)[0]["generated_text"]
|
| 164 |
summary_text = text_pipe(
|
| 165 |
+
f"Translate the following paragraph into Chinese:\n{summary_text}"
|
| 166 |
)[0]["generated_text"]
|
| 167 |
else:
|
| 168 |
academic_desc_out = academic_desc
|
| 169 |
|
| 170 |
+
# -------- Step 4: 图像简单增强(对比度 + 亮度),让图表更清晰 --------
|
| 171 |
img_rgb = image.convert("RGB")
|
| 172 |
enhancer_c = ImageEnhance.Contrast(img_rgb)
|
| 173 |
+
img_c = enhancer_c.enhance(1.4) # 对比度 +40%
|
| 174 |
enhancer_b = ImageEnhance.Brightness(img_c)
|
| 175 |
+
enhanced_image = enhancer_b.enhance(1.1) # 略微提亮
|
| 176 |
|
| 177 |
return image, raw_caption, academic_desc_out, enhanced_image, caption_text, summary_text
|
| 178 |
+
|
| 179 |
+
|
| 180 |
+
# ===================== 4. Gradio 界面 =====================
|
| 181 |
|
| 182 |
with gr.Blocks() as demo:
|
| 183 |
+
gr.Markdown("# ChartSmith – AI 论文图表生成助手(支持上传论文上下文)")
|
| 184 |
|
| 185 |
with gr.Row():
|
| 186 |
with gr.Column():
|
| 187 |
img_in = gr.Image(type="pil", label="上传你的学术图表(截图也可以)")
|
| 188 |
+
paper_file = gr.File(label="上传整篇论文 PDF(可选,用于更准确解释图)", file_types=[".pdf"])
|
| 189 |
style = gr.Dropdown(
|
| 190 |
["Formal academic", "Infographic", "Magazine-style"],
|
| 191 |
value="Formal academic",
|
|
|
|
| 196 |
with gr.Column():
|
| 197 |
orig_img = gr.Image(label="原始图表")
|
| 198 |
raw_caption_box = gr.Textbox(label="Step 2: 初步自动描述(Vision-LLM)")
|
| 199 |
+
academic_box = gr.Textbox(label="Step 3: 学术化解释(结合论文上下文)")
|
| 200 |
enhanced_img = gr.Image(label="Step 4: 简单增强后的图示(对比度+亮度提升)")
|
| 201 |
caption_box = gr.Textbox(label="Step 5: 自动生成图注(Caption)")
|
| 202 |
summary_box = gr.Textbox(label="Step 5: 图表相关简短摘要 / 讨论")
|
| 203 |
|
| 204 |
btn.click(
|
| 205 |
analyze_and_enhance,
|
| 206 |
+
inputs=[img_in, style, language, paper_file],
|
| 207 |
outputs=[orig_img, raw_caption_box, academic_box, enhanced_img, caption_box, summary_box]
|
| 208 |
)
|
| 209 |
|