""" Drop — Are You and the Planet Getting Enough Water? The thing you need most is the thing you think about least. """ import gradio as gr import os import random from huggingface_hub import InferenceClient HF_TOKEN = os.environ.get("HF_TOKEN", "") MODEL = "mistralai/Mistral-7B-Instruct-v0.3" client = InferenceClient(model=MODEL, token=HF_TOKEN) if HF_TOKEN else None SYSTEM_PROMPT = """Someone asks about water — their own hydration, their city's water situation, a water fact, or anything related to water on this planet. Your job is to connect the personal to the planetary. Show them how the water in their glass connects to the water crisis everywhere else. Rules: - 4 to 5 sentences. No more. - Always connect the small to the big. Their glass of water to the aquifer under their city. Their shower to the Colorado River. Their tap to the infrastructure nobody thinks about. - Include one specific fact that makes them look at their water differently. - Don't guilt trip. Don't moralize. Just show the connection. - The tone is wonder, not warning. Water is extraordinary before it's endangered. - Talk like a friend who just watched a documentary and can't stop thinking about it. - No "we should all." No "every drop counts." Just show them what a drop actually is.""" WATERS = [ "I probably don't drink enough water", "what's in my tap water", "why does water taste different in different cities", "the ocean", "rain", "ice caps melting", "my city's water supply", "bottled water vs tap", "a glass of water sitting on my desk", "the shower I took this morning", "a river near my house", "swimming pools", "tears", "fog", "a puddle after rain", "the water in my body", "a dripping faucet", "snow", "clouds", "a lake I used to swim in", ] FALLBACKS = [ "**a glass of water sitting on my desk**\n\nThat glass has been a lot of things. Some of those molecules fell as rain on a field in the Midwest last spring. Some of them were in the Great Lakes ten thousand years ago when there was a mile of ice on top. Water doesn't get made or destroyed — it just moves. The glass on your desk is a rest stop on a trip that started before anything was alive. You're drinking history and it doesn't even taste like anything.", "**I probably don't drink enough water**\n\nYour body is running on about 60% water right now, and your brain is closer to 75%. When you feel foggy at 2pm, that's usually not a coffee problem — it's a water problem. But here's the wild part: the water you're not drinking enough of is the same water everything on this planet shares. There's no new water. The dinosaurs drank it. The sequoias are drinking it right now. Your body is just next in line and you keep forgetting to show up.", "**the shower I took this morning**\n\nYou used about 17 gallons in there. That water came from a reservoir or an aquifer that your city built pipes to decades ago — infrastructure that nobody alive today remembers building but everybody uses every morning. After it went down your drain it headed to a treatment plant where someone's entire job is making sure your shower water doesn't end up in someone else's drinking water. The whole system is invisible until it breaks. You stood in an engineering miracle this morning and thought about your day.", "**rain**\n\nEvery raindrop started as a speck of dust. Literally — water vapor needs something to cling to, so it grabs onto pollen, ash, salt, even bacteria floating miles above you. That drop fell from a cloud that formed when the sun heated the ocean yesterday, maybe a thousand miles away. It traveled farther to reach your windshield than most people travel in a month. And when it hits the ground, it doesn't stop — it joins a creek, a river, an aquifer, and starts the whole trip again. Rain isn't weather. It's circulation. The planet is breathing and you're watching it exhale.", "**the water in my body**\n\nYou're about 60% water right now, which means you're more liquid than solid. Your blood is 90% water. Your brain is 75%. The water in your cells right now was somewhere else last week — in a glass, in a river, in a cloud. You cycle through about 2.5 liters a day, which means you replace all the water in your body roughly every three weeks. You're not a fixed thing. You're a pattern that water moves through. Three weeks ago, you were made of completely different water and you didn't even notice the swap.", "**bottled water vs tap**\n\nIn most American cities, tap water is tested hundreds of times a day by law. Bottled water is tested by the company that sells it, on their own schedule, with their own standards. The FDA regulates bottled water less strictly than the EPA regulates your tap. That bottle costs 2,000 times more per gallon than what comes out of your faucet. You're paying for the bottle, not the water. The water in both of them fell as rain on the same planet, ran through the same rock, and ended up in your hand. One just came with marketing.", "**the ocean**\n\nThe ocean holds 97% of all water on Earth and we've explored about 5% of it. There are mountains down there taller than anything on land. There are rivers — actual rivers, with banks and currents — flowing along the ocean floor. The average depth is about 12,000 feet, which means if you put Mount Hood in the middle of the Pacific, the peak wouldn't break the surface. Every breath you take, about half the oxygen in it came from phytoplankton in the ocean, not from trees. The ocean isn't next to you. It's keeping you alive from a distance.", "**a dripping faucet**\n\nThat drip is about one-fifth of a milliliter. It doesn't seem like anything. But a faucet dripping once per second wastes about five gallons a day — over 2,000 gallons a year. That's enough to fill a swimming pool. The sound of it at 3am isn't just annoying, it's the sound of a system that was built to hold pressure and can't anymore. Someone designed the washer inside that faucet to hold back thousands of pounds per square inch, and it did, for years, until it wore out one molecule at a time. That drip is an engineering failure measured in drops. It's also your water bill going up a dollar a month while you try to ignore it.", "**fog**\n\nFog is a cloud that couldn't stay in the sky. It's literally the same thing — water droplets suspended in air — just closer to the ground. In San Francisco, the fog that rolls over the Golden Gate Bridge comes from the cold California Current meeting warm inland air, and it's been doing that for millions of years. Before the bridge was there, the fog came anyway. Before people were there, the fog came anyway. Redwood trees in Northern California get about 40% of their water from fog drip — they comb moisture out of the air with their needles. The trees are drinking the clouds. Fog isn't weather. It's the water table showing up in person.", ] def find_fallback(thing): if thing: thing_lower = thing.lower().strip() for fb in FALLBACKS: try: fb_topic = fb.split("**")[1].lower() if thing_lower == fb_topic or (thing_lower in fb_topic and len(thing_lower) > 5): return fb except (IndexError, ValueError): continue return random.choice(FALLBACKS) def pour(user_input): topic = user_input.strip() if user_input and user_input.strip() else "" if client and topic: try: response = client.chat_completion( messages=[ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": f"The water topic: {topic}"}, ], max_tokens=400, temperature=0.8, ) result = response.choices[0].message.content if result and result.strip(): return f"**{topic}**\n\n{result.strip()}" except Exception: pass return find_fallback(topic) def pour_random(): return pour("") CUSTOM_CSS = """ @import url('https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=Inter:wght@300;400;500;600&display=swap'); body, .gradio-container { background: #f5f5f8 !important; font-family: 'Inter', sans-serif !important; color: #1a1a2e !important; } footer { display: none !important; } .app-header { text-align: center; padding: 28px 20px 8px; } .app-header h1 { font-family: 'Space Mono', monospace; font-size: 2.8rem; font-weight: 700; background: linear-gradient(135deg, #3090d0, #60c0e0); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin: 0; } .app-header .sub { color: #777777; font-size: 0.88rem; margin-top: 6px; font-weight: 300; letter-spacing: 0.04em; } .app-visual { text-align: center; font-size: 5rem; padding: 12px 0 4px; filter: drop-shadow(0 0 20px rgba(48, 144, 208, 0.3)); } .input-box textarea { background: #ffffff !important; border: 1px solid #d0d0d8 !important; color: #1a1a2e !important; font-family: 'Inter', sans-serif !important; border-radius: 12px !important; font-size: 0.95rem !important; } .input-box textarea::placeholder { color: #888888 !important; } .input-box textarea:focus { border-color: #3090d0 !important; box-shadow: 0 0 20px rgba(48, 144, 208, 0.15) !important; } .input-box label, .output-box label { color: #666666 !important; font-family: 'Space Mono', monospace !important; font-size: 0.75rem !important; letter-spacing: 0.05em !important; } button.primary { background: linear-gradient(135deg, #3090d0, #2070b0) !important; border: none !important; color: #fff !important; font-family: 'Space Mono', monospace !important; font-size: 1.1rem !important; font-weight: 700 !important; border-radius: 24px !important; padding: 12px 40px !important; box-shadow: 0 4px 20px rgba(48, 144, 208, 0.3) !important; } button.primary:hover { box-shadow: 0 4px 30px rgba(48, 144, 208, 0.5) !important; } button.secondary { background: transparent !important; border: 1px solid rgba(48, 144, 208, 0.3) !important; color: #3090d0 !important; font-family: 'Space Mono', monospace !important; font-size: 0.8rem !important; border-radius: 20px !important; } button.secondary:hover { background: rgba(48, 144, 208, 0.1) !important; } .output-box .prose { background: #ffffff !important; border: 1px solid #e0e0e8 !important; border-radius: 12px !important; padding: 24px !important; color: #1a1a2e !important; font-size: 0.95rem !important; line-height: 1.7 !important; } .output-box .prose, .output-box .prose *, .output-box .md, .output-box .md *, .output-box p, .output-box span, .output-box div { color: #1a1a2e !important; background: #ffffff !important; } .output-box .prose strong { color: #60c0e0 !important; font-family: 'Space Mono', monospace !important; } .footer-text { text-align: center; padding: 20px; color: #777777; font-size: 0.65rem; font-weight: 300; letter-spacing: 0.05em; } .footer-text a { color: #3090d0; text-decoration: none; } """ with gr.Blocks(css=CUSTOM_CSS, title="Drop", theme=gr.themes.Base()) as demo: gr.HTML("""

Drop

The thing you need most is the thing you think about least
""") with gr.Column(elem_classes="input-box"): user_input = gr.Textbox( label="What about water?", placeholder="my tap water, the ocean, rain, the glass on my desk, the river near my house...", lines=1, max_lines=2, ) with gr.Row(): go_btn = gr.Button("Pour", variant="primary", size="lg") random_btn = gr.Button("Surprise me", variant="secondary", size="sm") with gr.Column(elem_classes="output-box"): output = gr.Markdown(label="") gr.Markdown("**Or try one of these:**") with gr.Row(): ex1 = gr.Button("the water in my body", variant="secondary", size="sm") ex2 = gr.Button("the ocean", variant="secondary", size="sm") ex3 = gr.Button("rain", variant="secondary", size="sm") with gr.Row(): ex4 = gr.Button("bottled water vs tap", variant="secondary", size="sm") ex5 = gr.Button("a dripping faucet", variant="secondary", size="sm") ex6 = gr.Button("surprise me", variant="secondary", size="sm") go_btn.click(pour, [user_input], [output]) random_btn.click(pour_random, [], [output]) ex1.click(lambda: pour("the water in my body"), [], [output]) ex2.click(lambda: pour("the ocean"), [], [output]) ex3.click(lambda: pour("rain"), [], [output]) ex4.click(lambda: pour("bottled water vs tap"), [], [output]) ex5.click(lambda: pour("a dripping faucet"), [], [output]) ex6.click(pour_random, [], [output]) gr.HTML('') if __name__ == "__main__": demo.launch()