Just Pick For Me: A Restaurant Picker for My Mom That Runs Entirely in Her Browser
Just Pick For Me: A Restaurant Picker for My Mom That Runs Entirely in Her Browser
Hacktoberfest Weekend Challenge: Build for a Friend Submission 🤝 This is a submission for the Hacktoberfest Weekend Challenge: Build for a Friend.
Hacktoberfest 周末挑战:为朋友构建项目提交 🤝 这是我为 Hacktoberfest 周末挑战“为朋友构建项目”所提交的作品。
What I Built My mom has the hardest time picking a restaurant, and I’m not much help either. It’s not that there are too many places, or not enough. We just can never figure out what we want, so it always ends with “just pick someplace.” Just Pick For Me was born from that. Instead of showing her a long list, it asks four easy “this or that” questions (sit down or grab-and-go, light or hearty, familiar or something new, close by or worth a drive), finds real places nearby, and picks one for her with a short, friendly reason why.
我构建了什么 我妈妈总是很难决定去哪家餐厅吃饭,而我也帮不上什么忙。并不是因为选择太多或太少,而是我们永远不知道自己想吃什么,最后总是以“随便选一家吧”告终。Just Pick For Me 就是为了解决这个问题而诞生的。它不再向她展示长长的列表,而是提出四个简单的“二选一”问题(堂食还是外带、清淡还是丰盛、熟悉还是尝鲜、附近还是值得开车去),查找附近的真实餐厅,并为她挑选一家,同时给出一个简短、友好的理由。
A few touches I added just for her:
- It knows her name. The first time she opens it, it asks what to call her. After that it greets her and talks to her by name.
- It shows its work. The result lists the answers that led to the pick, so it never feels random.
- It learns what she likes. “Let’s go here!” saves a place as a favorite, and the AI leans toward favorites when she wants something familiar. “Never suggest this place” means she never sees it again. “Not tonight” just picks another.
- Directions in one tap to get her there, just in case it is a new one.
我为她特别添加的一些功能:
- 它认识她的名字。 她第一次打开时,应用会询问该如何称呼她。之后,它会用名字向她问候并与她交流。
- 它展示逻辑。 结果会列出导致该选择的答案,因此它看起来绝非随机。
- 它学习她的喜好。 点击“就去这家!”会将餐厅保存为收藏,当她想吃熟悉的食物时,AI 会倾向于推荐收藏。点击“不再推荐这家”意味着她再也不会看到它。“今晚不想去”则会重新挑选一家。
- 一键导航,以防她去的是一家新餐厅。
Mom’s (raw) reactions:
- “A little bland but seems simple enough”
- “Nice loading bar”
- “Do I have to give it permission to my location? Is that safe?”
- “Clear and not too wordy so that’s nice”
- “Should it be doing something here?”
妈妈的(原始)反馈:
- “界面有点平淡,但看起来足够简单。”
- “加载条不错。”
- “我必须授予它位置权限吗?这安全吗?”
- “清晰且不啰嗦,这点很好。”
- “它在这里应该在运行什么吗?”
Her “Should it be doing something here?” is exactly the rough edge I list under What’s Next, and her location question is why I made sure the app is honest about what leaves her computer. “A little bland” is fair too. Making it look better is on the list.
她提到的“它在这里应该在运行什么吗?”正是我在“下一步计划”中列出的粗糙之处,而她关于位置的问题也是我确保应用明确告知哪些数据会离开她电脑的原因。“界面平淡”的评价也很中肯,优化外观已经在我的计划列表中了。
How I Built It The stack: Vite + React for a simple, lightweight static site, the OpenStreetMap Overpass API for real nearby restaurants (free, no API key), and Qwen 2.5 0.5B, an open-weight model, running inside the browser with Transformers.js. No server, no API key, nothing to install.
我是如何构建它的 技术栈:使用 Vite + React 构建一个简单、轻量级的静态网站;使用 OpenStreetMap Overpass API 获取附近的真实餐厅(免费,无需 API 密钥);并使用 Qwen 2.5 0.5B(一个开源权重模型),通过 Transformers.js 在浏览器内运行。无需服务器,无需 API 密钥,无需安装任何东西。
Getting there was the real adventure:
- WebLLM on the GPU. My first version used WebLLM to run a model on the graphics card. It worked once, then kept crashing. My laptop has Intel UHD integrated graphics, and Windows kept resetting the GPU because it thought it had frozen.
- Smaller and smaller models. I tried Gemma 2 2B, then Gemma 3 1B, then Llama 3.2 1B. I shrank the prompt, fed it in smaller chunks, and switched from 16-bit to 32-bit math. Same crash every time. That’s when I realized the problem wasn’t the model, it was the graphics card.
- Moving to the CPU. I switched to Transformers.js, which can run models on the regular processor instead. It’s slower, but it can’t crash the graphics card, and it works on everyday computers like my mom’s. Gemma’s browser version turned out to use an operation the CPU engine doesn’t support, so I landed on Qwen 2.5 0.5B.
实现过程是一场真正的冒险:
- 在 GPU 上运行 WebLLM。 我的第一个版本使用 WebLLM 在显卡上运行模型。它成功运行了一次,然后就不断崩溃。我的笔记本电脑使用的是 Intel UHD 集成显卡,Windows 系统因为认为显卡已死机而不断重置它。
- 尝试越来越小的模型。 我试过 Gemma 2 2B,然后是 Gemma 3 1B,再到 Llama 3.2 1B。我缩减了提示词,分小块输入,并将 16 位运算切换为 32 位。但每次都会崩溃。这时我意识到问题不在模型,而在显卡上。
- 转向 CPU。 我改用了 Transformers.js,它可以在普通处理器上运行模型。虽然速度较慢,但不会导致显卡崩溃,并且可以在像我妈妈那样的普通电脑上运行。Gemma 的浏览器版本使用了一种 CPU 引擎不支持的操作,所以我最终选择了 Qwen 2.5 0.5B。
Teaching a tiny model to behave. A 0.5B model is small, and it showed: it copied lines from the list, put names in the wrong place, and once wrote a fake restaurant review. (“I ordered the Margherita…”) So I gave it one job at a time:
- Pick: I start its answer for it (“The best choice is number…”) so it only has to add a digit.
- Explain: a separate request about only the chosen place, again starting the sentence for it (“Melissa, Giacomo’s Pizza…”) so it just finishes the thought.
- Safety net: if the sentence still comes out wrong, the app writes a friendly one from the real data, so Mom never sees nonsense.
教导微型模型“守规矩”。 0.5B 的模型很小,这显而易见:它会复制列表中的行,把名字放错位置,甚至有一次写了一篇虚假的餐厅评论(“我点了玛格丽特披萨……”)。所以我让它一次只做一件事:
- 挑选: 我替它开头(“最好的选择是第……号”),这样它只需要补上数字。
- 解释: 针对所选餐厅单独发起请求,同样由我来开头(“Melissa,Giacomo’s Pizza……”),让它只需补全想法。
- 安全网: 如果句子仍然出错,应用会根据真实数据生成一段友好的描述,这样妈妈永远不会看到乱码。
Why Does Open Innovation Matter? With a closed API, my mom’s name, what she’s in the mood for, and her restaurant likes and dislikes would go to an AI company’s server every time she asked about dinner, and I’d be paying for every request. With an open-weight model running in her own browser, the AI part never leaves her computer. The only thing that goes out is her approximate location, to OpenStreetMap, so it can find restaurants nearby. It costs nothing to run no matter how many people use it.
为什么开放创新很重要? 如果使用闭源 API,我妈妈的名字、她的心情、她对餐厅的喜好,每次查询晚餐时都会发送到 AI 公司的服务器,而且我还要为每次请求付费。而使用在浏览器中运行的开源权重模型,AI 部分永远不会离开她的电脑。唯一发送出去的数据是她的近似位置(发送给 OpenStreetMap),以便查找附近的餐厅。无论多少人使用,它都不会产生任何运行成本。