radextract / templates /index.html
goelak's picture
Add blog permalink
daa2f7a
<!doctype html>
<html>
<head>
<title>Radiology Report Structuring</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Open Graph / Twitter Card meta tags for rich link previews -->
<meta
property="og:title"
content="RadExtract – Radiology Report Structuring Demo"
/>
<meta
property="og:description"
content="Transform unstructured radiology reports into actionable, structured data instantly. See how Google's Gemini AI + LangExtract revolutionize medical documentation with real-time extraction of findings, impressions, and clinical insights."
/>
<meta property="og:url" content="{{ share_url_for_sharing }}" />
<meta
property="og:image"
content="{{ share_url_for_sharing }}/static/radextract-preview.jpg"
/>
<meta property="og:type" content="website" />
<meta property="og:video" content="{{ share_url_for_sharing }}/static/radextract-preview.mp4" />
<meta property="og:video:secure_url" content="{{ share_url_for_sharing }}/static/radextract-preview.mp4" />
<meta property="og:video:type" content="video/mp4" />
<meta property="og:video:width" content="1920" />
<meta property="og:video:height" content="1080" />
<meta name="twitter:card" content="player" />
<meta
name="twitter:title"
content="RadExtract – Radiology Report Structuring Demo"
/>
<meta
name="twitter:description"
content="Transform unstructured radiology reports into actionable, structured data instantly. See how Google's Gemini AI + LangExtract revolutionize medical documentation with real-time extraction of findings, impressions, and clinical insights."
/>
<meta
name="twitter:image"
content="{{ share_url_for_sharing }}/static/radextract-preview.jpg"
/>
<meta name="twitter:player" content="{{ share_url_for_sharing }}/static/radextract-preview.mp4" />
<meta name="twitter:player:width" content="1920" />
<meta name="twitter:player:height" content="1080" />
<meta name="twitter:player:stream" content="{{ share_url_for_sharing }}/static/radextract-preview.mp4" />
<meta name="twitter:player:stream:content_type" content="video/mp4" />
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg" />
<link rel="shortcut icon" href="/static/favicon.svg" />
<link rel="apple-touch-icon" href="/static/favicon.svg" />
<link rel="stylesheet" href="/static/style.css?v=20250129-video-preview" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Google+Sans:wght@400;500;700&family=Google+Sans+Text:wght@400;500&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght@300;400;500"
rel="stylesheet"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/json-formatter-js@2.3.4/dist/json-formatter.min.css"
/>
</head>
<body class="page-wrapper">
<div class="header-container">
<h1>
<strong>RadExtract</strong>:
<span class="brand-split">Radiology Report Structuring&nbsp;Demo</span>
</h1>
<!-- Top share buttons -->
<div class="share-top">
<span>Share →</span>
<a
class="shr-btn shr-x"
href="https://twitter.com/intent/tweet?text={{ share_text }}"
target="_blank"
rel="noopener"
aria-label="Share on X"
>
<svg viewBox="0 0 24 24" width="20" aria-hidden="true">
<path
fill="currentColor"
d="M23 2.999a9.05 9.05 0 0 1-2.588.71A4.516 4.516 0 0 0 22.36.365a9.04 9.04 0 0 1-2.867 1.096 4.505 4.505 0 0 0-7.67 4.107A12.79 12.79 0 0 1 1.64.896a4.505 4.505 0 0 0 1.396 6.01 4.47 4.47 0 0 1-2.04-.563v.057a4.507 4.507 0 0 0 3.614 4.417 4.522 4.522 0 0 1-2.034.077 4.508 4.508 0 0 0 4.207 3.128A9.03 9.03 0 0 1 0 19.54a12.75 12.75 0 0 0 6.92 2.026c8.304 0 12.846-6.877 12.846-12.837 0-.196-.004-.392-.013-.586A9.17 9.17 0 0 0 23 2.999z"
/>
</svg>
</a>
<a
class="shr-btn shr-li"
href="https://www.linkedin.com/shareArticle?mini=true&url={{ share_url_encoded }}&title={{ linkedin_title }}&summary={{ linkedin_summary }}&source=RadExtract"
target="_blank"
rel="noopener"
aria-label="Share on LinkedIn"
>
<svg viewBox="0 0 24 24" width="20" aria-hidden="true">
<path
fill="currentColor"
d="M4.98 3.5C4.98 5.43 3.43 7 1.5 7S-1.98 5.43-1.98 3.5 0.57 0 2.5 0 4.98 1.57 4.98 3.5zM.02 8h5V24h-5V8zM7.98 8h4.8v2.2h.07c.67-1.27 2.31-2.6 4.76-2.6 5.09 0 6.04 3.35 6.04 7.7V24h-5v-7.7c0-1.84-.03-4.21-2.57-4.21-2.57 0-2.96 1.99-2.96 4.07V24h-5V8z"
/>
</svg>
</a>
</div>
<!-- Attribution block: subtitle + logo -->
<div class="attribution">
<p class="sub-header">
<strong>Powered by LangExtract + Gemini 2.5</strong>
</p>
<!-- Google Research logo -->
<div class="google-research-logo">
<img
src="/static/google-research-logo.svg"
alt="Google Research"
width="174"
height="25"
loading="lazy"
tabindex="-1"
/>
</div>
<!-- Blog link -->
<div class="blog-link-container">
<a
class="blog-link"
href="https://developers.googleblog.com/en/introducing-langextract-a-gemini-powered-information-extraction-library"
target="_blank"
rel="noopener noreferrer"
aria-label="Read about LangExtract on Google for Developers"
>
<span class="material-symbols-outlined blog-icon">article</span>
See the LangExtract Blog Post in Google for Developers
<span class="material-symbols-outlined external-icon">open_in_new</span>
</a>
</div>
</div>
<div class="disclaimer-container">
<div class="disclaimer-box">
<span class="material-symbols-outlined disclaimer-icon">warning</span>
<span class="disclaimer-text"
>This demonstration is for illustrative purposes only to show the
baseline capabilities of LangExtract, the library that powers this
demo. It does not represent a finished or approved product, is not
intended to diagnose or suggest treatment for any disease or
condition, and should not be used for medical advice.</span
>
</div>
<div class="citation-note">
<strong>License & Citation:</strong> If you use
RadExtract or LangExtract in production or
publications, please cite accordingly and acknowledge usage. Use is
subject to the Apache 2.0 License. See
<a
class="banner-link"
href="https://huggingface.co/spaces/google/radextract/blob/main/README.md#disclaimer"
target="_blank"
rel="noopener noreferrer"
>README</a
>&nbsp;for&nbsp;details.
</div>
</div>
<div class="banner card">
<p class="banner-description">
<a
class="banner-link"
href="https://github.com/google/langextract"
target="_blank"
rel="noopener noreferrer"
><strong>LangExtract (LX)</strong></a
>
is a multi-purpose NLP extraction library that uses large language
models such as Gemini to convert free-text into schema-controlled
data. It learns from your few-shot examples (structured using
<strong>LX</strong>'s extraction schema) to identify and extract
information, with every datum linked back to its exact words in the
source.
</p>
<hr class="banner-divider" />
<h3 class="banner-section-title">Demo Overview</h3>
<p class="banner-description">
<strong>RadExtract</strong> uses
<a
class="banner-link"
href="https://github.com/google/langextract"
target="_blank"
rel="noopener noreferrer"
><strong>LangExtract (LX)</strong></a
>
powered by
<a
id="model-link"
class="banner-link"
href="https://cloud.google.com/vertex-ai/generative-ai/docs/models/gemini/2-5-flash"
target="_blank"
rel="noopener noreferrer"
><span id="model-name">Gemini 2.5 Flash</span></a
>
or
<a
class="banner-link"
href="https://cloud.google.com/vertex-ai/generative-ai/docs/models/gemini/2-5-pro"
target="_blank"
rel="noopener noreferrer"
>Gemini 2.5 Pro</a
>
to convert radiology report findings into structured, optimized
radiology reports with highlighted significant findings. By leveraging
a
<a
class="banner-link"
href="https://huggingface.co/spaces/google/radextract/blob/main/prompt_instruction.py"
target="_blank"
rel="noopener noreferrer"
>prompt</a
>
that describes the structuring task with <strong>LX</strong>'s schema
and a
<a
class="banner-link"
href="https://huggingface.co/spaces/google/radextract/blob/main/report_examples.py"
target="_blank"
rel="noopener noreferrer"
>few select examples</a
>, <strong>LX</strong> processes free text into the structured output
shown below. Leveraging Gemini's foundational knowledge,
<strong>RadExtract</strong> can also process imaging modalities beyond
those included in the prompt examples, such as the X-ray and
ultrasound samples available below.
</p>
<p class="banner-description">
<strong>Interactive Features</strong><br />
Each extracted finding is directly grounded by
<strong>LX</strong> (linked precisely back to its original words in
the source text); hover over any structured item to see this exact
textual origin highlighted. <strong>Clinical significance</strong> is
visually highlighted: general findings are marked with yellow
underlines, while significant findings have red&nbsp;underlines.
</p>
<p class="banner-description">
<strong>Clinical Background</strong><br />
Structured reporting helps ensure completeness, reduces ambiguity, and
facilitates data sharing in radiology. For background on the value of
structured radiology reports, see
<a
class="banner-link"
href="https://link.springer.com/article/10.1007/s13244-017-0588-8"
target="_blank"
rel="noopener noreferrer"
>this European Society of Radiology paper</a
>.
</p>
</div>
</div>
<div class="samples-container card">
<h3>Select a Report</h3>
<div class="samples-description">
<div class="instruction-step">
<span class="step-number">1</span> Select a sample or paste your
report
</div>
<div class="instruction-step">
<span class="step-number">2</span> Click "Process" to start for pasted
reports
</div>
<div class="instruction-step">
<span class="step-number">3</span> Hover output findings to highlight
source text
</div>
</div>
<div class="sample-buttons"></div>
<p class="samples-tip tip-desktop">
💡 Try tweaking a sample (remove sections, add extra findings, or paste
your own report) to see how the demo responds.
</p>
<p class="mobile-tip" role="note">
<span class="icon">💡</span>
Tap any sample report to explore the structuring features. The keyboard
stays closed so you can easily scroll and interact with highlighted findings.<br><br>
<strong>Tip:</strong> Custom input is available only on desktop or laptop computers.
If you're viewing this on a mobile device, please switch to a computer to enter your own reports.
</p>
</div>
<div class="interface-options-panel card">
<div class="interface-options-header" data-action="toggle-interface">
<h4 class="interface-options-title">Interface Controls</h4>
<div class="interface-options-summary">
<span>LX Generated Prompt • LX Structured Output • Use Cache</span>
<span
class="material-symbols-outlined expand-icon"
id="interface-expand-icon"
>expand_more</span
>
</div>
</div>
<div
class="interface-options-content"
id="interface-options-content"
style="display: none"
>
<div class="interface-options-grid">
<div class="interface-option">
<div class="option-header">
<span class="material-symbols-outlined option-icon"
>visibility</span
>
<strong>LX Generated Prompt</strong>
</div>
<p class="option-description">
View the complete prompt sent to the model, including task
description, examples, and your input text
</p>
</div>
<div class="interface-option">
<div class="option-header">
<span class="material-symbols-outlined option-icon">code</span>
<strong>LX Structured Output</strong>
</div>
<p class="option-description">
Toggle between the formatted text view and raw LangExtract JSON
data with extraction details
</p>
</div>
<div class="interface-option">
<div class="option-header">
<span class="material-symbols-outlined option-icon">cached</span>
<strong>Use Cache</strong>
</div>
<p class="option-description">
Switch between live model inference and pre-generated Gemini 2.5
Pro cached results for faster testing
</p>
</div>
</div>
<div class="interface-options-note">
<span class="material-symbols-outlined note-icon">info</span>
<span
>These controls are located in the Input and Output headers below
for easy access during interaction.</span
>
</div>
</div>
</div>
<div class="text-area-container card">
<div class="text-area-wrapper input-wrapper">
<div class="input-header">
<h2>Input</h2>
<label class="prompt-toggle"
><input type="checkbox" id="prompt-toggle" /> LX Prompt</label
>
</div>
<div id="input-text-container" class="input-container">
<textarea
id="input-text"
class="large-text-area"
placeholder="Enter radiology report here or load a sample from above..."
spellcheck="false"
autocomplete="off"
autocorrect="off"
autocapitalize="off"
inputmode="none"
></textarea>
<button
id="clear-input"
class="clear-button-overlay"
title="Clear input"
>
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
<div id="prompt-output" class="raw-json" style="display: none"></div>
</div>
<div class="text-area-wrapper" id="output-container">
<div class="output-header">
<h2>Output</h2>
<label class="raw-toggle"
><input type="checkbox" id="raw-toggle" /> LX Data</label
>
</div>
<div id="output-text-container" class="output-container">
<pre
id="output-text"
class="large-text-area output-text"
placeholder="Structured output will appear here..."
></pre>
<div
id="raw-output"
class="raw-json output-text"
style="display: none"
></div>
<button
id="copy-output"
class="copy-button-overlay"
title="Copy output to clipboard"
>
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path
d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"
></path>
</svg>
</button>
<div
id="loading-overlay"
class="loading-overlay"
style="display: none"
>
<div class="spinner"></div>
<div class="loader-text">
<span class="loader-message"
>Running LangExtract with Gemini 2.5 Flash</span
>
</div>
</div>
</div>
</div>
<div class="panel-controls">
<!-- ROW 1 -->
<div class="model-select-container">
<label for="model-select">Model:</label>
<select id="model-select">
<option value="gemini-2.5-flash" selected>Gemini 2.5 Flash</option>
<option value="gemini-2.5-pro">Gemini 2.5 Pro</option>
</select>
</div>
<label class="cache-toggle">
<input type="checkbox" id="cache-toggle" checked />
Use Cache
<span class="cache-status" id="cache-status"></span>
</label>
<!-- ROW 2 (mobile only) -->
<label class="prompt-toggle mobile-toggle">
<input type="checkbox" id="prompt-toggle-mobile" /> LX Prompt
</label>
<label class="raw-toggle mobile-toggle">
<input type="checkbox" id="raw-toggle-mobile" /> LX Data
</label>
</div>
</div>
<div class="action-bar">
<button id="predict-button">Process</button>
<div class="clinical-significance-legend">
<span class="legend-title">Findings:</span>
<span class="legend-item"
><span class="legend-line minor"></span>General</span
>
<span class="legend-item"
><span class="legend-line major"></span>Significant</span
>
<span class="legend-item"
><span class="legend-line grounding"></span>Grounding</span
>
</div>
</div>
<div class="instructions"></div>
<script src="https://cdn.jsdelivr.net/npm/json-formatter-js@2.3.4/dist/json-formatter.umd.js"></script>
<script src="https://cdn.jsdelivr.net/npm/marked@9.1.6/marked.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<script
type="module"
src="/static/script.js?v=20250125-refactored"
></script>
<!-- Bottom share placement (minimal space above footer) -->
<div class="share-bottom">
<span>Share&nbsp;this&nbsp;demo →</span>
<a
class="shr-btn shr-x"
href="https://twitter.com/intent/tweet?text={{ share_text }}"
target="_blank"
rel="noopener"
aria-label="Share on X"
>
<svg viewBox="0 0 24 24" width="24" aria-hidden="true">
<path
fill="currentColor"
d="M23 2.999a9.05 9.05 0 0 1-2.588.71A4.516 4.516 0 0 0 22.36.365a9.04 9.04 0 0 1-2.867 1.096 4.505 4.505 0 0 0-7.67 4.107A12.79 12.79 0 0 1 1.64.896a4.505 4.505 0 0 0 1.396 6.01 4.47 4.47 0 0 1-2.04-.563v.057a4.507 4.507 0 0 0 3.614 4.417 4.522 4.522 0 0 1-2.034.077 4.508 4.508 0 0 0 4.207 3.128A9.03 9.03 0 0 1 0 19.54a12.75 12.75 0 0 0 6.92 2.026c8.304 0 12.846-6.877 12.846-12.837 0-.196-.004-.392-.013-.586A9.17 9.17 0 0 0 23 2.999z"
/>
</svg>
</a>
<a
class="shr-btn shr-li"
href="https://www.linkedin.com/shareArticle?mini=true&url={{ share_url_encoded }}&title={{ linkedin_title }}&summary={{ linkedin_summary }}&source=RadExtract"
target="_blank"
rel="noopener"
aria-label="Share on LinkedIn"
>
<svg viewBox="0 0 24 24" width="24" aria-hidden="true">
<path
fill="currentColor"
d="M4.98 3.5C4.98 5.43 3.43 7 1.5 7S-1.98 5.43-1.98 3.5 0.57 0 2.5 0 4.98 1.57 4.98 3.5zM.02 8h5V24h-5V8zM7.98 8h4.8v2.2h.07c.67-1.27 2.31-2.6 4.76-2.6 5.09 0 6.04 3.35 6.04 7.7V24h-5v-7.7c0-1.84-.03-4.21-2.57-4.21-2.57 0-2.96 1.99-2.96 4.07V24h-5V8z"
/>
</svg>
</a>
</div>
<div class="footer-note">
View this demo’s source on&nbsp;<a
class="banner-link"
href="https://huggingface.co/spaces/google/radextract/tree/main"
target="_blank"
rel="noopener noreferrer"
>Hugging&nbsp;Face&nbsp;Spaces</a
>&nbsp;🤗
</div>
</body>
</html>