Upload 3 files
Browse files- .gitattributes +1 -0
- assets/artemis.webp +3 -0
- data.txt +47 -0
- index.html +761 -18
.gitattributes
CHANGED
|
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
assets/artemis.webp filter=lfs diff=lfs merge=lfs -text
|
assets/artemis.webp
ADDED
|
Git LFS Details
|
data.txt
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Artemis II
|
| 2 |
+
|
| 3 |
+
Artemis II is a planned lunar flyby mission under the Artemis program, scheduled to launch on April 1, 2026 from the Kennedy Space Center in Cape Canaveral, Florida. The ten-day mission will carry NASA astronauts Reid Wiseman, Victor Glover, and Christina Koch, along with Canadian Space Agency astronaut Jeremy Hansen, on a free-return trajectory around the Moon and back to Earth. It will be the second flight of the Space Launch System (SLS), the first crewed mission of the Orion spacecraft, and the first crewed mission beyond low Earth orbit since Apollo 17 in 1972.
|
| 4 |
+
|
| 5 |
+
The mission is expected to set several human spaceflight records. Glover would become the first person of color, Koch the first woman, and Hansen the first non-U.S. citizen to travel beyond low Earth orbit. At a distance of approximately 4,700 miles (7,600 km) beyond the Moon and an atmospheric reentry speed of about 25,000 miles per hour (40,000 km/h), the mission would exceed previous crewed flight distance and reentry speed.
|
| 6 |
+
|
| 7 |
+
Artemis II is a flight test supporting subsequent Artemis missions, which are planned to return humans to the Moon in 2028 for the first time since the Apollo program. Its planned free-return trajectory closely resembles that flown by Apollo 13.
|
| 8 |
+
|
| 9 |
+
## History
|
| 10 |
+
|
| 11 |
+
### Hardware development and integration
|
| 12 |
+
|
| 13 |
+
RS-25 engines were installed on the core stage in New Orleans by September 2023. The fully outfitted core stage was delivered to KSC in July 2024. Rocket stacking began on November 20, 2024, and was completed on October 20, 2025. On January 18, 2026, the integrated SLS rocket, Orion capsule, and launch tower were rolled out to Launch Complex 39B.
|
| 14 |
+
|
| 15 |
+
### Launch date
|
| 16 |
+
|
| 17 |
+
The launch date was repeatedly delayed from initial estimates of 2019β2021. In December 2024, the launch was delayed to April 2026 due to engineering investigations into issues with the life support system and heat shield. The earliest launch window was set for early February 2026, but a liquid hydrogen leak during a wet dress rehearsal and a subsequent helium flow issue caused further delays. After a Flight Readiness Review on March 12, seven launch windows were announced for April 1β6 and April 30, with the first at 6:24 pm EDT, April 1.
|
| 18 |
+
|
| 19 |
+
### Heat shield concerns
|
| 20 |
+
|
| 21 |
+
Following the uncrewed Artemis I mission in November 2022, NASA identified unexpected erosion of Orion's ablative heat shield after atmospheric reentry. Post-flight inspections found areas of char loss in the AVCOAT material that eroded more extensively than predicted. NASA engineers determined the char loss was caused by trapped gases leading to cracking during reentry. Rather than replacing the heat shield, NASA elected to modify the reentry trajectory by increasing the descent angle, reducing time in the thermal environment. Additional testing showed the capsule would remain intact under conditions exceeding those expected during mission reentry. Design changes addressing AVCOAT permeability are planned for Artemis III.
|
| 22 |
+
|
| 23 |
+
## Crew
|
| 24 |
+
|
| 25 |
+
Artemis II will be crewed by four astronauts: commander Reid Wiseman (NASA), pilot Victor Glover (NASA), mission specialist Christina Koch (NASA), along with mission specialist Jeremy Hansen (Canadian Space Agency). Glover would become the first person of color, Koch the first woman, and Hansen the first non-American to travel around the Moon. This mission will break the record for the most people in deep space at once, set at three during Apollo 8 in 1968.
|
| 26 |
+
|
| 27 |
+
## Mission
|
| 28 |
+
|
| 29 |
+
The mission plan sends four astronauts in the first crewed Orion spacecraft on a lunar flyby using the Block 1 variant of the Space Launch System. The profile includes multiple departure burns and a free-return trajectory from the Moon. Orion will first enter a high Earth orbit, where the crew will perform spacecraft checkouts and proximity operations with the spent ICPS. It will then perform a translunar injection burn, fly around the Moon at approximately 4,047 miles (6,513 km) from the far-side surface, and return to Earth.
|
| 30 |
+
|
| 31 |
+
Orion will re-enter Earth's atmosphere at approximately 25,000 miles per hour (40,000 km/h), the fastest reentry ever attempted. Due to heat shield concerns from Artemis I, mission managers replaced the planned skip reentry with a steeper entry profile. Splashdown is planned in the Pacific Ocean off San Diego.
|
| 32 |
+
|
| 33 |
+
### Optical communications
|
| 34 |
+
|
| 35 |
+
Artemis II will test optical communications using the Orion Artemis II Optical Communications System (O2O), sending data to Earth at up to 260 megabits per second via ground stations in California and New Mexico.
|
| 36 |
+
|
| 37 |
+
### Science payloads
|
| 38 |
+
|
| 39 |
+
NASA will fly AVATAR (A Virtual Astronaut Tissue Analog Response), which mimics individual astronaut organs, marking its first test outside the ISS and Van Allen Belt. The ARCHAR payload will monitor crew movement and sleep patterns, and test immune biomarkers through saliva samples to study the effects of radiation and isolation during deep space flight.
|
| 40 |
+
|
| 41 |
+
## CubeSat secondary payloads
|
| 42 |
+
|
| 43 |
+
Five CubeSats from international Artemis Accords signatories will fly aboard the mission: Germany's TACHELES (testing electrical components for lunar vehicles), Argentina's ATENEA (radiation shielding and communication testing), Korea's K-RadCube (space radiation effects on human tissue analogues), Saudi Arabia's Space Weather CubeSat-1 (space weather measurements), and an Avionics Unit.
|
| 44 |
+
|
| 45 |
+
## Similar missions
|
| 46 |
+
|
| 47 |
+
Artemis II's objectives are comparable to Apollo 8, the first crewed lunar mission in 1968. Unlike Apollo 8 and Apollo 10, which orbited the Moon, Artemis II will fly a free-return trajectory like Apollo 13. While Apollo 13 came within 158 miles (254 km) of the lunar surface, Artemis II's closest approach will be ~4,700 miles (7,600 km).
|
index.html
CHANGED
|
@@ -1,19 +1,762 @@
|
|
| 1 |
-
<!
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
</html>
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
|
| 4 |
+
<head>
|
| 5 |
+
<meta charset="UTF-8">
|
| 6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 7 |
+
<title>LFM2.5 Summarizer | WebGPU</title>
|
| 8 |
+
<style>
|
| 9 |
+
:root {
|
| 10 |
+
--bg: #0f1117;
|
| 11 |
+
--surface: #1a1d27;
|
| 12 |
+
--surface-hover: #222632;
|
| 13 |
+
--border: #2a2e3b;
|
| 14 |
+
--text: #e4e4e7;
|
| 15 |
+
--text-muted: #8b8fa3;
|
| 16 |
+
--accent: #6366f1;
|
| 17 |
+
--accent-glow: rgba(99, 102, 241, 0.25);
|
| 18 |
+
--accent-light: #818cf8;
|
| 19 |
+
--radius: 12px;
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
* {
|
| 23 |
+
margin: 0;
|
| 24 |
+
padding: 0;
|
| 25 |
+
box-sizing: border-box;
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
body {
|
| 29 |
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
|
| 30 |
+
background: var(--bg);
|
| 31 |
+
color: var(--text);
|
| 32 |
+
min-height: 100vh;
|
| 33 |
+
line-height: 1.7;
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
/* Layout */
|
| 37 |
+
main {
|
| 38 |
+
max-width: 1100px;
|
| 39 |
+
margin: 0 auto;
|
| 40 |
+
padding: 2.5rem 2rem 6rem;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
.article-layout {
|
| 44 |
+
display: grid;
|
| 45 |
+
grid-template-columns: 1fr 280px;
|
| 46 |
+
gap: 2.5rem;
|
| 47 |
+
align-items: start;
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
.article-aside {
|
| 51 |
+
position: sticky;
|
| 52 |
+
top: 2.5rem;
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
.article-figure {
|
| 56 |
+
border-radius: var(--radius);
|
| 57 |
+
overflow: hidden;
|
| 58 |
+
border: 1px solid var(--border);
|
| 59 |
+
background: var(--surface);
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
.article-figure img {
|
| 63 |
+
width: 100%;
|
| 64 |
+
display: block;
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
.article-figure figcaption {
|
| 68 |
+
padding: 10px 14px;
|
| 69 |
+
font-size: 0.78rem;
|
| 70 |
+
line-height: 1.5;
|
| 71 |
+
color: var(--text-muted);
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
@media (max-width: 768px) {
|
| 75 |
+
.article-layout {
|
| 76 |
+
grid-template-columns: 1fr;
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
.article-aside {
|
| 80 |
+
position: static;
|
| 81 |
+
order: -1;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
.article-figure {
|
| 85 |
+
max-width: 320px;
|
| 86 |
+
}
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
/* Article typography */
|
| 90 |
+
.article-content h1 {
|
| 91 |
+
font-size: 2.2rem;
|
| 92 |
+
font-weight: 800;
|
| 93 |
+
letter-spacing: -0.03em;
|
| 94 |
+
margin-bottom: 1.5rem;
|
| 95 |
+
line-height: 1.2;
|
| 96 |
+
background: linear-gradient(135deg, var(--text), var(--text-muted));
|
| 97 |
+
-webkit-background-clip: text;
|
| 98 |
+
-webkit-text-fill-color: transparent;
|
| 99 |
+
background-clip: text;
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
.article-content h2 {
|
| 103 |
+
font-size: 1.5rem;
|
| 104 |
+
font-weight: 700;
|
| 105 |
+
letter-spacing: -0.02em;
|
| 106 |
+
margin-top: 2.5rem;
|
| 107 |
+
margin-bottom: 1rem;
|
| 108 |
+
padding-top: 1.5rem;
|
| 109 |
+
border-top: 1px solid var(--border);
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
.article-content h3 {
|
| 113 |
+
font-size: 1.15rem;
|
| 114 |
+
font-weight: 600;
|
| 115 |
+
margin-top: 2rem;
|
| 116 |
+
margin-bottom: 0.75rem;
|
| 117 |
+
color: var(--text-muted);
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
.article-content h4 {
|
| 121 |
+
font-size: 1.02rem;
|
| 122 |
+
font-weight: 600;
|
| 123 |
+
margin-top: 1.5rem;
|
| 124 |
+
margin-bottom: 0.5rem;
|
| 125 |
+
color: var(--text-muted);
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
.article-content p {
|
| 129 |
+
margin-bottom: 1.25rem;
|
| 130 |
+
font-size: 1.02rem;
|
| 131 |
+
position: relative;
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
/* Hoverable paragraphs with summarize button */
|
| 135 |
+
.article-content p.hoverable {
|
| 136 |
+
padding: 10px 14px;
|
| 137 |
+
border-radius: 8px;
|
| 138 |
+
transition: background 0.2s;
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
.article-content p.hoverable:hover {
|
| 142 |
+
background: var(--surface);
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
.summarize-btn {
|
| 146 |
+
position: absolute;
|
| 147 |
+
top: 8px;
|
| 148 |
+
right: 8px;
|
| 149 |
+
display: flex;
|
| 150 |
+
align-items: center;
|
| 151 |
+
gap: 5px;
|
| 152 |
+
padding: 5px 12px;
|
| 153 |
+
border: 1px solid var(--border);
|
| 154 |
+
border-radius: 7px;
|
| 155 |
+
background: var(--surface);
|
| 156 |
+
color: var(--accent-light);
|
| 157 |
+
font-size: 0.75rem;
|
| 158 |
+
font-weight: 600;
|
| 159 |
+
cursor: pointer;
|
| 160 |
+
opacity: 0;
|
| 161 |
+
pointer-events: none;
|
| 162 |
+
transition: all 0.15s;
|
| 163 |
+
white-space: nowrap;
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
.summarize-btn svg {
|
| 167 |
+
flex-shrink: 0;
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
.article-content p.hoverable:hover .summarize-btn {
|
| 171 |
+
opacity: 1;
|
| 172 |
+
pointer-events: auto;
|
| 173 |
+
}
|
| 174 |
+
|
| 175 |
+
.summarize-btn:hover {
|
| 176 |
+
background: var(--surface-hover);
|
| 177 |
+
border-color: var(--accent);
|
| 178 |
+
box-shadow: 0 0 12px var(--accent-glow);
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
/* Summary result block */
|
| 182 |
+
.summary-block {
|
| 183 |
+
background: rgba(99, 102, 241, 0.06);
|
| 184 |
+
border-radius: 8px;
|
| 185 |
+
padding: 14px 16px;
|
| 186 |
+
margin: 1.25rem 0;
|
| 187 |
+
}
|
| 188 |
+
|
| 189 |
+
.summary-block .label {
|
| 190 |
+
display: inline-flex;
|
| 191 |
+
align-items: center;
|
| 192 |
+
gap: 5px;
|
| 193 |
+
font-size: 0.68rem;
|
| 194 |
+
font-weight: 700;
|
| 195 |
+
text-transform: uppercase;
|
| 196 |
+
letter-spacing: 0.08em;
|
| 197 |
+
color: var(--accent-light);
|
| 198 |
+
margin-bottom: 4px;
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
.summary-block .output {
|
| 202 |
+
margin: 0;
|
| 203 |
+
font-size: 1.02rem;
|
| 204 |
+
line-height: 1.7;
|
| 205 |
+
}
|
| 206 |
+
|
| 207 |
+
.summary-block .stats {
|
| 208 |
+
display: inline-flex;
|
| 209 |
+
align-items: center;
|
| 210 |
+
gap: 6px;
|
| 211 |
+
font-size: 0.72rem;
|
| 212 |
+
color: var(--text-muted);
|
| 213 |
+
margin-top: 8px;
|
| 214 |
+
padding-top: 8px;
|
| 215 |
+
border-top: 1px solid var(--border);
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
.summary-block .stats span {
|
| 219 |
+
color: var(--accent-light);
|
| 220 |
+
font-weight: 600;
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
/* Spinner */
|
| 224 |
+
@keyframes spin {
|
| 225 |
+
to { transform: rotate(360deg); }
|
| 226 |
+
}
|
| 227 |
+
|
| 228 |
+
.spinner {
|
| 229 |
+
display: inline-block;
|
| 230 |
+
width: 10px;
|
| 231 |
+
height: 10px;
|
| 232 |
+
border: 1.5px solid var(--accent-glow);
|
| 233 |
+
border-top-color: var(--accent-light);
|
| 234 |
+
border-radius: 50%;
|
| 235 |
+
animation: spin 0.6s linear infinite;
|
| 236 |
+
}
|
| 237 |
+
|
| 238 |
+
/* Chat widget */
|
| 239 |
+
.chat-widget {
|
| 240 |
+
position: fixed;
|
| 241 |
+
bottom: 24px;
|
| 242 |
+
right: 24px;
|
| 243 |
+
z-index: 150;
|
| 244 |
+
display: flex;
|
| 245 |
+
flex-direction: column;
|
| 246 |
+
align-items: flex-end;
|
| 247 |
+
gap: 10px;
|
| 248 |
+
width: 400px;
|
| 249 |
+
max-width: calc(100vw - 48px);
|
| 250 |
+
}
|
| 251 |
+
|
| 252 |
+
/* Response bubble */
|
| 253 |
+
.chat-response {
|
| 254 |
+
width: 100%;
|
| 255 |
+
background: var(--surface);
|
| 256 |
+
border: 1px solid var(--border);
|
| 257 |
+
border-radius: 14px;
|
| 258 |
+
padding: 16px;
|
| 259 |
+
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.5);
|
| 260 |
+
display: none;
|
| 261 |
+
animation: bubbleIn 0.2s ease-out;
|
| 262 |
+
max-height: 50vh;
|
| 263 |
+
overflow-y: auto;
|
| 264 |
+
}
|
| 265 |
+
|
| 266 |
+
@keyframes bubbleIn {
|
| 267 |
+
from { opacity: 0; transform: translateY(8px) scale(0.97); }
|
| 268 |
+
to { opacity: 1; transform: translateY(0) scale(1); }
|
| 269 |
+
}
|
| 270 |
+
|
| 271 |
+
.chat-response.visible {
|
| 272 |
+
display: block;
|
| 273 |
+
}
|
| 274 |
+
|
| 275 |
+
.chat-response-header {
|
| 276 |
+
display: flex;
|
| 277 |
+
align-items: center;
|
| 278 |
+
justify-content: space-between;
|
| 279 |
+
margin-bottom: 8px;
|
| 280 |
+
}
|
| 281 |
+
|
| 282 |
+
.chat-response .chat-label {
|
| 283 |
+
display: inline-flex;
|
| 284 |
+
align-items: center;
|
| 285 |
+
gap: 5px;
|
| 286 |
+
font-size: 0.65rem;
|
| 287 |
+
font-weight: 700;
|
| 288 |
+
text-transform: uppercase;
|
| 289 |
+
letter-spacing: 0.08em;
|
| 290 |
+
color: var(--accent-light);
|
| 291 |
+
}
|
| 292 |
+
|
| 293 |
+
.chat-close {
|
| 294 |
+
width: 24px;
|
| 295 |
+
height: 24px;
|
| 296 |
+
border: none;
|
| 297 |
+
border-radius: 6px;
|
| 298 |
+
background: transparent;
|
| 299 |
+
color: var(--text-muted);
|
| 300 |
+
cursor: pointer;
|
| 301 |
+
display: flex;
|
| 302 |
+
align-items: center;
|
| 303 |
+
justify-content: center;
|
| 304 |
+
transition: all 0.15s;
|
| 305 |
+
flex-shrink: 0;
|
| 306 |
+
}
|
| 307 |
+
|
| 308 |
+
.chat-close:hover {
|
| 309 |
+
background: var(--surface-hover);
|
| 310 |
+
color: var(--text);
|
| 311 |
+
}
|
| 312 |
+
|
| 313 |
+
.chat-response .chat-question {
|
| 314 |
+
font-size: 0.8rem;
|
| 315 |
+
color: var(--text-muted);
|
| 316 |
+
margin-bottom: 8px;
|
| 317 |
+
padding-bottom: 8px;
|
| 318 |
+
border-bottom: 1px solid var(--border);
|
| 319 |
+
font-style: italic;
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
.chat-response .chat-text {
|
| 323 |
+
margin: 0;
|
| 324 |
+
font-size: 0.9rem;
|
| 325 |
+
line-height: 1.6;
|
| 326 |
+
}
|
| 327 |
+
|
| 328 |
+
.chat-response .chat-stats {
|
| 329 |
+
font-size: 0.7rem;
|
| 330 |
+
color: var(--text-muted);
|
| 331 |
+
margin-top: 8px;
|
| 332 |
+
padding-top: 8px;
|
| 333 |
+
border-top: 1px solid var(--border);
|
| 334 |
+
}
|
| 335 |
+
|
| 336 |
+
.chat-response .chat-stats span {
|
| 337 |
+
color: var(--accent-light);
|
| 338 |
+
font-weight: 600;
|
| 339 |
+
}
|
| 340 |
+
|
| 341 |
+
/* Input row */
|
| 342 |
+
.chat-input-row {
|
| 343 |
+
display: flex;
|
| 344 |
+
gap: 8px;
|
| 345 |
+
align-items: center;
|
| 346 |
+
width: 100%;
|
| 347 |
+
background: var(--surface);
|
| 348 |
+
border: 1px solid var(--border);
|
| 349 |
+
border-radius: 12px;
|
| 350 |
+
padding: 6px 6px 6px 16px;
|
| 351 |
+
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.4);
|
| 352 |
+
transition: border-color 0.15s;
|
| 353 |
+
}
|
| 354 |
+
|
| 355 |
+
.chat-input-row:focus-within {
|
| 356 |
+
border-color: var(--accent);
|
| 357 |
+
}
|
| 358 |
+
|
| 359 |
+
.chat-input {
|
| 360 |
+
flex: 1;
|
| 361 |
+
padding: 6px 0;
|
| 362 |
+
border: none;
|
| 363 |
+
background: transparent;
|
| 364 |
+
color: var(--text);
|
| 365 |
+
font-size: 0.9rem;
|
| 366 |
+
font-family: inherit;
|
| 367 |
+
outline: none;
|
| 368 |
+
}
|
| 369 |
+
|
| 370 |
+
.chat-input::placeholder {
|
| 371 |
+
color: var(--text-muted);
|
| 372 |
+
}
|
| 373 |
+
|
| 374 |
+
.chat-input:disabled {
|
| 375 |
+
opacity: 0.5;
|
| 376 |
+
}
|
| 377 |
+
|
| 378 |
+
.chat-send {
|
| 379 |
+
width: 34px;
|
| 380 |
+
height: 34px;
|
| 381 |
+
border: none;
|
| 382 |
+
border-radius: 8px;
|
| 383 |
+
background: var(--accent);
|
| 384 |
+
color: white;
|
| 385 |
+
cursor: pointer;
|
| 386 |
+
display: flex;
|
| 387 |
+
align-items: center;
|
| 388 |
+
justify-content: center;
|
| 389 |
+
flex-shrink: 0;
|
| 390 |
+
transition: all 0.15s;
|
| 391 |
+
}
|
| 392 |
+
|
| 393 |
+
.chat-send:hover:not(:disabled) {
|
| 394 |
+
background: var(--accent-light);
|
| 395 |
+
box-shadow: 0 0 16px var(--accent-glow);
|
| 396 |
+
}
|
| 397 |
+
|
| 398 |
+
.chat-send:disabled {
|
| 399 |
+
opacity: 0.4;
|
| 400 |
+
cursor: not-allowed;
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
/* Loading overlay */
|
| 404 |
+
.loading-overlay {
|
| 405 |
+
position: fixed;
|
| 406 |
+
inset: 0;
|
| 407 |
+
background: rgba(15, 17, 23, 0.6);
|
| 408 |
+
backdrop-filter: blur(4px);
|
| 409 |
+
z-index: 200;
|
| 410 |
+
display: flex;
|
| 411 |
+
align-items: center;
|
| 412 |
+
justify-content: center;
|
| 413 |
+
transition: opacity 0.4s;
|
| 414 |
+
}
|
| 415 |
+
|
| 416 |
+
.loading-overlay.hidden {
|
| 417 |
+
opacity: 0;
|
| 418 |
+
pointer-events: none;
|
| 419 |
+
}
|
| 420 |
+
|
| 421 |
+
.loading-card {
|
| 422 |
+
background: var(--surface);
|
| 423 |
+
border: 1px solid var(--border);
|
| 424 |
+
border-radius: 20px;
|
| 425 |
+
padding: 3rem 3rem 2.5rem;
|
| 426 |
+
text-align: center;
|
| 427 |
+
max-width: 420px;
|
| 428 |
+
width: 100%;
|
| 429 |
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
|
| 430 |
+
}
|
| 431 |
+
|
| 432 |
+
.loading-card h2 {
|
| 433 |
+
font-size: 1.2rem;
|
| 434 |
+
font-weight: 700;
|
| 435 |
+
margin-bottom: 6px;
|
| 436 |
+
}
|
| 437 |
+
|
| 438 |
+
.loading-card p {
|
| 439 |
+
font-size: 0.85rem;
|
| 440 |
+
color: var(--text-muted);
|
| 441 |
+
margin-bottom: 28px;
|
| 442 |
+
}
|
| 443 |
+
|
| 444 |
+
.loading-progress {
|
| 445 |
+
height: 6px;
|
| 446 |
+
background: var(--bg);
|
| 447 |
+
border-radius: 3px;
|
| 448 |
+
overflow: hidden;
|
| 449 |
+
}
|
| 450 |
+
|
| 451 |
+
.loading-progress-fill {
|
| 452 |
+
height: 100%;
|
| 453 |
+
background: linear-gradient(90deg, var(--accent), #a78bfa);
|
| 454 |
+
border-radius: 3px;
|
| 455 |
+
transition: width 0.3s;
|
| 456 |
+
width: 0%;
|
| 457 |
+
}
|
| 458 |
+
|
| 459 |
+
.loading-detail {
|
| 460 |
+
font-size: 0.78rem;
|
| 461 |
+
color: var(--text-muted);
|
| 462 |
+
margin-top: 14px;
|
| 463 |
+
}
|
| 464 |
+
</style>
|
| 465 |
+
</head>
|
| 466 |
+
|
| 467 |
+
<body>
|
| 468 |
+
<main>
|
| 469 |
+
<div class="article-layout">
|
| 470 |
+
<div class="article-content" id="article"></div>
|
| 471 |
+
<aside class="article-aside">
|
| 472 |
+
<figure class="article-figure">
|
| 473 |
+
<img src="./assets/artemis.webp" alt="SLS rocket for Artemis II at Launch Complex 39B" />
|
| 474 |
+
<figcaption>The Space Launch System (SLS) rocket for Artemis II
|
| 475 |
+
at Launch Complex 39B in March 2026</figcaption>
|
| 476 |
+
</figure>
|
| 477 |
+
</aside>
|
| 478 |
+
</div>
|
| 479 |
+
</main>
|
| 480 |
+
|
| 481 |
+
<div class="chat-widget">
|
| 482 |
+
<div class="chat-response" id="chat-response">
|
| 483 |
+
<div class="chat-response-header">
|
| 484 |
+
<div class="chat-label" id="chat-label"><span class="spinner"></span> Thinking</div>
|
| 485 |
+
<button class="chat-close" id="chat-close">
|
| 486 |
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
| 487 |
+
stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
| 488 |
+
<path d="M18 6L6 18M6 6l12 12" />
|
| 489 |
+
</svg>
|
| 490 |
+
</button>
|
| 491 |
+
</div>
|
| 492 |
+
<div class="chat-question" id="chat-question"></div>
|
| 493 |
+
<p class="chat-text" id="chat-text"></p>
|
| 494 |
+
<div class="chat-stats" id="chat-stats"></div>
|
| 495 |
+
</div>
|
| 496 |
+
<div class="chat-input-row">
|
| 497 |
+
<input type="text" class="chat-input" id="chat-input"
|
| 498 |
+
placeholder="Ask about this article..." autocomplete="off" disabled />
|
| 499 |
+
<button class="chat-send" id="chat-send" disabled>
|
| 500 |
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"
|
| 501 |
+
stroke-linecap="round" stroke-linejoin="round">
|
| 502 |
+
<path d="M5 12h14M12 5l7 7-7 7" />
|
| 503 |
+
</svg>
|
| 504 |
+
</button>
|
| 505 |
+
</div>
|
| 506 |
+
</div>
|
| 507 |
+
|
| 508 |
+
<div class="loading-overlay" id="loading-overlay">
|
| 509 |
+
<div class="loading-card">
|
| 510 |
+
<h2>Loading LFM2.5-350M</h2>
|
| 511 |
+
<p>Downloading model and compiling WebGPU shaders</p>
|
| 512 |
+
<div class="loading-progress">
|
| 513 |
+
<div class="loading-progress-fill" id="loading-progress-fill"></div>
|
| 514 |
+
</div>
|
| 515 |
+
<div class="loading-detail" id="loading-detail">Starting...</div>
|
| 516 |
+
</div>
|
| 517 |
+
</div>
|
| 518 |
+
|
| 519 |
+
<script type="module">
|
| 520 |
+
import { pipeline, TextStreamer } from "https://cdn.jsdelivr.net/npm/@huggingface/transformers@4.0.0";
|
| 521 |
+
|
| 522 |
+
const SUMMARIZE_SVG = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 6h16M4 12h10M4 18h14"/></svg>`;
|
| 523 |
+
|
| 524 |
+
// ββ State ββ
|
| 525 |
+
let generator = null;
|
| 526 |
+
let isGenerating = false;
|
| 527 |
+
let articleSource = "";
|
| 528 |
+
|
| 529 |
+
// ββ DOM refs ββ
|
| 530 |
+
const article = document.getElementById("article");
|
| 531 |
+
const loadingOverlay = document.getElementById("loading-overlay");
|
| 532 |
+
const loadingProgressFill = document.getElementById("loading-progress-fill");
|
| 533 |
+
const loadingDetail = document.getElementById("loading-detail");
|
| 534 |
+
const chatInput = document.getElementById("chat-input");
|
| 535 |
+
const chatSend = document.getElementById("chat-send");
|
| 536 |
+
const chatResponse = document.getElementById("chat-response");
|
| 537 |
+
const chatLabel = document.getElementById("chat-label");
|
| 538 |
+
const chatQuestion = document.getElementById("chat-question");
|
| 539 |
+
const chatText = document.getElementById("chat-text");
|
| 540 |
+
const chatStats = document.getElementById("chat-stats");
|
| 541 |
+
const chatClose = document.getElementById("chat-close");
|
| 542 |
+
|
| 543 |
+
// ββ Markdown β HTML ββ
|
| 544 |
+
function markdownToHTML(md) {
|
| 545 |
+
const HEADINGS = [
|
| 546 |
+
{ prefix: "#### ", tag: "h4" },
|
| 547 |
+
{ prefix: "### ", tag: "h3" },
|
| 548 |
+
{ prefix: "## ", tag: "h2" },
|
| 549 |
+
{ prefix: "# ", tag: "h1" },
|
| 550 |
+
];
|
| 551 |
+
|
| 552 |
+
const lines = md.split("\n");
|
| 553 |
+
let html = "";
|
| 554 |
+
let buffer = "";
|
| 555 |
+
|
| 556 |
+
const flushBuffer = () => {
|
| 557 |
+
if (buffer) {
|
| 558 |
+
html += `<p>${buffer.trim()}</p>`;
|
| 559 |
+
buffer = "";
|
| 560 |
+
}
|
| 561 |
+
};
|
| 562 |
+
|
| 563 |
+
for (const line of lines) {
|
| 564 |
+
const heading = HEADINGS.find((h) => line.startsWith(h.prefix));
|
| 565 |
+
if (heading) {
|
| 566 |
+
flushBuffer();
|
| 567 |
+
html += `<${heading.tag}>${line.slice(heading.prefix.length)}</${heading.tag}>`;
|
| 568 |
+
} else if (line.trim() === "") {
|
| 569 |
+
flushBuffer();
|
| 570 |
+
} else {
|
| 571 |
+
buffer += (buffer ? " " : "") + line.replace(/\[\d+\]/g, "");
|
| 572 |
+
}
|
| 573 |
+
}
|
| 574 |
+
flushBuffer();
|
| 575 |
+
return html;
|
| 576 |
+
}
|
| 577 |
+
|
| 578 |
+
// ββ Attach summarize buttons to all <p> in the article ββ
|
| 579 |
+
function attachSummarizeButtons() {
|
| 580 |
+
for (const p of article.querySelectorAll("p")) {
|
| 581 |
+
if (p.classList.contains("hoverable")) continue;
|
| 582 |
+
p.classList.add("hoverable");
|
| 583 |
+
|
| 584 |
+
const btn = document.createElement("button");
|
| 585 |
+
btn.className = "summarize-btn";
|
| 586 |
+
btn.innerHTML = `${SUMMARIZE_SVG} Summarize`;
|
| 587 |
+
btn.onclick = (e) => {
|
| 588 |
+
e.stopPropagation();
|
| 589 |
+
summarizeParagraph(p);
|
| 590 |
+
};
|
| 591 |
+
p.appendChild(btn);
|
| 592 |
+
}
|
| 593 |
+
}
|
| 594 |
+
|
| 595 |
+
// ββ Load article + model ββ
|
| 596 |
+
async function loadArticle() {
|
| 597 |
+
const res = await fetch("data.txt");
|
| 598 |
+
articleSource = await res.text();
|
| 599 |
+
article.innerHTML = markdownToHTML(articleSource);
|
| 600 |
+
}
|
| 601 |
+
|
| 602 |
+
async function loadModel() {
|
| 603 |
+
loadingDetail.textContent = "Downloading model...";
|
| 604 |
+
|
| 605 |
+
generator = await pipeline(
|
| 606 |
+
"text-generation",
|
| 607 |
+
"onnx-community/LFM2.5-350M-ONNX",
|
| 608 |
+
{
|
| 609 |
+
dtype: "q4",
|
| 610 |
+
device: "webgpu",
|
| 611 |
+
progress_callback: (progress) => {
|
| 612 |
+
if (progress.status === "progress_total") {
|
| 613 |
+
loadingProgressFill.style.width = `${progress.progress ?? 0}%`;
|
| 614 |
+
}
|
| 615 |
+
},
|
| 616 |
+
},
|
| 617 |
+
);
|
| 618 |
+
|
| 619 |
+
loadingOverlay.classList.add("hidden");
|
| 620 |
+
chatInput.disabled = false;
|
| 621 |
+
chatSend.disabled = false;
|
| 622 |
+
chatInput.focus();
|
| 623 |
+
}
|
| 624 |
+
|
| 625 |
+
// ββ Summarize a paragraph ββ
|
| 626 |
+
async function summarizeParagraph(p) {
|
| 627 |
+
if (!generator || isGenerating) return;
|
| 628 |
+
isGenerating = true;
|
| 629 |
+
|
| 630 |
+
const originalText = p.textContent.trim();
|
| 631 |
+
const originalWordCount = originalText.split(/\s+/).length;
|
| 632 |
+
|
| 633 |
+
const block = document.createElement("div");
|
| 634 |
+
block.className = "summary-block";
|
| 635 |
+
|
| 636 |
+
const label = document.createElement("div");
|
| 637 |
+
label.className = "label";
|
| 638 |
+
label.innerHTML = `<span class="spinner"></span> Summarizing`;
|
| 639 |
+
block.appendChild(label);
|
| 640 |
+
|
| 641 |
+
const output = document.createElement("p");
|
| 642 |
+
output.className = "output";
|
| 643 |
+
block.appendChild(output);
|
| 644 |
+
|
| 645 |
+
p.replaceWith(block);
|
| 646 |
+
|
| 647 |
+
const t0 = performance.now();
|
| 648 |
+
let tFirstToken = null;
|
| 649 |
+
let tokenCount = 0;
|
| 650 |
+
|
| 651 |
+
const streamer = new TextStreamer(generator.tokenizer, {
|
| 652 |
+
skip_prompt: true,
|
| 653 |
+
skip_special_tokens: true,
|
| 654 |
+
callback_function: (text) => {
|
| 655 |
+
tFirstToken ??= performance.now();
|
| 656 |
+
tokenCount++;
|
| 657 |
+
output.textContent += text;
|
| 658 |
+
},
|
| 659 |
+
});
|
| 660 |
+
|
| 661 |
+
try {
|
| 662 |
+
await generator(
|
| 663 |
+
[
|
| 664 |
+
// { role: "system", content: "You are a concise summarizer. Summarize the given text in a brief paragraph, preserving key facts. Output only the summary, nothing else." },
|
| 665 |
+
{ role: "user", content: `Summarize this:\n\n${originalText}` },
|
| 666 |
+
],
|
| 667 |
+
{ max_new_tokens: 512, do_sample: false, streamer },
|
| 668 |
+
);
|
| 669 |
+
} catch (err) {
|
| 670 |
+
output.textContent = "Error: " + err.message;
|
| 671 |
+
}
|
| 672 |
+
|
| 673 |
+
const elapsed = ((performance.now() - t0) / 1000).toFixed(1);
|
| 674 |
+
const decodeTime = (performance.now() - (tFirstToken ?? t0)) / 1000;
|
| 675 |
+
const tokPerSec = tokenCount > 1 ? ((tokenCount - 1) / decodeTime).toFixed(1) : "\u2014";
|
| 676 |
+
const summaryWordCount = output.textContent.split(/\s+/).length;
|
| 677 |
+
|
| 678 |
+
label.textContent = "Summary";
|
| 679 |
+
|
| 680 |
+
const stats = document.createElement("div");
|
| 681 |
+
stats.className = "stats";
|
| 682 |
+
stats.innerHTML = `<span>${originalWordCount}</span> words → <span>${summaryWordCount}</span> words · ${elapsed}s · <span>${tokPerSec}</span> tok/s`;
|
| 683 |
+
block.appendChild(stats);
|
| 684 |
+
|
| 685 |
+
isGenerating = false;
|
| 686 |
+
}
|
| 687 |
+
|
| 688 |
+
// ββ Chat: ask a question about the article ββ
|
| 689 |
+
async function askQuestion() {
|
| 690 |
+
const question = chatInput.value.trim();
|
| 691 |
+
if (!question || !generator || isGenerating) return;
|
| 692 |
+
|
| 693 |
+
isGenerating = true;
|
| 694 |
+
chatInput.disabled = true;
|
| 695 |
+
chatSend.disabled = true;
|
| 696 |
+
|
| 697 |
+
// Reset response area
|
| 698 |
+
chatQuestion.textContent = question;
|
| 699 |
+
chatText.textContent = "";
|
| 700 |
+
chatStats.textContent = "";
|
| 701 |
+
chatLabel.innerHTML = `<span class="spinner"></span> Thinking`;
|
| 702 |
+
chatResponse.classList.add("visible");
|
| 703 |
+
chatInput.value = "";
|
| 704 |
+
|
| 705 |
+
const t0 = performance.now();
|
| 706 |
+
let tFirstToken = null;
|
| 707 |
+
let tokenCount = 0;
|
| 708 |
+
|
| 709 |
+
const streamer = new TextStreamer(generator.tokenizer, {
|
| 710 |
+
skip_prompt: true,
|
| 711 |
+
skip_special_tokens: true,
|
| 712 |
+
callback_function: (text) => {
|
| 713 |
+
tFirstToken ??= performance.now();
|
| 714 |
+
tokenCount++;
|
| 715 |
+
chatText.textContent += text;
|
| 716 |
+
},
|
| 717 |
+
});
|
| 718 |
+
|
| 719 |
+
try {
|
| 720 |
+
await generator(
|
| 721 |
+
[
|
| 722 |
+
{ role: "system", content: `You are a helpful assistant. Answer the user's question based on the following article. Be concise and accurate. If the answer is not in the article, say so.\n\n${articleSource}` },
|
| 723 |
+
{ role: "user", content: question },
|
| 724 |
+
],
|
| 725 |
+
{ max_new_tokens: 512, do_sample: false, streamer },
|
| 726 |
+
);
|
| 727 |
+
} catch (err) {
|
| 728 |
+
chatText.textContent = "Error: " + err.message;
|
| 729 |
+
}
|
| 730 |
+
|
| 731 |
+
const elapsed = ((performance.now() - t0) / 1000).toFixed(1);
|
| 732 |
+
const decodeTime = (performance.now() - (tFirstToken ?? t0)) / 1000;
|
| 733 |
+
const tokPerSec = tokenCount > 1 ? ((tokenCount - 1) / decodeTime).toFixed(1) : "\u2014";
|
| 734 |
+
|
| 735 |
+
chatLabel.textContent = "Answer";
|
| 736 |
+
chatStats.innerHTML = `${elapsed}s · <span>${tokPerSec}</span> tok/s`;
|
| 737 |
+
|
| 738 |
+
isGenerating = false;
|
| 739 |
+
chatInput.disabled = false;
|
| 740 |
+
chatSend.disabled = false;
|
| 741 |
+
chatInput.focus();
|
| 742 |
+
}
|
| 743 |
+
|
| 744 |
+
chatSend.onclick = askQuestion;
|
| 745 |
+
chatInput.addEventListener("keydown", (e) => {
|
| 746 |
+
if (e.key === "Enter" && !e.shiftKey) {
|
| 747 |
+
e.preventDefault();
|
| 748 |
+
askQuestion();
|
| 749 |
+
}
|
| 750 |
+
});
|
| 751 |
+
chatClose.onclick = () => {
|
| 752 |
+
if (!isGenerating) chatResponse.classList.remove("visible");
|
| 753 |
+
};
|
| 754 |
+
|
| 755 |
+
// ββ Init ββ
|
| 756 |
+
await loadArticle();
|
| 757 |
+
attachSummarizeButtons();
|
| 758 |
+
loadModel();
|
| 759 |
+
</script>
|
| 760 |
+
</body>
|
| 761 |
+
|
| 762 |
</html>
|