Spaces:
Runtime error
Runtime error
File size: 5,582 Bytes
d2457b8 b86b8a9 49e9bd8 d2457b8 14f649b 92da610 49e9bd8 92da610 ae07758 d8e4400 d2457b8 ae07758 d2457b8 3e0ae5e ae07758 d2457b8 49e9bd8 d2457b8 3e0ae5e 49e9bd8 ae07758 7234f68 14f649b 7234f68 ae07758 3e0ae5e d2457b8 3e0ae5e 14f649b 49e9bd8 92da610 49e9bd8 3e0ae5e 49e9bd8 61eea38 33718d6 61eea38 49e9bd8 33718d6 49e9bd8 33718d6 49e9bd8 d2457b8 3e0ae5e 49e9bd8 f96ba11 49e9bd8 d2457b8 b547608 49e9bd8 d2457b8 1a92a4c d2457b8 49e9bd8 1a92a4c 49e9bd8 1a92a4c 49e9bd8 1a92a4c 49e9bd8 d2457b8 49e9bd8 1a92a4c 49e9bd8 f96ba11 49e9bd8 d2457b8 3e0ae5e 49e9bd8 92da610 3e0ae5e 49e9bd8 d8e4400 49e9bd8 f96ba11 61eea38 1a92a4c 3bfeef1 49e9bd8 3e0ae5e 49e9bd8 b547608 3bfeef1 49e9bd8 b07a6cc 3e0ae5e 49e9bd8 61eea38 1a92a4c b547608 f96ba11 49e9bd8 1a92a4c 49e9bd8 1a92a4c 49e9bd8 b547608 2009574 92da610 3e0ae5e 49e9bd8 92da610 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | import os
import gradio as gr
from transformers import pipeline
import torch
from openai import OpenAI
from pypdf import PdfReader
device = "cuda" if torch.cuda.is_available() else "cpu"
vision_pipe = pipeline(
"image-to-text",
model="nlpconnect/vit-gpt2-image-captioning",
device=0 if device == "cuda" else -1
)
api_key = os.environ.get("YUNWU_API_KEY")
if not api_key:
raise RuntimeError("YUNWU_API_KEY not set in Space secrets.")
client = OpenAI(
api_key=api_key,
base_url="https://yunwu.ai/v1"
)
def call_llm(prompt, model="deepseek-chat", temperature=0.2, max_tokens=512):
resp = client.chat.completions.create(
model=model,
messages=[
{
"role": "system",
"content": (
"You are an academic figure interpretation assistant. "
"Write accurate, natural-sounding text for scientific use."
),
},
{"role": "user", "content": prompt},
],
temperature=temperature,
max_tokens=max_tokens,
)
return resp.choices[0].message.content.strip()
def extract_pdf_snippet(pdf_path, max_chars=2500):
if not pdf_path:
return ""
try:
reader = PdfReader(pdf_path)
texts = []
for page in reader.pages:
txt = page.extract_text() or ""
texts.append(txt)
if sum(len(t) for t in texts) > max_chars * 1.5:
break
full = " ".join(texts)
return full[:max_chars]
except Exception:
return ""
def analyze_figure(image, style, pdf_path):
if image is None:
return None, "Please upload a figure first.", "", ""
vision_raw = vision_pipe(image)[0]["generated_text"]
pdf_context = extract_pdf_snippet(pdf_path)
step1_prompt = f"""
You are looking at a scientific figure from a paper.
A vision model produced this rough description:
\"\"\"{vision_raw}\"\"\"
Paper context (may be noisy or incomplete):
\"\"\"{pdf_context}\"\"\"
Task:
Write a clear, paper-style explanation (4β6 sentences) of what the figure shows.
- Describe what is compared on the x-axis/panels and what the y-axis measures.
- Summarize the main pattern/trend across conditions.
- Do NOT invent exact numbers, statistics, or p-values.
- Do NOT restate the full experimental design.
Write in formal academic English, but keep it readable.
"""
step1_text = call_llm(step1_prompt, model="deepseek-chat", max_tokens=420)
step2_prompt = f"""
You are helping a student annotate this scientific figure for a presentation.
Rough visual description:
\"\"\"{vision_raw}\"\"\"
Paper context:
\"\"\"{pdf_context}\"\"\"
Give practical suggestions for how to annotate the figure directly on the image.
Constraints:
- Output 4β6 bullet points.
- Use plain hyphen bullets only (no numbering, no bold, no asterisks, no markdown headings).
- Sound like a helpful human TA, not an AI.
- Focus on labels, arrows, callouts, grouping, legend clarity, and highlighting key contrasts.
"""
step2_text = call_llm(step2_prompt, model="deepseek-chat", temperature=0.4, max_tokens=260)
step2_text = step2_text.replace("**", "").replace("*", "").strip()
style_map = {
"formal": "formal but still plain language, suitable for a report",
"fluency": "smooth, narrative, easy to speak aloud in a presentation",
"simple": "very simple words for quick student notes"
}
style_instruction = style_map.get(style, style_map["fluency"])
step3_prompt = f"""
You are writing a plain-language explanation of the figure for a student.
Paper-style meaning:
\"\"\"{step1_text}\"\"\"
Paper context:
\"\"\"{pdf_context}\"\"\"
Now paraphrase/explain the figure in {style_instruction}.
- 3β5 sentences.
- Keep it accurate to the paper-style meaning above.
- No numbers or p-values unless they are explicitly visible in the figure.
- Make it easy to reuse in slides or homework.
"""
step3_text = call_llm(step3_prompt, model="deepseek-chat", temperature=0.5, max_tokens=240)
return image, step1_text, step2_text, step3_text
with gr.Blocks() as demo:
gr.Markdown("## ChartSmith β AI Figure Explainer (multi-model workflow)")
with gr.Row():
with gr.Column():
img_in = gr.Image(
type="pil",
label="Upload your scientific figure (screenshot is fine)"
)
style = gr.Radio(
["formal", "fluency", "simple"],
value="fluency",
label="Explanation style for Step 3"
)
pdf_in = gr.File(
label="Upload the paper PDF (optional, for context)",
type="filepath"
)
run_btn = gr.Button("Run workflow", variant="primary")
with gr.Column():
preview_img = gr.Image(label="Figure preview")
step1_box = gr.Textbox(
label="Step 1: Explanation of what the figure shows (paper-style)",
lines=8
)
step2_box = gr.Textbox(
label="Step 2: Suggestions for annotating the figure",
lines=7
)
step3_box = gr.Textbox(
label="Step 3: Plain-language explanation (style-adapted)",
lines=6
)
run_btn.click(
analyze_figure,
inputs=[img_in, style, pdf_in],
outputs=[preview_img, step1_box, step2_box, step3_box],
)
if __name__ == "__main__":
demo.launch() |