Ichlibitiche commited on
Commit
fe941e5
·
verified ·
1 Parent(s): a75b1bf

Add RoasterDB sample explorer app

Browse files
Files changed (3) hide show
  1. README.md +13 -7
  2. app.py +83 -0
  3. requirements.txt +2 -0
README.md CHANGED
@@ -1,13 +1,19 @@
1
  ---
2
- title: Roasterdb Sample Explorer
3
- emoji: 📚
4
- colorFrom: red
5
- colorTo: blue
6
  sdk: gradio
7
- sdk_version: 6.19.0
8
- python_version: '3.13'
9
  app_file: app.py
10
  pinned: false
 
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
1
  ---
2
+ title: RoasterDB Specialty Coffee Sample Explorer
3
+ emoji:
4
+ colorFrom: yellow
5
+ colorTo: red
6
  sdk: gradio
7
+ sdk_version: 5.9.0
 
8
  app_file: app.py
9
  pinned: false
10
+ license: cc-by-nc-4.0
11
  ---
12
 
13
+ # RoasterDB Specialty Coffee Sample Explorer
14
+
15
+ Interactively explore the free sample of [RoasterDB](https://specialty-coffee-roasterdb.pages.dev): specialty-coffee products from artisan roaster storefronts, with tasting notes normalized to the SCA Flavor Wheel and a source URL on every record.
16
+
17
+ Data: [free sample dataset](https://huggingface.co/datasets/Ichlibitiche/roasterdb-specialty-coffee-sample) (100 verified records, 72 roasters). The full dataset (8,000+ products, 280+ roasters) is available at [roasterdb.net](https://specialty-coffee-roasterdb.pages.dev).
18
+
19
+ Sample data © RoasterDB, CC BY-NC 4.0.
app.py ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+
4
+ # Load the free sample directly from the public Hugging Face dataset
5
+ DATA_URL = "hf://datasets/Ichlibitiche/roasterdb-specialty-coffee-sample/roasterdb_sample.csv"
6
+ df = pd.read_csv(DATA_URL)
7
+
8
+ DISPLAY_COLS = {
9
+ "source_roaster": "Roaster",
10
+ "title": "Coffee",
11
+ "origin_country": "Origin",
12
+ "process_method": "Process",
13
+ "roast_level": "Roast",
14
+ "weight_grams": "Weight (g)",
15
+ "price_value": "Price (USD)",
16
+ "tasting_notes_sca_nodes": "SCA Flavor Notes",
17
+ "source_url": "Source URL",
18
+ }
19
+
20
+ def choices(col):
21
+ vals = df[col].dropna().astype(str)
22
+ vals = sorted(v for v in vals.unique() if v.strip() and v != "Unknown")
23
+ return ["All"] + vals
24
+
25
+ PRICE_MAX = float(df["price_value"].max())
26
+
27
+ def explore(roaster, country, process, roast, flavor, max_price):
28
+ d = df
29
+ if roaster != "All":
30
+ d = d[d["source_roaster"] == roaster]
31
+ if country != "All":
32
+ d = d[d["origin_country"] == country]
33
+ if process != "All":
34
+ d = d[d["process_method"] == process]
35
+ if roast != "All":
36
+ d = d[d["roast_level"] == roast]
37
+ if flavor and flavor.strip():
38
+ d = d[d["tasting_notes_sca_nodes"].fillna("").str.contains(flavor.strip(), case=False, regex=False)]
39
+ if max_price < PRICE_MAX:
40
+ d = d[d["price_value"].fillna(PRICE_MAX + 1) <= max_price]
41
+
42
+ summary = (
43
+ f"**{len(d)} coffees** from **{d['source_roaster'].nunique()} roasters** match — "
44
+ f"out of {len(df)} records in the free sample. "
45
+ f"The full RoasterDB has **8,000+ products from 280+ roasters**."
46
+ )
47
+ table = d[list(DISPLAY_COLS)].rename(columns=DISPLAY_COLS).sort_values("Price (USD)")
48
+ return summary, table
49
+
50
+ with gr.Blocks(title="RoasterDB Sample Explorer") as demo:
51
+ gr.Markdown("# ☕ RoasterDB: Specialty Coffee Sample Explorer")
52
+ gr.Markdown(f"""Explore **{len(df)} verified specialty coffees from {df['source_roaster'].nunique()} artisan roasters** — tasting notes normalized to the **SCA Flavor Wheel**, with a verifiable source URL on every record.
53
+
54
+ ---
55
+ ### 🌐 This is the free sample. The full RoasterDB has 8,000+ products from 280+ roasters.
56
+ * **🔗 Official Portal (full dataset, $99 snapshot):** [roasterdb.net](https://specialty-coffee-roasterdb.pages.dev)
57
+ * **🤗 Free Sample Dataset (Download CSV):** [Ichlibitiche/roasterdb-specialty-coffee-sample](https://huggingface.co/datasets/Ichlibitiche/roasterdb-specialty-coffee-sample)
58
+ * **🏆 Kaggle Dataset:** [RoasterDB Specialty Coffee Sample](https://www.kaggle.com/datasets/ahtiticheamine/roasterdb-specialty-coffee-sample)
59
+ * **🔄 Live Self-Serve Scraping:** [Specialty Coffee Roaster Scraper on Apify](https://apify.com/dataengineered/specialty-coffee-roaster-scraper)
60
+ ---""")
61
+
62
+ with gr.Row():
63
+ roaster_dd = gr.Dropdown(choices=choices("source_roaster"), value="All", label="Roaster")
64
+ country_dd = gr.Dropdown(choices=choices("origin_country"), value="All", label="Origin Country")
65
+ process_dd = gr.Dropdown(choices=choices("process_method"), value="All", label="Process Method")
66
+ roast_dd = gr.Dropdown(choices=choices("roast_level"), value="All", label="Roast Level")
67
+ with gr.Row():
68
+ flavor_tb = gr.Textbox(label="SCA Flavor Search", placeholder="e.g. Berry, Chocolate, Floral, Peach...")
69
+ price_sl = gr.Slider(minimum=0, maximum=PRICE_MAX, value=PRICE_MAX, step=1, label="Max Price (USD)")
70
+
71
+ btn = gr.Button("Explore Coffees", variant="primary")
72
+
73
+ out_text = gr.Markdown()
74
+ out_table = gr.Dataframe(label="Matching Coffees", wrap=True)
75
+
76
+ inputs = [roaster_dd, country_dd, process_dd, roast_dd, flavor_tb, price_sl]
77
+ btn.click(fn=explore, inputs=inputs, outputs=[out_text, out_table])
78
+ demo.load(fn=explore, inputs=inputs, outputs=[out_text, out_table])
79
+
80
+ gr.Markdown("""---
81
+ *Sample data © RoasterDB under CC BY-NC 4.0. Full dataset commercially licensed at [roasterdb.net](https://specialty-coffee-roasterdb.pages.dev) · contact RoasterDB@proton.me*""")
82
+
83
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ pandas
2
+ huggingface_hub