<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Luiz Felipe Mendes on Medium]]></title>
        <description><![CDATA[Stories by Luiz Felipe Mendes on Medium]]></description>
        <link>https://medium.com/@lfomendes?source=rss-4120e6551cbe------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*tbP4AA6zT2xp8aUOcf20Ww.jpeg</url>
            <title>Stories by Luiz Felipe Mendes on Medium</title>
            <link>https://medium.com/@lfomendes?source=rss-4120e6551cbe------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 19:14:07 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@lfomendes/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Can design skills make Claude look less like Claude?]]></title>
            <link>https://lfomendes.medium.com/can-design-skills-make-claude-look-less-like-claude-f535bc1fb1d4?source=rss-4120e6551cbe------2</link>
            <guid isPermaLink="false">https://medium.com/p/f535bc1fb1d4</guid>
            <category><![CDATA[web-design]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[claude]]></category>
            <category><![CDATA[vibe-coding]]></category>
            <category><![CDATA[ui-design]]></category>
            <dc:creator><![CDATA[Luiz Felipe Mendes]]></dc:creator>
            <pubDate>Tue, 27 Oct 2026 20:37:26 GMT</pubDate>
            <atom:updated>2026-10-27T20:37:26.254Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PNMtEI4YzflgUr9qcIaDHw.png" /></figure><p>It’s been a bit less than a year since I left my job to work on my own projects, and most of that time I’ve been building with AI. For the last six months or so, that mostly means Claude.</p><p>Today I have two products with real users. <a href="https://iwish.gifts/">iWish</a> is a free platform to create a page for your event, with invitation, RSVP, gift list and photo album, all in one place. <a href="https://guaxi-app.com.br/">Guaxí</a> is an app for doctors who work in several places, to keep shifts, appointments and payments organized. (Yes, Guaxí comes from <em>guaxinim</em>. The raccoon is back.)</p><p>Back in 2024 I wrote about <a href="https://lfomendes.medium.com/recommended-reading-how-i-use-ai-by-nicholas-carlini-83d959744b19">how I was using AI day to day</a>, mostly for small productivity tasks. A lot has changed since then.</p><p>The programming part got really fast. But there’s one thing I can’t stop noticing: almost every interface built with AI looks the same. Same kind of buttons, same page layout, similar fonts, even similar copy. You open a new site and think “yep, an AI made this”.</p><p>If you don’t give the model much guidance, that’s what you get. And I’m not a designer (if you read my <a href="https://lfomendes.medium.com/using-openai-api-to-make-a-coffee-barista-part-1-9ea500c90d77">coffee barista post</a>, you already know my apologies to all designers out there are a recurring thing).</p><p>Recently, I came across <a href="https://uxplanet.org/i-tested-3-claude-code-skills-for-web-design-which-one-is-best-521137220dc1">this post on UX Planet</a>, where the author tests three Claude Code skills for web design. I recommend reading it. It gave me the push to run my own version of the test, using a project of my own.</p><p>So I wanted to answer a simple question:</p><blockquote><strong>if you don’t have a design background, can skills help you get out of the default look?</strong></blockquote><p>This is the first of a couple of posts about what I’ve learned building with AI this year. This one is only about interfaces. The next one will cover how I organize files and projects for agents, and how the developer role is changing.</p><h3>The Experiment</h3><p>My first idea was to test this on my own projects. But they already have a branding file and interface definitions that the agent reads every time it touches design. That’s great for consistency, but it leaves very little room for a skill to change anything.</p><blockquote>So I started from scratch, with a new project. And since I’m me, it’s about coffee.</blockquote><h3>Coffee Nerds</h3><p>Coffee Nerds is an app for coffee geeks. You can find famous coffee recipes, brew them, and log the result: “I made this recipe with this specific coffee and it was great” (or not so great).</p><p>To keep the comparison fair, every version got exactly the same inputs:</p><ul><li><a href="https://github.com/lfomendes/guaxinim-tests/blob/main/PROJECT.md">PROJECT.md</a>, a single markdown file with the vision, target users, the data model (coffee, method, recipe and brew log) and six well-known recipes as seed data, like James Hoffmann’s V60 and Tetsu Kasuya’s 4:6 method. This is the only context every version received.</li><li>The same model: Claude Opus 5.5.</li><li>The same execution prompt.</li></ul><p>Everything is on GitHub: <a href="https://github.com/lfomendes/guaxinim-tests">lfomendes/guaxinim-tests</a>. Each design lives in its own branch, so you can check out any version and compare them yourself.</p><h4><strong>The two skills</strong></h4><p>If you haven’t used them yet, a skill is basically a set of instructions the agent loads when it’s doing a specific kind of task (if agents are new to you, I wrote a short intro in <a href="https://lfomendes.medium.com/weekly-reading-ai-agents-8414e387bfd8">Weekly reading: AI Agents</a>). Think of it as a style guide plus a checklist that the model reads before it starts working. I picked two design skills:</p><ul><li><a href="https://github.com/leonxlnx/taste-skill"><strong>Taste Skill</strong></a>: focused on pushing the agent away from generic, boilerplate UI and toward more deliberate choices in layout, typography, spacing and motion.</li><li><a href="https://github.com/nextlevelbuilder/ui-ux-pro-max-skill"><strong>UI UX Pro Max</strong></a>: a broader design guide for web and mobile, with visual styles, color palettes and UX guidelines.</li></ul><h4>Four versions</h4><p>Besides the two skills, I ran two reference versions. One with no skill at all, just telling Claude “execute this”, which is exactly the look I’m trying to escape. And one with no skill but using Claude Design, to see how much the design feature alone changes things.</p><p>So, four versions in total, one run each, each in its own branch:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oVrir3dXONUMKhhtelIOsQ.png" /></figure><h3>The results</h3><p>Now I’m going to show what each version looks like. The goal here is not to crown a winner. It’s to compare what each combination produces and how far it gets from the default.</p><h3>1. Default (no skill)</h3><p>Let’s start with the reference: same spec, same prompt, nothing else. (<a href="https://github.com/lfomendes/guaxinim-tests/tree/claude/lucid-tesla-y2vm5y">branch</a>)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*7J_WAPpF7ohrB5H414fP5A.gif" /></figure><p>This is the look you’ve probably seen a hundred times by now: warm off-white background, a red pill button for the main action, rounded cards, four stat tiles at the top, little pill badges and star ratings. It’s clean and it works. There are even some nice touches, like a monospaced font for dates and a dark card for the best cup.</p><p>But put it next to any other AI-built app and you’ll see the family resemblance.</p><h3>2. Claude Design (no skill)</h3><p>Same spec, no skill, but using Claude Design. (<a href="https://github.com/lfomendes/guaxinim-tests/tree/claude/practical-cray-sxgfsi">branch</a>)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*vsgKh5XqAElvpBhBUooRyA.gif" /></figure><p>Honestly, I expected more difference here. Claude Design organized the page better, putting the stats right next to the main message, and the hierarchy is clearer. But the visual language is basically the same as the default: same red, same rounded cards, same stat tiles, same pills. Side by side, they look like siblings.</p><p>One note: the headline text is the same in both because I used a shared sample data file to fill the screens. That part is on me, not on the AI.</p><h3>3. Taste Skill</h3><p>(<a href="https://github.com/lfomendes/guaxinim-tests/tree/taste-skill">branch</a>)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*38BLpSOt1YJzr_geTCe9LA.gif" /></figure><p>This is the one that surprised me. It went for an editorial, almost brutalist look: black-and-white coffee photos (including an old one from a coffee harvest in São Paulo), flat color blocks, huge uppercase type and no rounded cards anywhere. Nobody would look at this and think “AI made this”.</p><p>It also packaged the app differently. Instead of opening straight into the journal like the others, it built a website with a big landing page up front. But don’t be fooled by the first screen: everything I asked for in the spec is there, the recipes, the brew timers and logging your cup. It didn’t ignore the brief, it just chose a very different way to present it.</p><p>And it got everything by its own, all the images, the video, the animation. I really enjoyed the final product.</p><h3>4. UI UX Pro Max</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*kKlYHg5jipo2RNYgWeTLqA.gif" /></figure><p>This one feels like a real product with its own personality. Sidebar navigation instead of the top bar, serif headings, a brown and caramel palette that actually feels like coffee, and monospaced numbers for the recipe details.</p><p>Under the hood, though, it still uses the usual building blocks: cards, pills, stars and the same sections. It also generated a design system and a style guide along the way, which is exactly the kind of file I’d want to keep the project consistent from here on.</p><h3>What I took from it</h3><p><strong>Short version: Claude Design alone didn’t get me out of the default look. The skills did, in very different ways.</strong></p><ul><li><strong>Claude Design</strong> improved the layout, but kept the same visual language as the default.</li><li><strong>UI UX Pro Max</strong> gave the app a personality while staying inside the usual app conventions. It’s the safer choice if you’re building something people use every day.</li><li><strong>Taste Skill</strong> was the only one that really broke the pattern. It wrapped the app in a website with a landing page up front, but still delivered every feature in the spec, recipes and timers included.</li></ul><p>Another thing became clear looking at them side by side. The three app screens have almost the same sections (bags on the shelf, best brews, recent brews), because they all came from the same PROJECT.md. <strong>The spec decided the structure; the skill decided the look.</strong> That makes me even more convinced that your project files matter more than your prompt, but that’s a topic for the next post.</p><p>A few things I already believed before the test, and still do:</p><ul><li><strong>If you have a designer, use a designer.</strong> Someone with that background can write a proper definition file with patterns, colors, fonts and examples. That will beat any skill. This test is for the rest of us.</li><li><strong>Ask for options early.</strong> At the start of a project, asking Claude for three different designs is one of the easiest ways to steer the visual direction. It’s much easier to react to options than to describe what you want from nothing.</li><li><strong>Then lock it down.</strong> Once the project is moving, the goal flips from variety to consistency. That’s why I keep design and branding files in my projects, and the agent reads them every time it touches the UI. I’ll talk more about that in the next post.</li></ul><h3>Limitations</h3><p>I used both skills in the simplest way possible: one prompt and let it run. These libraries probably have more features, and they likely work better in a more iterative process, going back and forth with the agent. So take this as a “from zero” comparison, not a full review of either skill.</p><p>Also, this is one project, one prompt and one run per version. Run it again tomorrow and you’ll probably get something a bit different.</p><h3>What’s next</h3><p>The next step is to use two of these skills in my real projects, asking for a new page or a new feature. I want to see how they behave when there’s already a project definition and a brand file in place, which is the situation most of us are actually in.</p><h3>Wrapping up</h3><p>AI made building the app the easy part. Making it look like <em>your</em> app, and not like every other AI-built site out there, is still on us. Skills seem like a good shortcut for people like me without a design background, but they don’t replace knowing what you want.</p><p>If you’ve been using other design skills, or have tricks to get Claude out of its default look, I’d love to hear about them. Feel free to leave any questions or suggestions in the comments.</p><p>And if you want to see what came out of a year building this way (with design files, not skills, at least for now), take a look at <a href="https://iwish.gifts/">iWish</a> and <a href="https://guaxi-app.com.br/">Guaxí</a>. Feedback is very welcome there too.</p><p>And if you want to try it yourself, the repo is <a href="https://github.com/lfomendes/guaxinim-tests">here</a>. Start from PROJECT.md, pick your favorite skill, and see what you get. Each of my versions is in its own branch if you want to compare.</p><p><em>This text was reviewed with the help of an LLM.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f535bc1fb1d4" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Comments on Netflix's latest advances in LLMs for recommendations]]></title>
            <link>https://lfomendes.medium.com/comments-on-netflixs-latest-advances-in-llms-for-recommendations-2fb97d217023?source=rss-4120e6551cbe------2</link>
            <guid isPermaLink="false">https://medium.com/p/2fb97d217023</guid>
            <category><![CDATA[llm]]></category>
            <category><![CDATA[genai]]></category>
            <category><![CDATA[netflix]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[recommendations]]></category>
            <dc:creator><![CDATA[Luiz Felipe Mendes]]></dc:creator>
            <pubDate>Tue, 18 Aug 2026 16:54:13 GMT</pubDate>
            <atom:updated>2026-08-18T16:54:13.331Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2J3x3psmWbZgud-BP-YfSw.jpeg" /></figure><p>Personal Hub: Learn more about my work and latest indie projects at <a href="https://www.linkedin.com/redir/general-malware-page?url=http%3A%2F%2Fguaxinimapps%2epages%2edev">guaxinimapps.pages.dev</a>.</p><p>Even though I’m not working directly with Recommendation Systems at the moment, I always make time to follow how production AI architectures are evolving. Continuous learning is essential in ML engineering, and Netflix’s latest <a href="https://netflixtechblog.com/genrec-towards-llm-native-recommendation-at-netflix-f20be6f643e3">post on GenRec</a> (their LLM-native recommendation ranker) was an incredible read!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*921hSlz0Qw_2kUvNlZBojg.png" /></figure><p>Here are a few key takeaways that stood out to me:</p><p><strong>🔹 Off-the-shelf LLMs aren’t production-ready RecSys</strong></p><p>Standard foundation models tend to hallucinate out-of-catalog items, over-recommend globally popular content, and ignore business constraints. GenRec addresses this by post-training an open-source backbone on Netflix-specific data, matching or exceeding mature production systems with far fewer labeled examples.</p><p><strong>🔹 From Feature Engineering to Context Engineering</strong></p><p>We’re seeing a paradigm shift: <em>“The prompt becomes the new feature vector.”</em> Instead of designing manual feature vectors, Netflix verbalizes user interaction logs and metadata into natural language conversations. Modeling effort shifts to deciding what context to include, how far back to go, and how to stay within a token budget.</p><p><strong>🔹 A Smart Two-Phase Architecture</strong></p><ul><li>Phase 1 (Foundation): Adapts an open-source base LLM to domain-specific Netflix content and member patterns. Updated infrequently, it serves as a shared backbone.</li><li>Phase 2 (GenRec Ranker): Post-trains the backbone specifically for candidate ranking and steering. Refreshed frequently to capture evolving tastes and content additions under strict serving cost limits.</li></ul><p><strong>🔹 Prefill-Only Inference (Game Changer for Latency)</strong></p><p>Autoregressive token-by-token generation across thousands of items would be way too slow and expensive for real-time recommendations. Netflix bypasses generation entirely: the LLM consumes the prompt once in prefill mode, scoring the candidate set in a single GPU forward pass!</p><p><strong>🔹 Multi-Objective Loss &amp; Long-Term Alignment</strong></p><p>Training combines ranking loss, language modeling loss (preserving text understanding and explanation potential), and reward-weighted loss. This ensures recommendations align with broader business goals: balancing movies, series, live shows, and games while optimizing for long-term member satisfaction rather than short-term clickbait.</p><p>Generative AI isn’t just about generating text, when paired with clever system architecture and inference tricks, foundation models can completely transform high-throughput ranking systems at scale.</p><h3>Final Thoughts</h3><p>LLMs have transformed almost every corner of AI over the past couple of years, but recommendations always felt like a particularly tough area to tackle. The obstacles felt overwhelming: high inference costs, strict real-time latency budgets, model scale, and the notorious difficulty of translating offline metric wins into actual online impact.</p><p>To be honest, I was pretty pessimistic about LLMs playing a meaningful role in production RecSys anytime soon. However, seeing architectures like GenRec shows that with clever engineering, especially around context compression and prefill-only serving we really can merge the best of traditional RecSys with the reasoning power of LLMs.</p><h3>🇧🇷 Para os leitores brasileiros: conheça meu trabalho atual</h3><p>Para quem é do Brasil e quer acompanhar o que venho construindo recentemente como indie developer, confira alguns dos produtos que lancei:</p><ul><li>🎈 <a href="https://iwish.gifts/">iWish Gifts</a>: Plataforma para simplificar listas de presentes e vaquinhas de aniversários, chás de bebê e eventos.</li><li>🎁 <a href="https://entrenos.iwish.gifts/">entre nós</a>: O “Wrapped” para casais : transforme seu histórico de conversas do WhatsApp em um presente visual inesquecível.</li><li>🩺 <a href="https://guaxinim-financas.com.br/">Guaxi</a>: Gestão financeira descomplicada para profissionais de saúde autônomos acompanharem plantões e repasses de convênios.</li></ul><p>Confira todos esses projetos e meus artigos no meu portal central: <a href="https://www.linkedin.com/redir/general-malware-page?url=http%3A%2F%2Fguaxinimapps%2epages%2edev">guaxinimapps.pages.dev</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2fb97d217023" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[When AI Writes and AI Reads: Why Human Work Is Becoming the Premium Tier]]></title>
            <link>https://lfomendes.medium.com/when-ai-writes-and-ai-reads-why-human-work-is-becoming-the-premium-tier-8d127e292c83?source=rss-4120e6551cbe------2</link>
            <guid isPermaLink="false">https://medium.com/p/8d127e292c83</guid>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[llm]]></category>
            <category><![CDATA[techology]]></category>
            <category><![CDATA[writing]]></category>
            <category><![CDATA[ai]]></category>
            <dc:creator><![CDATA[Luiz Felipe Mendes]]></dc:creator>
            <pubDate>Wed, 29 Jul 2026 14:01:45 GMT</pubDate>
            <atom:updated>2026-07-29T14:42:58.732Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="Editorial illustration, wide 2:1 aspect ratio. A closed circular loop of printed pages flowing endlessly between two identical machines — one printing pages, one consuming them — forming an ouroboros of paper. The loop dominates the frame. Off to one side, small and slightly outside the circle, a single wooden desk with a lamp, a notebook, and an empty chair. Muted palette: warm paper cream, ink black, one accent of amber from the lamp. Flat vector style with subtle grain texture, generous negat" src="https://cdn-images-1.medium.com/max/1024/1*gRVGu3FsGBLrg-fJGPGh3Q.png" /><figcaption>This image is AI generated</figcaption></figure><p>A while ago I was doing something pretty boring: going through the list of new signups for one of my projects. I have three of them running in parallel right now, all at least in beta with real users, so this kind of housekeeping is part of my weekends.</p><p>Then I noticed something odd. <strong>A lot of those accounts weren’t people.</strong> At one point I had more bots signing up than actual humans.</p><p>I ended up changing the application just to add some friction and verify there was a person on the other side.</p><p>Crawlers have always existed, anyone who has ever run a website knows that. But today’s bots are smarter, cheaper to run, and much harder to block.</p><p>Then in June, Cloudflare’s CEO <a href="https://blog.cloudflare.com/">posted a chart showing that automated requests had overtaken human ones on the web for the first time</a>: something like 57% bots to 43% humans, arriving years earlier than he had predicted. Measuring this is messy and different providers report very different numbers, so I’d take the exact percentage with a grain of salt. But it made my little signup problem feel less like a bug in my app and more like a symptom.</p><p>That has been rattling around my head ever since, because it connects to something bigger I’ve been trying to put into words.</p><h3>The loop</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/662/1*ki5ow3O4W3xmg_ms0Bb2aw.jpeg" /></figure><p>I’m currently reading <a href="https://www.goodreads.com/book/show/241434373-the-infinity-machine"><em>The Infinity Machine</em></a>, Sebastian Mallaby’s book about Demis Hassabis and DeepMind, and while I was in the middle of it two news items showed up in my feed.</p><p>The first was Anthropic buying physical books, cutting off the bindings, and scanning them page by page to train models. The second was a term I keep running into: <strong>“Google Zero”</strong>, <a href="https://www.theverge.com/2024/5/14/24156640/google-ai-overviews-search-zero-click">a phrase Nilay Patel coined at The Verge</a> for the endpoint where AI summaries answer your question right there on the results page and the traffic to the original site goes to roughly nothing.</p><p>That endpoint stopped being theoretical this month. The New York Times ran a piece on <a href="https://www.nytimes.com/2026/07/22/technology/google-ai-search-traffic.html">how Google is building an AI fence around the internet it once defended</a>, and the Wall Street Journal reported that Reddit, USA Today, Reuters, Politico and The Economist are all seriously considering blocking Google’s crawlers, the reported traffic declines vary a lot depending on who’s measuring, but Business Insider’s drop is somewhere north of 85%.</p><p><strong>Read that again, because it’s genuinely strange.</strong> Publishers are considering making themselves invisible to the largest search engine on earth, because being visible no longer pays.</p><p>Put all of it next to my bot signups and a pattern shows up.</p><blockquote>We’re entering a loop where AI generates the content and AI consumes it. Bots writing, bots reading, and humans somewhere in the middle, increasingly optional.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/496/1*dN1g6zD3-kv-5Jpmr0ZeGw.jpeg" /><figcaption>“monkey” bots writing</figcaption></figure><p>I should be honest about my own part in this. I use AI when I write these posts, mostly to organize a messy pile of ideas into something with a beginning and an end. But I curate, read, rewrite, and adjust everything myself. <strong>What ends up published here reflects things I actually think.</strong></p><p>That’s a different thing from what a growing share of the web is becoming: agents that watch trending topics, scrape what already exists, and publish articles automatically, at a volume no human team could ever match.</p><h3>When content becomes free</h3><p>Set aside for a moment the bigger debates around AI ethics, synthetic video, and elections. The part that keeps pulling my attention is simpler and more structural: we are about to be flooded. First with text, then images, then video, pushed by the cost of producing all of it falling toward zero.</p><p>And when content becomes almost free to produce, basic information gets commoditized.</p><p>If I search for the population of Ecuador, I get the number immediately. No click, no visit, no ad impression. Great for me. But what happens to the site that compiled that data and depended on that traffic to exist?</p><p>This is the part I don’t think we’ve fully priced in. The internet as we know it was built on an economic loop:</p><ul><li>search engines send traffic,</li><li>traffic pays for the content</li><li>the content feeds the search engines.</li></ul><p>AI answers break the middle link of that chain while still depending on the last one.</p><p>Which brings me to the conclusion I keep arriving at.</p><blockquote>Human-created work is becoming the premium tier.</blockquote><p>You can already see it. If you need a quick image for a blog post, AI generation is usually good enough. But whoever has the budget still hires a human artist, for the technique, the quality, and the creative direction. The same is happening with writing: serious outlets are putting human journalism behind paywalls, precisely because it costs more to produce.</p><blockquote>AI becomes the default option for the masses. Human touch, expertise, and craft get reserved for the top of the pyramid. I’m not sure I love that outcome, but I have a hard time seeing the incentives pointing anywhere else.</blockquote><h3>So what do we actually do?</h3><p>Honestly, I don’t have a clean answer, and I’m suspicious of anyone who does.</p><p>But there are two things I’ve been arguing for a long time now.<strong> The first is regulation. </strong>These tools are going to need it, and I think it’s inevitable. If search engines stop sending traffic to the sites whose content powers their answers, there should be some obligation to compensate the people who created it.</p><p>The second is that we need decent frameworks to verify whether content is authentic and human-made. Not a perfect solution, I don’t think a perfect one exists but something better than “trust me.”</p><p>At the individual level, the lever is smaller and simpler: intentionally look for and support human-generated work. Pay for the newsletter. Buy the book. Follow the person, not the feed.</p><h3>The pendulum</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*L7NaMBffjYpkOKRtHA73Xw.jpeg" /><figcaption>Book club (stockphoto)</figcaption></figure><p>The optimistic part is that the reaction is already visible.</p><p>Book clubs and physical media groups are growing again: people meeting online or in person to read paper books written by humans and talk about them together.<strong> My guess is that platforms will eventually adopt explicit badges saying something like <em>“this was made by a human”</em>, the same way we got organic food labels.</strong></p><p>Society tends to work like a pendulum. As AI floods the market, I think it swings back toward valuing human authenticity and that’s a swing worth helping along.</p><p><strong>I’m still figuring out what that means for the products I build, and I’ll probably change my mind about parts of this over the next year.</strong> But the bot signups made it concrete for me in a way that no think-piece had, and that seemed worth writing down.</p><h3>Sources</h3><p>Everything I referenced above, in case you want to go to the originals, which, given the subject of this post, feels like the least I can do:</p><ul><li><strong>The Infinity Machine: Demis Hassabis, DeepMind, and the Quest for Superintelligence</strong>, Sebastian Mallaby (2026) — <a href="https://www.goodreads.com/book/show/241434373-the-infinity-machine">Goodreads</a></li><li><strong>“Google Is Building an A.I. Fence Around the Internet It Once Defended”</strong> — <a href="https://www.nytimes.com/2026/07/22/technology/google-ai-search-traffic.html">The New York Times</a></li><li><strong>Reddit and news publishers weighing whether to cut off Google</strong> — <a href="https://www.wsj.com/tech/ai/reddit-news-publishers-google-ai-search-traffic-212ec8a7">The Wall Street Journal</a> (and the <a href="https://nypost.com/2026/07/22/business/reddit-news-outlets-consider-cutting-off-google-access-due-to-ai-search-traffic-drop-report/">New York Post summary</a>, if you hit the paywall)</li><li><strong>The original “Google Zero” framing</strong>, by Nilay Patel — <a href="https://www.theverge.com/2024/5/14/24156640/google-ai-overviews-search-zero-click">The Verge</a></li><li><strong>Bot vs. human traffic, and the crawl-to-refer ratios</strong> — <a href="https://blog.cloudflare.com/">The Cloudflare Blog</a></li><li>I also found <a href="https://www.youtube.com/watch?v=_J0T8-Z3akY">this video</a> a good walkthrough of the Google Zero story if you’d rather watch than read.</li></ul><h3>If you’d rather listen</h3><p>I’ve been turning these posts into short audio episodes: same ideas, more conversational, made for walks and commutes. It’s called <strong>GuaxiCast</strong>, and you can find it <a href="https://open.spotify.com/show/033Cm5nn5wBwse7QGq28Ps">on Spotify</a> or through the <a href="https://rss.com/podcasts/guaxicast/">RSS feed</a>.</p><h3>Para os leitores brasileiros ☕</h3><p>The apps I mentioned are all Brazil-first, so if you’re reading from here, these are what I’m currently building. All of them live at <a href="https://guaxinimapps.pages.dev/">guaxinimapps.pages.dev</a>:</p><ul><li><a href="https://entrenos.iwish.gifts/"><strong>entre nós</strong></a> — turns a WhatsApp conversation into a visual gift: message counts, most-used words, favorite emojis, the whole timeline of a relationship. Basically a Wrapped for couples.</li><li><a href="https://iwish.gifts/"><strong>iWish Gifts</strong></a> — gift registries and group gifting for baby showers, birthdays, and everything in between. This one scratched a very personal itch.</li><li><a href="https://guaxinim-financas.com.br/"><strong>Guaxi</strong></a> — for autonomous health professionals: all the money from shifts and insurance plans in one place, so you know exactly when each payment lands.</li></ul><p>And yes, the raccoon is still around.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8d127e292c83" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Back to the Keyboard: 4 Apps, a Sabbatical, and What AI Coding Actually Feels Like]]></title>
            <link>https://lfomendes.medium.com/back-to-the-keyboard-4-apps-a-sabbatical-and-what-ai-coding-actually-feels-like-6cad3aff0639?source=rss-4120e6551cbe------2</link>
            <guid isPermaLink="false">https://medium.com/p/6cad3aff0639</guid>
            <category><![CDATA[agents]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[vibe-coding]]></category>
            <category><![CDATA[claude]]></category>
            <dc:creator><![CDATA[Luiz Felipe Mendes]]></dc:creator>
            <pubDate>Tue, 31 Mar 2026 17:10:27 GMT</pubDate>
            <atom:updated>2026-05-29T20:38:19.760Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UzSU0N9nwQlQHbPW6WsOfg.png" /><figcaption>“Where coffee meets code. Building the future, one line (and one cup) at a time.”</figcaption></figure><p>A few months ago, I made a decision that scared me a little: I left my stable job and took a sabbatical.</p><p>Most of it was about rest and reflection. But it was also about curiosity. I wanted to go back to the thing I love most — creating stuff. And I wanted to do it in this new world where AI is sitting right next to you at the keyboard.</p><p><em>(If you want the full story of what I learned during my time off, check out [my sabbatical post — </em><a href="https://medium.com/@lfomendes/what-i-learned-during-my-short-sabbatical-637a41600fdb"><em>link here</em></a><em>].)</em></p><h3>Four projects later…</h3><p>I didn’t just play around. I actually shipped things.</p><p>(if you wanna follow my projects I’m adding all of them here -&gt; <a href="https://guaxinimapps.pages.dev/">https://guaxinimapps.pages.dev</a>)</p><p>One project was for a friend in the medical field — a more private one. Another was an anniversary gift (yes, I built software as a gift).</p><p><strong>On is in beta and two of them are open (updated on may 29th 2026) </strong>right now, and I’m genuinely excited to share them, but I’m sorry for my international readers, both of them are focused on Brazilian customers.</p><p><a href="https://iwish.gifts/"><strong>iWish</strong></a> — A platform designed to simplify organization for social events like baby showers. Currently in Open Beta.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xAQ2QFqk9fNUnazcL0BLFg.png" /></figure><p><a href="https://guaxinim-financas.com.br/"><strong>Guaxinim Finanças</strong></a> — Yes, raccoons again. If you’ve read<a href="https://medium.com/@lfomendes/using-openai-api-to-make-a-coffee-barista-part-1-9ea500c90d77"> my coffee barista posts</a>, you know I have a thing for guaxinins. This one is a personal finance app built with a minimalist UX — quick expense tracking, financial health at a glance, no noise. Also in beta, but this one’s a closed beta for now.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3So11wSypmY3wBGsR_kdTA.png" /></figure><p><strong>entre nós</strong> (<a href="https://entrenos.iwish.gifts/">entrenos.iwish.gifts</a>) — It turns a couple’s WhatsApp or Telegram conversation into a beautiful animated keepsake — a “retrospective” of the relationship, with the real numbers: total messages, who wrote more, first message date, most-used words.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/879/1*NmmFlbpJIk_YUMA4Q400wg.png" /></figure><p>All of them are real products, used by real people, and built mostly by me — with a lot of AI help.</p><p>Which brings me to what this post is actually about.</p><h3>What I learned building with AI (the honest version)</h3><h4>You ship more. A lot more. But there’s a catch.</h4><p>This part is real — AI coding genuinely multiplies your output. Features that would have taken me days came together in hours. The ceiling of what a solo developer can build has moved significantly.</p><p>But here’s what nobody tells you upfront: <strong>you need more structure, not less.</strong></p><p>When you’re writing code yourself, the architecture lives in your head. You feel the inconsistencies. With AI helping, you can move so fast that the codebase becomes incoherent before you notice. I learned to invest more time upfront in documentation, planning, and defining patterns.</p><p>Think of it like hiring a very fast contractor. They’ll build whatever you describe. The better your blueprints, the better your building.</p><h3>AI dev is expensive</h3><p>If you’re coding with AI casually, the paid tiers of Claude, ChatGPT, or Windsurf are fine. But if you’re building full time? <strong>You will burn through credits embarrassingly fast.</strong></p><p>The “max versions” are much more expensive. I’m talking somewhere around <strong>$200/monreth</strong> — that’s over <strong>R$1.000</strong> just to keep the lights on for your AI tooling. That’s not sustainable for independent developers, and it’s something companies should think seriously about. Either pay for the max tier for developers who actually use these tools, or accept that your team is either context-switching constantly or paying out of pocket.</p><p>One thing that helped me a lot — and I touched on this in <a href="https://medium.com/@lfomendes/what-i-learned-during-my-short-sabbatical-637a41600fdb">a previous post</a>, is being intentional about <strong>which model you use for which task</strong>. Not every step in your workflow needs the most powerful (and most expensive) model. A pattern that worked well for me with Claude models as examples.</p><ul><li><strong>Opus</strong> for the heavy thinking: research, architecture decisions, writing a detailed markdown spec for a new feature.</li><li><strong>Sonnet</strong> to read that spec and produce a concrete development plan — it has the context it needs, the hard thinking is already done.</li><li><strong>Haiku</strong> for the actual implementation of well-defined tasks — fast, cheap, and perfectly capable when the instructions are clear.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tmnJdfwYG0i5KPJfWXbK7A.png" /></figure><p><strong>You’re essentially using the expensive model to produce a compressed, high-quality brief, and then letting cheaper models do the execution.</strong> The cost difference is significant.</p><p>And there’s one more trick that compounds this: <strong>use separate sessions for each phase.</strong> It sounds simple, but it matters. Each session starts with a clean context window. If you carry everything into one long conversation — the research, the planning, the implementation — you’re paying to re-process all that context on every single message. Splitting by phase keeps each session lean and focused, which is both cheaper and, honestly, produces better results because the model isn’t wading through irrelevant history.</p><h3>Learn the meta-layer: Skills, Rules, Agents, Workflows</h3><p>This one changed how I work more than anything else.</p><p>There’s a layer above just “chatting with AI to write code” that most people skip. Tools like Windsurf introduced the <a href="https://docs.windsurf.com/windsurf/cascade/agents-md">concept of <strong>agents.md</strong></a> — a file where you define how the AI agent should behave in that folder.</p><blockquote>“This is particularly useful for providing directory-specific coding guidelines, architectural decisions, or project conventions.”</blockquote><p>But the honest origin of this pattern is Claude. Anthropic started the conversation around structuring AI behavior through explicit instructions and context — the idea that you’re not just prompting, you’re <em>configuring a collaborator</em>. Windsurf and others built on top of that thinking.</p><p><a href="https://docs.windsurf.com/windsurf/cascade/skills"><strong>Skills</strong></a> are reusable capabilities you define once and invoke repeatedly. <strong>Workflows</strong> are sequences the AI follows for repeated tasks. <strong>Rules</strong> are guardrails that keep the AI consistent with your codebase’s personality.</p><p>Once I started thinking in these terms — not “what do I ask the AI?” but “how do I set up the AI to work well with me on this project?” — everything got better. <strong>Less repetition, fewer corrections, more flow.</strong></p><p>Here’s a real example from iWish. Every time I touched a database model or schema file, the AI needed to know: use Alembic for migrations, always test the downgrade, never use datetime.now(). Instead of repeating that every single time, I defined it once as a skill:</p><pre>---<br>name: db-migration<br>description: MUST be invoked before any SQLAlchemy model change, new table,<br>new column, new enum, or Alembic migration file. <br>Use this whenever touching models.py, alembic/versions/, <br>or any database schema change.<br>---<br><br># Database Migration Skill## When to Use<br><br>This skill activates when modifying database models or working with migrations.<br>## Key Rules<br>1. **Always use Alembic** - never modify schema manually<br>2. **Always backup first** - before running migrations<br>3. **Test downgrade** - verify migrations are reversible<br>4. **Use utcnow()** - never `datetime.now()` for timestamps<br><br>Full guide: `windsurf/docs/alembic_database_migration.md`<br></pre><p>The elegant part is how this actually works under the hood. The AI agent only reads the skill <em>definition</em> — the name and description — and decides whether it’s relevant to the current task. It only loads the full content if it actually needs it. So your context window doesn’t get crowded with instructions that aren’t relevant to what you’re doing right now.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*peNLa4cus0Rl2ISdeMr0dw.png" /></figure><p>Think of it like a smart index. The agent knows what tools are available without having to load all of them at once. As your project grows and you accumulate more skills, this becomes genuinely important — otherwise you’d be stuffing the AI’s context with migration rules every time you’re just fixing a CSS bug.</p><p>Here are the official Windsurf docs URLs for each layer:</p><ul><li><strong>Rules</strong> → <a href="https://docs.windsurf.com/windsurf/cascade/rules">https://docs.windsurf.com/windsurf/cascade/rules</a></li><li><strong>Skills</strong> → <a href="https://docs.windsurf.com/windsurf/cascade/skills">https://docs.windsurf.com/windsurf/cascade/skills</a></li><li><strong>Memories</strong> → <a href="https://docs.windsurf.com/windsurf/cascade/memories">https://docs.windsurf.com/windsurf/cascade/memories</a></li><li><strong>Workflows</strong> → <a href="https://docs.windsurf.com/windsurf/cascade/workflows">https://docs.windsurf.com/windsurf/cascade/workflows</a></li></ul><h3>A word about the AI coding influencer wave</h3><p>Social media is flooded right now with AI coding “experts.” Courses, threads, YouTube channels, LinkedIn carousels. And look — some of it helped me. I picked up a few useful tricks from people sharing their setups.</p><p>But the more I watched, the more I noticed a pattern: <strong>a lot of these people are selling more than building.</strong></p><p>The content is about AI coding. The product is the course about AI coding. The proof of expertise is the follower count, not the shipped product.</p><p>It’s not unique to this space — it happens in every wave of new technology. Teaching scales better than building. Influence compounds faster than code. And there’s nothing inherently wrong with education and content creation.</p><p>But it gets worse. Increasingly, I suspect a lot of this content isn’t even written by the people selling it. No hands-on testing, no real projects behind it — just agents generating tutorials about how to use agents. The irony writes itself.</p><p>If you’re learning to build with AI, I’d encourage you to be a little selective about who you actually learn from. Look for people who are shipping things. Look for the GitHub links, the beta apps, the honest post-mortems. The people who are a little too busy building to post every day.</p><blockquote>The best thing I did during my sabbatical wasn’t watching tutorials. It was opening Windsurf and starting to build something I actually cared about.</blockquote><h3>Finally</h3><p>That’s where I am right now — three apps with users, a lot of lessons in my head, and genuinely more excited about building than I’ve been in years.</p><p>If you’re using <a href="https://iwish.gifts/">iWish</a> for an upcoming event, or want to try <a href="https://guaxinim-financas.com.br/">Guaxinim Finanças</a> to get your finances under control, <strong>I’d love your feedback.</strong> And as always — questions, pushback, suggestions in the comments. That’s what makes writing these worth it.</p><p>(if you wanna follow my projects I’m adding all of them here -&gt; <a href="https://guaxinimapps.pages.dev/">https://guaxinimapps.pages.dev</a>)</p><blockquote>P.S. — A small heads-up on transparency: this post was written with AI assistance. The ideas, experiences, and opinions are entirely mine — I outlined the content, defined the structure, and wrote the core of each section. Claude helped me shape the language, improve the flow, and keep the tone consistent. Felt only right to mention it, given the topic.</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6cad3aff0639" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Lessons on LLMs, Coding, and System Design from a Short Sabbatical]]></title>
            <link>https://lfomendes.medium.com/what-i-learned-during-my-short-sabbatical-637a41600fdb?source=rss-4120e6551cbe------2</link>
            <guid isPermaLink="false">https://medium.com/p/637a41600fdb</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[vibe-coding]]></category>
            <category><![CDATA[llm]]></category>
            <dc:creator><![CDATA[Luiz Felipe Mendes]]></dc:creator>
            <pubDate>Fri, 19 Dec 2025 17:54:04 GMT</pubDate>
            <atom:updated>2025-12-19T18:38:00.878Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Y9P4Dykqpd1PvRmDG-SfUA.jpeg" /></figure><p>After <strong>three months</strong> on sabbatical — studying, traveling, building things, and revisiting fundamentals — I felt it was worth writing down some of the lessons I picked up along the way.</p><p>This is not a guide, a manifesto, or a set of best practices.<br> It’s simply a collection of reflections from a period where I slowed down, went back to hands-on work, and tried to understand how modern AI tools <em>actually</em> fit into real systems and products.</p><p><strong>Before talking about <em>why</em> I took a sabbatical, I want to start with the most practical thing I learned while building with LLMs every day:</strong></p><blockquote>Most problems with LLM-based systems are <strong>not only</strong> prompt problems — they’re <strong>architecture problems</strong>.</blockquote><p>During this period, I built several small projects using LLMs as real system components — not demos. What consistently made the difference wasn’t clever prompting, but <strong>how the system around the LLM was designed</strong>.</p><p>Here are a few lessons that changed how I now think about building with LLMs.</p><h3>Practical Lessons from Using LLMs Daily</h3><h4>Avoid the “Mega Prompt” Trap</h4><p>One of the first mistakes I kept seeing (and making) was trying to encode everything into a single massive prompt.</p><p>In practice, it works much better to:</p><ul><li>split the flow into smaller, focused prompts,</li><li>let each prompt solve one clear problem,</li><li>and compose the results downstream.</li></ul><p>Smaller prompts are easier to reason about, debug, and evolve over time.</p><h4>Hybrid Flows Beat Prompt Fighting</h4><p>In one project, the LLM kept producing a formatting error I explicitly asked it to avoid.<br> No matter how much I tweaked the prompt, the issue persisted.</p><p><strong>The solution wasn’t better prompting.</strong></p><p>Instead, I introduced a deterministic step:</p><ul><li>a simple function validated the output,</li><li>and when the error appeared, a <strong>small “corrector prompt”</strong> fixed it.</li></ul><p>This hybrid approach — classical logic plus LLMs — turned out to be far more reliable than relying on a single prompt to behave perfectly.</p><h4>Evaluation and Prompt Versioning Matter</h4><p>LLMs are still AI systems, which means they need <strong>evaluation</strong>, even when outputs are qualitative.</p><p>As <a href="https://huyenchip.com/">Chip Huyen</a> points out, having <em>some</em> evaluation strategy is essential.<br>Equally important is prompt management:</p><ul><li>Do you store prompts in a database?</li><li>Do you version them in Git?</li><li>How do you roll back a change that silently degraded quality?</li></ul><p>These become real engineering problems surprisingly fast.</p><h4>Meta-Prompting Is a Superpower</h4><p>Instead of writing prompts from scratch, I started using LLMs to generate the <em>first version</em> of a prompt.</p><p>I’d describe the goal, ask for a draft, and then refine it.<br>This consistently surfaced assumptions and constraints I hadn’t considered.</p><h4>Cost-Aware Orchestration Wins</h4><p>Finally, cost matters more than most people expect.</p><p>A pattern that worked very well:</p><ul><li>use a <strong>state-of-the-art model</strong> for planning and design,</li><li>produce a clear plan in Markdown,</li><li>and pass that plan to a <strong>smaller, cheaper model</strong> for execution.</li></ul><p>You keep most of the quality while drastically reducing cost.</p><h3>Why I Decided to Dive Deep Again</h3><p>I wanted to better understand <strong>LLMs, agents, and how they truly integrate into products and classical ML systems</strong>.</p><p>LLMs are everywhere right now. But in practice, I kept seeing the same patterns:</p><ul><li>LLMs being used where simpler systems would work better</li><li>complexity added without a clear payoff</li><li>impressive demos that don’t survive contact with production</li></ul><p>So my goal during this sabbatical was simple:</p><blockquote><em>Understand where LLMs </em>actually shine<em>, where they don’t, and how to combine them with traditional ML instead of replacing everything with a single model.</em></blockquote><p>This exploration came from a mix of:</p><ul><li>structured courses,</li><li>books,</li><li>and, most importantly, building things end to end.</li></ul><h3>How LLMs Changed the Way I Code</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8xtA3a41kC_XD9Xze-5tLw.png" /></figure><p>With tools like Windsurf (and experiments with Devin), the feedback loop is dramatically shorter. Going from an idea to a working prototype can take minutes instead of days.</p><p>But there’s an important caveat:</p><blockquote><em>LLMs don’t replace thinking.<br>They replace friction.</em></blockquote><p>If you’re clear about what you want to build, LLMs multiply your productivity.<br> If you’re not, they just help you move faster in the wrong direction.</p><p>This reinforced something I had almost forgotten: <strong>strong fundamentals matter even more when you have powerful tools</strong>.</p><h3>LLMs Don’t Replace Classical ML — They Complement It</h3><p>One misconception I see often is the idea that LLMs will replace:</p><ul><li>recommendation systems</li><li>ranking models</li><li>search pipelines</li><li>embeddings</li><li>or even basic feature-based models</li></ul><p>In practice, the opposite is true.</p><p>LLMs work best as <strong>orchestrators</strong>, not as a silver bullet.</p><p>Some observations from hands-on work:</p><ul><li>smaller, specialized models are still cheaper, faster, and more reliable for many tasks</li><li>good embeddings + indexing often outperform a giant model</li><li>RAG helps, but it’s not magic — bad data in still means bad output out</li></ul><p>The most robust systems I’ve seen (and built) are <strong>hybrid by design</strong>.</p><h3>Agents: Useful, but Not Everywhere</h3><p>I spent some time studying agentic systems (including Andrew Ng’s Agentic AI course), and my takeaway is fairly pragmatic.</p><p>Agents are not “autonomous intelligence.”<br> They’re <strong>decision flows with memory and tools</strong>.</p><p>They work well when:</p><ul><li>tasks are long or repetitive</li><li>multiple tools or APIs are involved</li><li>partial autonomy is acceptable</li></ul><p>They fail when:</p><ul><li>correctness must be absolute</li><li>the domain is very constrained</li><li>mistakes are expensive</li></ul><p>The most useful question shifted from:</p><blockquote><em>“How do I add an agent to this product?”</em></blockquote><p>to:</p><blockquote><em>“Which part of this product truly benefits from partial autonomy?”</em></blockquote><p>Often, the honest answer is: <em>none</em>.</p><h3>Revisiting the Fundamentals (Programming Matters)</h3><p>Alongside LLM-focused work, I deliberately went back to fundamentals.</p><p>I’m currently halfway through a Deep Learning specialization with <strong>PyTorch</strong>, and that decision was intentional.</p><p>With LLMs writing code for us, it’s easy to:</p><ul><li>stop touching tensors</li><li>forget how autograd really works</li><li>treat models as black boxes</li></ul><p>Writing PyTorch “by hand” again — layers, losses, backprop — was grounding.</p><p>It reminded me that:</p><ul><li>understanding what’s happening under the hood makes you a better engineer</li><li>fundamentals give you intuition, not just answers</li><li>LLMs are far more powerful when <em>you</em> know what you’re asking for</li></ul><h3>Building Small Projects Beats Reading Big Ideas</h3><p>One recurring lesson: <strong>small projects teach faster than big theories</strong>.</p><p>During this period, I built personal tools end to end (<a href="https://medium.com/@lfomendes/when-coding-a-finance-tracker-becomes-easier-than-making-a-spreadsheet-d1a315f84970">including a finance tracker I previously wrote about</a>). These projects forced me to deal with:</p><ul><li>trade-offs</li><li>incomplete requirements</li><li>architecture decisions</li><li>and messy reality</li></ul><p>LLMs made MVPs faster, but they didn’t remove responsibility.<br>You still have to decide <em>what</em> to build and <em>why</em>.</p><p>Returning to hands-on programming reignited a part of my motivation I didn’t realize I was missing.</p><h3>Final Thoughts</h3><p>The biggest takeaway from this sabbatical wasn’t technical.</p><p>It was this:</p><ul><li>tools change fast</li><li>fundamentals change slowly</li><li>good systems are still built, not prompted</li></ul><p>LLMs are incredibly powerful, but they shine when combined with:</p><ul><li>solid engineering</li><li>classical ML</li><li>good data</li><li>and clear product thinking</li></ul><p>I plan to keep sharing what I learn as I go.</p><p>If you’re interested in following along:</p><ul><li><strong>LinkedIn:</strong> <a href="https://www.linkedin.com/in/lfomendes/">https://www.linkedin.com/in/lfomendes/</a></li><li><strong>Medium:</strong> <a href="https://lfomendes.medium.com/">https://lfomendes.medium.com/</a></li></ul><p>Thanks for reading.</p><h3>Further Reading &amp; Courses</h3><p>If you’re interested in diving deeper into some of the topics I mentioned, these resources heavily influenced my thinking during this period:</p><h3>📚 Books</h3><ul><li><strong>Designing Machine Learning Systems</strong> — Chip Huyen<br> <a href="https://huyenchip.com/machine-learning-systems-design/">https://huyenchip.com/machine-learning-systems-design/</a></li><li><strong>AI Engineering</strong> — Chip Huyen<br> <a href="https://huyenchip.com/ai-eng/">https://huyenchip.com/ai-eng/</a></li></ul><h3>🎓 Courses</h3><ul><li><strong>Agentic AI</strong> — DeepLearning.AI (Andrew Ng)<br> <a href="https://learn.deeplearning.ai/courses/agentic-ai/information">https://learn.deeplearning.ai/courses/agentic-ai/information</a></li><li><strong>PyTorch for Deep Learning (Professional Certificate)</strong> — DeepLearning.AI<br> <a href="https://learn.deeplearning.ai/specializations/pytorch-for-deep-learning-professional-certificate/overview">https://learn.deeplearning.ai/specializations/pytorch-for-deep-learning-professional-certificate/overview</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=637a41600fdb" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[When Coding Becomes Easier Than Making a Spreadsheet]]></title>
            <link>https://lfomendes.medium.com/when-coding-a-finance-tracker-becomes-easier-than-making-a-spreadsheet-d1a315f84970?source=rss-4120e6551cbe------2</link>
            <guid isPermaLink="false">https://medium.com/p/d1a315f84970</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[spreadsheets]]></category>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[vibe-coding]]></category>
            <category><![CDATA[ai]]></category>
            <dc:creator><![CDATA[Luiz Felipe Mendes]]></dc:creator>
            <pubDate>Mon, 27 Oct 2025 21:44:01 GMT</pubDate>
            <atom:updated>2025-10-28T16:08:41.107Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dmwbLbvW7SYQJklgb2cf_A.png" /></figure><p>Spreadsheet are very useful and you can do a lot of with them, but when you actually try to build something from scratch — a personal finance tracker, for example — you realize how quickly that<strong> power turns into pain.</strong></p><p>It started innocently. I just wanted to organize my spendings — things like house expenses, dog costs, <a href="https://medium.com/@lfomendes/using-openai-api-to-make-a-coffee-barista-part-1-9ea500c90d77">COFFEE</a>, groceries, trips, supplements, and streaming subscriptions. A few categories, some monthly averages, maybe a chart or two. Simple, right?</p><p><strong>Not really.</strong></p><p>Within an hour, I was already buried under formulas, references, and endless cells. Each new feature (like recurring payments or monthly summaries) meant even more complexity. And every time I changed something, half of the sheet broke.</p><p>That’s when a thought hit me:</p><blockquote>“It might actually be easier to code this than to make it on a spreadsheet.”</blockquote><h3>The AI-Programming Moment</h3><p>I’ve been programming for more than 17 years, and lately I’ve been playing with AI-assisted development tools (“vibe coding”). You don’t have to write everything yourself anymore. You just describe what you want, iterate, and let the AI help you turn an idea into a working product.</p><p>So, instead of fixing broken formulas, I opened <a href="https://windsurf.com/">Windsurf IDE</a> and decided to <strong>build my own finance tracker webapp.</strong></p><p>In less than a day, I had something that looked (and worked) far better than any spreadsheet I’ve ever made. I could:</p><ul><li>Add expenses with categories and subcategories</li><li>Track recurrent costs like rent or mortgage</li><li>Visualize my spending with filters and charts</li><li>Even upload my <strong>ugly PDF credit card statements</strong> and have the app extract and categorize everything automatically</li></ul><p>It felt magical — not because of the features themselves, but because of how fast it came together.</p><h3>The APP</h3><p>The result was this: a clean, organized dashboard where I can finally <em>see</em> where my money goes without fighting with formulas.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*r8yO7hGRxkgMVN1WDc_60Q.png" /><figcaption>The app with some dummy data</figcaption></figure><p>The dashboard shows monthly summaries, spending trends, and category breakdowns. Each expense has a category, a subcategory, and optional recurrence, so I can easily distinguish between my monthly mortgage and one-time purchases.</p><p>There’s also a <strong>“spending by category”</strong> chart that makes it obvious where most of my budget goes — travel, home, food, streaming, education — and a <strong>recurrent cost tracker</strong> that automatically calculates my baseline monthly spending.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HGP_0DIzAiWI64scWzGoXQ.png" /><figcaption>Deep dive into some category</figcaption></figure><p>One of the most useful features, though, is the <strong>PDF reader</strong>. My credit card statement is a PDF nightmare — and if you’re a programmer, you know that parsing non-standardized PDFs is one of the worst tasks imaginable.</p><p>Now, I can just upload the file and let the AI do the heavy lifting: it extracts each transaction, parses the text, and adds the expenses automatically. I only need to categorize them, and they’re ready for analysis — no more copying and pasting from bank apps.</p><p>I even added a small flow to detect <strong>duplicate entries</strong>, using heuristics like matching amounts on the same day or similar descriptions.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HtTk0JMs_BFuUpmMDh83SQ.png" /></figure><p>And that’s the best part: adding new features like this is fast, easy, and dynamic.</p><h3>Programming in the Age of AI</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TgXhjoWm6BadKiSESnLyQg.png" /></figure><p>After building four different projects from scratch with AI assistance, I can say this with confidence: <strong>programming today feels completely different</strong>. It’s much faster — sometimes shockingly so — but it also demands a new way of thinking.</p><p><strong>AI can accelerate everything, but it still needs <em>guidance</em>.</strong> That’s where experience comes in. My background in computer science and years of programming helped me understand when the AI was going in the wrong direction, or how to “unstick” it and guide it toward cleaner, more efficient code.</p><p>It might look easy — and in a sense, it is easier to start — but great results still depend on having the right mental models. You need to know when to ask for help, how to decompose problems, and how to review and refine the code that AI generates.</p><p>I’m also developing my own <strong>best practices for AI-assisted development</strong> — how to prompt, how to structure iterations, and how to balance control and creativity. I might write another post soon diving deeper into that, with concrete examples.</p><p>PS: This post was written by a human (me) but revised and refactored with an LLM.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d1a315f84970" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using OpenAI API to Make a Coffee Barista — Part 3]]></title>
            <link>https://lfomendes.medium.com/using-openai-api-to-make-a-coffee-barista-part-3-d5bc7cb8a203?source=rss-4120e6551cbe------2</link>
            <guid isPermaLink="false">https://medium.com/p/d5bc7cb8a203</guid>
            <category><![CDATA[openai]]></category>
            <category><![CDATA[rags]]></category>
            <category><![CDATA[genai]]></category>
            <category><![CDATA[coffee]]></category>
            <category><![CDATA[llm]]></category>
            <dc:creator><![CDATA[Luiz Felipe Mendes]]></dc:creator>
            <pubDate>Thu, 27 Mar 2025 17:17:50 GMT</pubDate>
            <atom:updated>2025-03-27T17:43:58.303Z</atom:updated>
            <content:encoded><![CDATA[<h3>Using OpenAI API to Make a Coffee Barista — Part 3</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vPq4qxiLnt4LFQFM6GhPXg.png" /></figure><p>Welcome back to my journey of building a web-based barista app powered by Genenrative AI! If you’re new here, this is the third part of a series where I’m blending my love for coffee with my professional side doing AI models.</p><p>In <a href="https://lfomendes.medium.com/using-openai-api-to-make-a-coffee-barista-part-1-9ea500c90d77">Part 1</a>, I introduced the initial version of the app. The goal was to create a simple web interface using Streamlit that leverages the OpenAI API to assist coffee lovers in brewing the perfect cup. Users could either learn from scratch, improve their brew, or ask the app coffee-related questions. It was a fun MVP that used LLMs and gave a good enough result.</p><p>In <a href="https://lfomendes.medium.com/using-openai-api-to-make-a-coffee-barista-part-2-now-using-rag-73ef598aa0f8">Part 2</a>, I addressed a key challenge: improving the accuracy of the app’s responses. I introduced a Retrieval-Augmented Generation (RAG) system to provide more reliable answers backed by curated content from coffee experts like James Hoffmann. By implementing RAG, the barista app could now fetch trustworthy information while still delivering engaging and helpful advice.</p><p>In this third part, I’ll walk you through several improvements: refining the prompts, enhancing the RAG system, and adding caching to make the app faster and more cost-effective.</p><p>If you’d like to explore the source code, you can find it <a href="https://github.com/lfomendes/guaxinim-barista">here</a>.</p><h3><strong>New version</strong></h3><p>While experimenting with version 2 of my Personal Barista, I identified several areas for improvement:</p><ul><li>Prompts</li><li>Reliable Sources</li><li>Document Representation</li><li>RAG return</li><li>Cache</li></ul><p>Let’s dive into each of these changes.</p><h3><strong>Prompts</strong></h3><p>I restructured the prompts to follow a more effective format:</p><ol><li><strong>Task</strong></li><li><strong>Return Format</strong></li><li><strong>Warnings/Limitations</strong></li><li><strong>Context</strong></li></ol><p>Here’s an example of a new prompt format, where {context_str} comes from the RAG result:</p><pre>Goal: Provide a clear, accurate, and helpful answer to a coffee-related question using both provided context and barista expertise.<br><br>Return Format:<br>    Your response should be structured as follows:<br>    1. Direct answer to the question (2-3 sentences)<br>    2. Supporting explanation with technical details (if relevant)<br>    3. Practical tips or recommendations (if applicable)<br>    4. References to specific sources from context (if available)<br><br>Warnings:<br>    - Stick to factual information from the context when available<br>    - Clearly distinguish between context-based information and general barista knowledge<br>    - Avoid speculation or unsupported claims<br>    - Keep the answer focused and relevant to the specific query<br><br>Context:<br>    ---------------------<br>    {context_str}<br>    ---------------------<br><br>Query: {query_str}<br>Answer:</pre><h3>Reliable Sources</h3><p>In version 2, the barista’s knowledge base was limited. To improve this, I added a script that collects transcriptions from several trusted YouTube coffee influencers.</p><p>Running initialize_knowledge_base.py now fetches transcripts from 30 curated videos from each channel, processes the text, and creates embeddings for both individual chunks and summaries.</p><p>I’ve included four recommended channels in youtube_channels.json:</p><ul><li><a href="https://www.youtube.com/channel/UCMb0O2CdPBNi-QqPk5T3gsQ">jameshoffman</a></li><li><a href="https://www.youtube.com/@EuropeanCoffeeTrip">europeancoffeetrip</a></li><li><a href="https://www.youtube.com/@LanceHedrick">LanceHedrick</a></li><li><a href="https://www.youtube.com/@morgandrinkscoffee">morgandrinkscoffee</a></li></ul><p>With this update, expanding the barista’s knowledge base is now fast and efficient — one script does it all!</p><h3>Document Representation</h3><p>Other thing that I missed while using the app was more information about each source.</p><p>I realized that adding more metadata could improve search quality. I now use an LLM to generate concise summaries and relevant tags for each document. This additional context helps the app identify the most relevant information more effectively.</p><p>Here is the prompt that I’ve used for that:</p><pre>   prompt = f&quot;&quot;&quot;Given the following video title and transcript, please provide:<br>           1. A concise summary of the video content (max 200 words)<br>           2. 5 relevant tags that best represent the video&#39;s content<br><br>           Title: {title}<br>           Transcript: {text}<br><br>           Please format your response as follows:<br>           SUMMARY:<br>           [Your summary here]<br><br>          TAGS:<br>          - [tag1]<br>          - [tag2]<br>          - [tag3]<br>          - [tag4]<br>          - [tag5]&quot;&quot;&quot;</pre><p>Not every task is ideally suited for an LLM, but they are very good at summarizing content and generating relevant tags from text.</p><p>Here’s an example of the updated format:</p><pre>{<br>&quot;title&quot;: &quot;3 Essential Hario V60 Recipes: James Hoffmann, Tetsu Kasuya <br>          &amp; Osmotic Flow&quot;,<br>&quot;source&quot;: &quot;https://youtube.com/watch?v=P0mI6Ue8BKc&quot;,<br>&quot;summary&quot;: &quot;In this video, the hosts explore three different Hario V60 coffee brewing recipes developed by James Hoffmann, <br>Tetsu Kasuya, and the osmotic flow method. Each method is explained in detail, <br>including the grind size, pouring technique, and brewing time. <br>The hosts demonstrate the step-by-step process for each recipe and <br>taste and compare the results. The video emphasizes that there is <br>no single best recipe for everyone, but these three techniques provide<br> a solid foundation for creating a personalized V60 brewing method.&quot;,<br>&quot;tags&quot;: [<br>    &quot;Hario V60&quot;,<br>    &quot;Coffee brewing&quot;,<br>    &quot;James Hoffmann&quot;,<br>    &quot;Tetsu Kasuya&quot;,<br>    &quot;Osmotic flow method&quot;<br>  ],<br>  &quot;chunks&quot;: [<br>    &quot;[Music] in this video we picked three hario v60 recipes that we believe give you a solid framework for improving your poor over coffee game we picked recipes developed by james hoffman tetsu kasuya and method called osmotic flow for each method we will give a little insight into its origin and main brewing approach then we will take you step by step through proving coffee using this recipe and at the end we will taste and compare different results unfortunately there is not a single best recipe the ultimate one that would work for everyone but we hope this video will help you to pick or create your favorite v60 method let&#39;s start with james hoffman&#39;s recipe he presented his ultimate v60 coffee technique back in 2019 i use it in different variations and came across this method in many coffee shops the brewing technique focuses on small number of pores and increase extraction by using finer grind size and increased agitation so let&#39;s try it let&#39;s prove james hoffman recipe first we will&quot;,<br>    &quot;prepare our filter and wash it with hot or even boiling water if you have a plastic v60 it&#39;s not that important to have it hot but if you have ceramic v60 the boiling water is better because it gets your dripper heated properly okay we are gonna use 18 grams of coffee grind on commandante 21 clicks even the bed and now make a little well in the coffee grounds this is so the water gets absorbs faster and more evenly into the coffee now we can start we&#39;ll pour 45 grams of water usually james recommends to use two to three times the weight of the coffee and straight after pouring mix all coffee grounds until they are even don&#39;t worry to give it a proper stir and now we wait 45 seconds the pre-infusion phase is for all the co2 to escape the coffee so we can extract more flavors and it&#39;s especially important because now we have quite fine grind so it helps to escape faster now the first pour it&#39;s 60 of our total volume and that&#39;s up to 180 grams we should pour this in about 20 seconds this&quot;,<br>    &quot;is for you to im.......&quot;]<br>}</pre><h3>RAG return</h3><p>In the earlier version of my barista app, the RAG system retrieved text chunks from the knowledge base and used them directly as context in the prompt. While this approach worked reasonably well, I noticed some significant drawbacks during testing. For example, choosing two different incomplete recipes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wzRO6MiqnZWvPOefHWBM0A.png" /></figure><p>To address this, I introduced two key improvements:</p><ol><li><strong>Flexible Matching Options:</strong> I added a side menu in the app that allows users to choose between matching by <strong>chunks</strong> or <strong>summary</strong>.</li><li><strong>Customizable Return Types:</strong> Users can now select whether they want the RAG system to return only the most relevant <strong>chunks</strong> or retrieve the <strong>whole document </strong>as context<strong>.</strong></li></ol><p>Using isolated chunks often led to incomplete or fragmented information. For example, when asking about AeroPress techniques, the app sometimes combined details from two separate recipes, resulting in an unclear or confusing response. Similarly, if key information appeared across multiple chunks, the app would fail to provide a complete answer.</p><p>I found that the most effective combination is: “whole file” and summary matching. But feel free to test different options.</p><p>You can easily test these settings in the <strong>“Search Coffee Knowledge”</strong> section of the app, where you can explore various results and navigate through the associated tags.</p><p>To illustrate the difference, here’s a comparison between chunk-based and summary-based retrieval for the AeroPress method explanation.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/585/1*jZvnx7lDEwGDeWQfPypSPw.png" /><figcaption>Files and their tags returned while matching by chunk</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/585/1*vlztJUyjLMgGlIc02H_hcA.png" /><figcaption>Files and their tags returned while matching by summary</figcaption></figure><h3>Cache</h3><p>Since LLM requests are both time-consuming and costly, I added a Redis cache to improve performance.</p><p>For our barista the <a href="https://redis.io/pt/">Redis</a> cache is implemented before the context search — not just before the OpenAI call — maximizing efficiency. This was very easy using <a href="https://codeium.com/windsurf">Windsurf</a>, with two prompts and some code I had a Redis read to go saving my data.</p><p>Here it is an example of a key.</p><pre>&quot;guaxinim:{\&quot;args\&quot;: {\&quot;method\&quot;: \&quot;V60\&quot;}, <br>\&quot;func_name\&quot;: \&quot;get_coffee_guide\&quot;, <br>\&quot;instance_attrs\&quot;: {\&quot;similarity_field\&quot;: \&quot;chunks\&quot;},<br> \&quot;kwargs\&quot;: {\&quot;rag_return_type\&quot;: \&quot;chunks\&quot;}}&quot;</pre><p>I’ve created a cache decorator that handles:</p><ul><li>Generates unique cache keys based on function names and arguments</li><li>Serializes/deserializes data using pickle</li><li>Sets a TTL (Time To Live) for entries</li></ul><pre>```python<br>@persistent_cache(ttl_days=30)<br>def get_coffee_guide(method: str) -&gt; dict:<br>    # Your function implementation<br>    pass<br>```</pre><p>I also added a <strong>Clear Cache</strong> button in the side menu to simplify testing and experimentation.</p><h3>Lets make some coffee</h3><p>Alright, enough with the text and code — let’s talk about what really matters: <strong>coffee</strong>! After all, this is supposed to be a <em>barista</em> app, not a Python tutorial.</p><p>Recently, my partner gave me an <strong>AeroPress GO</strong> for my birthday. Since I’d never used one before, I figured it was the perfect opportunity to put my improved barista to the test.</p><p>I fired up the app, selected <strong>“Learn to make perfect coffee”</strong>, chose <strong>AeroPress</strong> as the method, and set the RAG options to:</p><p><strong>RAG Return:</strong> Whole file<br><strong>Similarity Field:</strong> Summary</p><p>The result? A step-by-step guide, straight from trusted coffee experts, with clear instructions and helpful tips.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/711/1*j-zP2etr2h75X3elQ3t8Jw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/729/1*teSf-AExa-dl5uLb06wWSw.png" /></figure><p>Since the AeroPress GO is smaller than the standard model, I had to tweak the recipe a bit. After some quick math (and resisting the urge to just wing it), I settled on <strong>12.5g of coffee</strong> with <strong>200ml of water</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QjHcTbT_lslETQBzTxittA.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*69SzBuVo50h4nXFjDuKufQ.jpeg" /><figcaption>Aeropress Go and the final delicious coffe cup</figcaption></figure><p>And the result? <strong>Delicious!</strong> Smooth, rich, and full of flavor.</p><p>The AeroPress seemed a bit intimidating at first, but it turns out it’s fast, easy to clean, and surprisingly versatile. I have a feeling this little gadget is going to become my go-to brewing method.</p><h3>Conclusion</h3><p>With these new improvements, my Racoon barista app has come a long way — and I’m pretty happy with where it stands now. The refined prompts, expanded knowledge base, improved RAG system, and caching have made it faster, smarter, and much more reliable.</p><p>This project started as a fun way to combine my love for coffee with my AI expertise, and it turned out to be an incredible learning experience. While I’m sure there’s always room for more tweaks and enhancements, I’m satisfied with the current state of the app.</p><p>Now that my caffeinated creation is brewing great results, I’m thinking about starting a new side project — this time inspired by another one of my passions: <strong>movies</strong>. I’m still brainstorming ideas, but who knows? Maybe my next post will feature a recommendation system that helps you pick the perfect film for your next movie night.</p><p>Until then, thanks for following along on this journey! If you have any suggestions, questions, or just want to chat about coffee (or movies), feel free to reach out.</p><p>Part 1: The beginning with generative AI<br><a href="https://lfomendes.medium.com/using-openai-api-to-make-a-coffee-barista-part-1-9ea500c90d77">https://lfomendes.medium.com/using-openai-api-to-make-a-coffee-barista-part-1-9ea500c90d77</a></p><p>Part 2: Raccoon learns RAG to improve accuracy<br><a href="https://lfomendes.medium.com/using-openai-api-to-make-a-coffee-barista-part-2-now-using-rag-73ef598aa0f8">https://lfomendes.medium.com/using-openai-api-to-make-a-coffee-barista-part-2-now-using-rag-73ef598aa0f8</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d5bc7cb8a203" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using OpenAI API to make a coffee barista — Part 2 (now using RAG)]]></title>
            <link>https://lfomendes.medium.com/using-openai-api-to-make-a-coffee-barista-part-2-now-using-rag-73ef598aa0f8?source=rss-4120e6551cbe------2</link>
            <guid isPermaLink="false">https://medium.com/p/73ef598aa0f8</guid>
            <category><![CDATA[genai]]></category>
            <category><![CDATA[openai]]></category>
            <category><![CDATA[llm]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[rags]]></category>
            <dc:creator><![CDATA[Luiz Felipe Mendes]]></dc:creator>
            <pubDate>Fri, 14 Feb 2025 21:05:07 GMT</pubDate>
            <atom:updated>2025-03-27T18:02:27.872Z</atom:updated>
            <content:encoded><![CDATA[<h3>Using OpenAI API to make a coffee barista — Part 2 (now using RAG)</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Bc8hbKFXv4UQ_GWI3GG2JA.png" /></figure><p><strong>Code available in: </strong><a href="https://github.com/lfomendes/guaxinim-barista"><strong>https://github.com/lfomendes/guaxinim-barista</strong></a></p><p>Hello everyone!</p><p>This is the second part of my personal project of creating a personal barista to help coffee lovers to make the best cup of coffee possible. The first part can be <a href="https://medium.com/p/9ea500c90d77">seen here</a>.</p><p>In the first part we created a simples coffee barista that can help you improve you coffee cup and respond to coffee related questions. Now I’m going to show how we can incorporate RAG to help the barista make fewer errors and provide reliable sources.</p><h3>What is RAG and why use one?</h3><p>I asked ChatGPT for help with my acidic coffee problem on two different days, and I got two completely different answers! One day, it suggested making the grind more fine, and the next time, it told me to go coarser. This is what we call AI “hallucination” — when the model comes up with stuff that isn’t exactly true. Both sounded plausible, but I consulted my most trusted coffee specialist (<a href="https://www.jameshoffmann.co.uk/">James Hoffman</a>) and found <a href="https://www.james-hoffmann.com/how-to-brew-less-acidic-coffee/#:~:text=Aging%20tends%20to%20reduce%20perceived,roasting%20can%20help%20mellow%20them.">this post</a>.</p><blockquote>A coarser grind means less surface area is exposed to water during brewing, resulting in lower acid extraction. Try going one notch coarser than you normally would for maximum smoothness. Just be aware that coarser grinds can also impact overall extraction, so experiment to strike the right balance.</blockquote><p>And that’s where Retrieval-Augmented Generation (RAG) comes in handy in AI. RAG helps make AI responses more accurate by data while generating answers. In the context of the personal barista app, this means it’s not just making stuff up — it’s pulling actual, relevant coffee info to help you get the best brew, every time. With RAG, the app offers solid coffee advice that’s both creative and <strong>well-grounded.</strong></p><h3>Creating a simple RAG</h3><p>To address the problem of varying or incorrect answers, we incorporate RAG into our barista application.</p><p>RAG systems can be very complex with databases, many jobs and steps. For our coffee barista V2.0.0 I decided to start simple. So these were my tasks for this version.</p><ul><li>Gather documents from reliable sources</li><li>Write a script that divides these documents into chunks. (pieces)</li><li>Create text embeddings for each chunk and save them in a JSON file.</li><li>During the app loading get this json file and put these embeddings into a Fasttext so we can do similarity search.</li><li>Create embeddings from the user queries and use a similarity search to get the most similar chunks from these documents</li><li>Change the prompt so it take these chunks into consideration while responding to the user</li><li>Add the sources into the interface</li></ul><p><strong>Documents</strong></p><p>Since this is the first version of our RAG, I downloaded three PDFs from the James Hoffman blog.</p><ul><li><a href="https://www.james-hoffmann.com/how-to-brew-less-acidic-coffee/">HowtoBrewLessAcidicCoffee.pdf</a></li><li><a href="https://www.james-hoffmann.com/how-to-make-tiramisu-coffee/">How to Make Tiramisu Coffee.pdf</a></li><li><a href="https://www.james-hoffmann.com/how-many-grams-of-coffee-for-cappuccino/">How Many Grams of Coffee for Cappuccino.pdf</a></li></ul><p>We are just creating a MVP, if it works for these 3 we can incorporate more curated data afterwards easily.</p><h3>Code</h3><p>For the PDF processing, I created the processor.py script, which divides the texts into chunks, creates embeddings, and saves them into a JSON file.</p><p>To create the embeddings I used the <a href="https://www.sbert.net/docs/quickstart.html">Sentence Transformer</a> since it is easy to use and have a good enough quality for this task. We load <a href="https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2">all-MiniLM-L6-v2</a>, which is a MiniLM model finetuned on a large dataset of over 1 billion training pairs.</p><blockquote>Our model is intended to be used as a sentence and short paragraph encoder. Given an input text, it outputs a vector which captures the semantic information. The sentence vector may be used for information retrieval, clustering or sentence similarity tasks.</blockquote><pre>def create_embeddings(chunks: List[str], model_name: str = &#39;all-MiniLM-L6-v2&#39;) -&gt; List[List[float]]:<br>    &quot;&quot;&quot;<br>    Create embeddings for a list of text chunks using sentence-transformers.<br>    <br>    Args:<br>        chunks (List[str]): List of text chunks to create embeddings for<br>        model_name (str): Name of the sentence-transformers model to use<br>        <br>    Returns:<br>        List[List[float]]: List of embeddings for each chunk<br>    &quot;&quot;&quot;<br>    model = SentenceTransformer(model_name)<br>    embeddings = model.encode(chunks, show_progress_bar=True)<br>    # Convert numpy arrays to lists for JSON serialization<br>    return embeddings.tolist()</pre><p>And I changed all prompts to take the information into consideration</p><pre>    CONTEXT_PROMPT_TEMPLATE = <br>    &quot;&quot;&quot;Context information is below.<br>    ---------------------<br>    {context_str}<br>    ---------------------<br>    Given the context information and your expertise as a professional barista,<br>    provide a answer to the query.<br>    Query: {query_str}<br>    Answer: &quot;&quot;&quot;</pre><p>With this we can see an answer from the barista citing the sources.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/884/1*9OQ3Y7H5LV0RZxNaIG_rVg.png" /></figure><p>I also created a new section of the app so we can debug this similarity search. This new screen has a text input and it returns the chunks and titles with their similarity score. In the two images below you can check a good match and a bad match as example.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/877/1*6-8SnlVsDRqPvRNJBWav4Q.png" /></figure><p>In this first example the input is about coffee and desserts. From the documents that we have, what we would expect is that the the chunks from the “How to Make Tiramisu Coffee” would be the most similar and it seems that our search return 3 chunks from this blog post. Great!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/877/1*vMDrd0HzzrLPdv5l-NH6UQ.png" /></figure><p>Now, for the second test I used a non-coffee relate question and we can see that the similarity scores are close to zero and one of them is even negative.</p><h3>App flow</h3><p>Now our barista app have two different flow, one that is offline. That is, we can run it only once to process all pdfs from a folder and save a json file.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1010/1*m8wq6Kapl04p--B1pCQpCA.png" /></figure><p>And a second flow that will load this json into the Fasttext, use this fasttext to do a similarity search for the chunks of information and incorporate them into the prompt.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Lja50cVAZ8lzKN8jr4puZg.png" /></figure><h3><strong>Results</strong></h3><p>And here is a video of this new version of the app:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FsfZZMsDefy8%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DsfZZMsDefy8&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FsfZZMsDefy8%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/aeb2d7ac5bae6b19f710d0e6502db509/href">https://medium.com/media/aeb2d7ac5bae6b19f710d0e6502db509/href</a></iframe><p>Now we can have a little more trust in our Barista, since he is studying from curated sources.</p><h3>Nexts steps</h3><p>Our Raccoon Barista is well on its way to becoming a reliable coffee companion. It now knows how to gather valuable information and respond to user queries, citing all sources used for transparency.</p><p>For the V3.0.0 I am planning to expand its information database and enhance interactivity, allowing users to engage in more dynamic conversations with the barista. I’m also considering writing a post on evaluating the quality of the barista’s answers.</p><p>I’d love to hear your thoughts on what additional features or improvements you’d like to see in our barista. Your suggestions are most welcome!</p><p>Until the next one!</p><p><strong>The third part is out</strong></p><p><a href="https://lfomendes.medium.com/using-openai-api-to-make-a-coffee-barista-part-3-d5bc7cb8a203">https://lfomendes.medium.com/using-openai-api-to-make-a-coffee-barista-part-3-d5bc7cb8a203</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=73ef598aa0f8" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using OpenAI API to make a coffee barista — Part 1]]></title>
            <link>https://lfomendes.medium.com/using-openai-api-to-make-a-coffee-barista-part-1-9ea500c90d77?source=rss-4120e6551cbe------2</link>
            <guid isPermaLink="false">https://medium.com/p/9ea500c90d77</guid>
            <category><![CDATA[openai]]></category>
            <category><![CDATA[genai]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[coffee]]></category>
            <category><![CDATA[llm]]></category>
            <dc:creator><![CDATA[Luiz Felipe Mendes]]></dc:creator>
            <pubDate>Wed, 29 Jan 2025 15:09:49 GMT</pubDate>
            <atom:updated>2025-03-27T18:02:01.454Z</atom:updated>
            <content:encoded><![CDATA[<h3>Using OpenAI API to make a coffee barista — Part 1</h3><figure><img alt="An adorable raccoon, wearing a stylish coffee barista apron and cap, is diligently brewing a cup of coffee using the V60 pour-over method. The raccoon is intensely focused, with its little paws expertly handling the coffee dripper. The background depicts a cozy coffee shop setting with soft lighting, conveying a warm and inviting atmosphere.”" src="https://cdn-images-1.medium.com/max/1024/1*aeLMdlWs-bbmkUiFZdOEaw.jpeg" /></figure><p><strong>Code available in: </strong><a href="https://github.com/lfomendes/guaxinim-barista"><strong>https://github.com/lfomendes/guaxinim-barista</strong></a></p><p>Like many other geeks I’ve been getting into the specialty coffee scene. It’s been an exciting and caffeine-fueled journey! <strong>Brewing a great cup is simple to start but tricky to master.</strong></p><p>I decided to blend my love for coffee with my interest in new technologies and tools.</p><p>My idea is to create a web app that uses LLMs (genAI) to help people brew better coffee while allowing me to experiment with new tools and APIs. I’ll share the code publicly and post insights in parts on Medium.</p><p>In this first installment, I’ll be building the app using <a href="https://streamlit.io/">Streamlit</a>, the <a href="https://openai.com/">OpenAI</a> API, and the <a href="https://codeium.com/windsurf">Windsurf IDE</a>. I know it might have some issues like occasional hallucinations and a “not-so-polished” interface. My apologies to all designers out there!</p><p>For those not familiar with Portuguese, ‘<strong>guaxinim</strong>’ (pronounced gwa-shee-neem) means raccoon. Why raccoons? They’re adorable, have human-like hands, and just might dream of crafting the perfect brew themselves!</p><p>So follow me in this caffeinated journey</p><h3>The MVP</h3><p>Let’s dive into the fun part: here’s the interface we’ve created so far.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/715/1*TpKNS_CzrXifaGOBE62u4A.png" /></figure><p>And a video of the app in action</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FDJaOtiP-BZo%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DDJaOtiP-BZo&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FDJaOtiP-BZo%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/114b1b2b2f705be629a5f978c4c6418b/href">https://medium.com/media/114b1b2b2f705be629a5f978c4c6418b/href</a></iframe><p>I think it is a good enough MVP with all the necessary capabilities and it took me only some hours to create with these new tools.</p><h3>The code</h3><p>The flow of the app is easy, the person chooses an action from</p><ul><li>Teach me how to brew from zero</li><li>Help me improve my brew</li><li>Ask anything coffee related to the web-barista</li></ul><p>Each action will show a different interface below but all of them will call an OpenAI api using its <a href="https://platform.openai.com/docs/api-reference/chat/create">chat completion</a> command.</p><p>For this mvp my folder is organized like this</p><pre>guaxinim/<br>├── guaxinim/<br>│   ├── __init__.py<br>│   ├── core/<br>│   │   ├── __init__.py<br>│   │   ├── guaxinim_bot.py<br>│   │   └── coffee_data.py<br>│   ├── ui/<br>│   │   ├── __init__.py<br>│   │   └── home.py<br>│   └── utils/<br>│       └── __init__.py<br>├── tests/<br>│   └── unit/<br>├── main.py<br>├── README.md<br>├── requirements.txt<br>├── .gitignore<br>└── env.example</pre><p>The <strong>Streamlit</strong> makes it easy to build an interface with only python code, almost everything for the interface is inside the home.py file.</p><p>Everything will be written in python using the <strong>windsurf IDE</strong>, I will try to use it as planned with some propts like this</p><pre>Analyze all .py files and suggest possible unit tests, create the necessary <br>folders and organize the files accordingly</pre><p>Just so you understand that was the result for this prompt at the time</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/465/1*fCcuWISP6cEOCxHVN62QXA.png" /></figure><h3>Prompts and OpenAI api</h3><p>I created 3 different prompts, one for each action, they can be found on the guaxinim_bot.py file. I’m using the chat completions from Open AI.</p><p><strong>Improve prompt</strong></p><pre><strong>system</strong><br>You are a professional coffee barista expert.<br><strong>user</strong><br>Analyze these coffee parameters and suggest improvements: Issue: <br>Too acidic Coffee amount: 20.0g Water amount: 180.0ml </pre><p><strong>Improve prompt</strong></p><pre>You are a professional coffee barista with years of experience.<br>You are teaching someone how to make an excellent cup of coffee using <br>the Cold Brew method. Please provide a detailed, step-by-step guide that <br>includes: 1. Required equipment 2. Recommended coffee-to-water ratio 3.<br>Grind size recommendation 4. Water temperature 5. Detailed brewing steps <br>6. Common mistakes to avoid 7. Tips for achieving the best results <br>Format your response in markdown for better readability.</pre><p><strong>Coffee question prompt</strong></p><pre><br><strong>system</strong><br>You are a professional coffee barista expert.<br><strong>user</strong><br>Check if the following question is coffee-related: <br>If yes: Provide a detailed answer <br>If no: Reply with &#39;I only answer questions about coffee.&#39; <br>Question: What is the best place to buy coffee?</pre><p>I’ve added a basic security feature to ensure the barista only answers coffee-related questions. I’ve tried to “hack” this but it seems that this protection is good enough for now.</p><p>Using OpenAI API is very straightforward, as demonstrated by the following code snippet:</p><pre>try:<br>    response = self.client.chat.completions.create(<br>        model=self.GPT_MODEL,<br>        messages=[<br>            {<br>                &quot;role&quot;: &quot;system&quot;,<br>                &quot;content&quot;: &quot;You are a professional coffee barista expert.&quot;,<br>            },<br>            {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: basic_prompt + query},<br>        ],<br>        temperature=0.2,<br>        max_tokens=500,<br>        store=True,<br>    )<br>    return response.choices[0].message.content<br>except (APIError, APIConnectionError) as e:<br>    return f&quot;Error processing question: {str(e)}&quot;</pre><p>You can check the documentation for chat completion <a href="https://platform.openai.com/docs/api-reference/chat">here</a>. I’m using 0.2 temperature to make it more focused and deterministic.</p><h3>Next Steps</h3><p>I’m very happy with the current state of this first version. It is available in the <strong>tag v1.0.0 (</strong>git checkout v1.0.0) in the <a href="https://github.com/lfomendes/guaxinim-barista">git repository</a>.</p><p>But now I want to take it to the next level by collecting some curated information about coffee from experts like <a href="https://www.jameshoffmann.co.uk/">James Hoffman</a> and improve the barista to use this knowledge and even point the user to the source of information.</p><p>This is usually what Retrieval-Augmented Generation (RAG) is used for, so in the <a href="https://medium.com/me/stats/post/73ef598aa0f8">next post</a> I will share my experience creating a simple RAG for this barista APP.</p><p>Thanks for reading! Feel free to leave any questions or suggestions in the comments.</p><p><strong>The second part is already out</strong></p><p><a href="https://lfomendes.medium.com/using-openai-api-to-make-a-coffee-barista-part-2-now-using-rag-73ef598aa0f8">https://lfomendes.medium.com/using-openai-api-to-make-a-coffee-barista-part-2-now-using-rag-73ef598aa0f8</a></p><p><strong>The third part</strong></p><p><a href="https://lfomendes.medium.com/using-openai-api-to-make-a-coffee-barista-part-3-d5bc7cb8a203">https://lfomendes.medium.com/using-openai-api-to-make-a-coffee-barista-part-3-d5bc7cb8a203</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9ea500c90d77" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Reflections on writing about Data Science: 2024 Posts]]></title>
            <link>https://lfomendes.medium.com/reflections-on-writing-aboutdata-science-2024-posts-4c1becaf7a70?source=rss-4120e6551cbe------2</link>
            <guid isPermaLink="false">https://medium.com/p/4c1becaf7a70</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[genai]]></category>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[Luiz Felipe Mendes]]></dc:creator>
            <pubDate>Mon, 23 Dec 2024 20:05:58 GMT</pubDate>
            <atom:updated>2024-12-23T20:06:31.832Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*R3Vl8HOARvSoI9hoG3J0nQ.png" /></figure><p>This year, I decided to start writing and sharing knowledge about Data Science. My goal wasn’t to become an influencer on LinkedIn/Medium, but rather to motivate myself to read more and think deeply about the content. Writing, even if just a simple summary, helps reinforce learning (pun not intended).</p><p>For those who missed it, here is a list of posts I published throughout the year:</p><p><a href="https://lfomendes.medium.com/weekly-reading-ai-agents-8414e387bfd8">Weekly Reading: AI Agents</a>: A post where I discuss the popular topic of AI agents.</p><p><a href="https://lfomendes.medium.com/weekly-reading-metas-approach-to-machine-learning-prediction-robustness-fae46957cf41">Weekly Reading: Meta’s Approach to Machine Learning Prediction Robustness</a>: A brief post highlighting Meta’s material on robustness in machine learning models, a topic also debated at iFood.</p><p><a href="https://lfomendes.medium.com/designing-a-machine-learning-system-2cd435ec434c">Designing a Machine Learning System</a>: A discussion about how an AI model is merely a part of a larger system, inspired by an excellent post by <a href="https://huyenchip.com/">Chip Huyen</a>.</p><p><a href="https://lfomendes.medium.com/recommended-reading-how-i-use-ai-by-nicholas-carlini-83d959744b19">Recommended Reading: How I Use “AI”</a>: Discussing the role of genAI in professional productivity, based on tips from the author <a href="https://nicholas.carlini.com/">Nicholas Carlini</a>.</p><p><a href="https://lfomendes.medium.com/transforming-data-into-art-the-evolution-of-cover-selection-at-netflix-b4a92da5c127">Transforming Data into Art: The Evolution of Cover Selection at Netflix</a>: My favorite post of the year, combining my passion for movies, series, and AI. It was meant to be just a post on Causal Machine Learning and turned into an exploration of Netflix’s evolution in choosing covers/artwork.</p><p><a href="https://lfomendes.medium.com/thoughts-on-rag-hybrid-search-and-rank-fusion-ab2024d2102b">Thoughts on: RAG, Hybrid Search, and Rank Fusion</a>: Reflections on important topics for my professional practice, such as RAG and Rank Fusion.</p><h3><strong>Conclusion</strong></h3><p>There were only a few posts, but I enjoyed the process of writing them. I’m not a writer, but these activities helped me read and reflect more on each topic. I hope they were helpful to others as well.</p><p><strong>Stay tuned, in 2025 there will be more!</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4c1becaf7a70" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>