<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Chandler</title>
    <description>The latest articles on Forem by Chandler (@chand1012).</description>
    <link>https://forem.com/chand1012</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F409814%2Ff4814a1f-6a35-45ab-b2c6-968707298848.jpeg</url>
      <title>Forem: Chandler</title>
      <link>https://forem.com/chand1012</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/chand1012"/>
    <language>en</language>
    <item>
      <title>I built a baby tracker app from my wife’s hospital room</title>
      <dc:creator>Chandler</dc:creator>
      <pubDate>Mon, 16 Feb 2026 22:40:20 +0000</pubDate>
      <link>https://forem.com/chand1012/i-built-a-baby-tracker-app-from-my-wifes-hospital-room-3i24</link>
      <guid>https://forem.com/chand1012/i-built-a-baby-tracker-app-from-my-wifes-hospital-room-3i24</guid>
      <description>&lt;p&gt;“I think my water broke!” Said my wife the day before her due date. Hastily, I threw all the pre-packed bags, a pillow and blanket for myself, and the baby’s carseat into the backseat of my truck. I took her to the hospital, which to our lack of surprise, she was right! Her water did break.&lt;/p&gt;

&lt;p&gt;It was a long day, especially for her. After 18 hours of labor then an emergency c-section at 3am, our son William was born. The first day after he was born, we slept, visited with family who made the drive to the hospital, and asked the nurses lots and lots of questions.&lt;/p&gt;

&lt;p&gt;One of the nurses asked, “Do you know what time he ate last?”&lt;/p&gt;

&lt;p&gt;We did not remember. It was quite late on his birthday at this point, she was in pain and we were both exhausted. We didn’t remember at all.&lt;/p&gt;

&lt;p&gt;The nurse said that we should try to keep track of it. Most people keep it in their phones notes app, but I figured surely there was a better solution for this.&lt;/p&gt;

&lt;p&gt;But my developer brain didn’t want to search the internet or ask an LLM for options. I wanted to build.&lt;/p&gt;

&lt;p&gt;After we both slept (the nurses graciously took him for a few hours so we could catch up on sleep), the next day I got to work.&lt;/p&gt;

&lt;p&gt;Except, that I really couldn’t. I didn’t bring my laptop, and while I have coded on my phone before, its a bit of a chore and I wanted something working that we could both use.&lt;/p&gt;

&lt;p&gt;Then I remembered, I had set up OpenClaw the previous weekend.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Claw
&lt;/h2&gt;

&lt;p&gt;OpenClaw, for those of you who don’t know, is a self-hosted AI assistant that’s meant to be like ChatGPT or Claude but has full access to the Linux system (or you laptop) its running on, and includes a vast skill library and the ability to connect basically any tool that can run on a Linux box or via MCP server. I’ve been using it as a general assistant, replacing ChatGPT and Claude as it had access to more tools that I found useful. &lt;/p&gt;

&lt;p&gt;So I have this AI agent that I can talk to via Telegram (and I mean literally talk - it can interpret Telegram voice messages) that has full access to a Linux server and I can give access to some of my cloud provider accounts. What can go wrong?&lt;/p&gt;

&lt;h2&gt;
  
  
  Surprisingly, not much
&lt;/h2&gt;

&lt;p&gt;I started from nothing - no template, no repo, only a basic idea of what tooling I wanted to use.&lt;/p&gt;

&lt;p&gt;I followed proper best agentic coding practice - by planning first. I have an iPhone, however my wife as a Samsung Galaxy, so I wanted this app to be web accessible, a PWA that &lt;em&gt;acts&lt;/em&gt; like a native app is preferred. I had just discovered &lt;a href="https://www.retroui.dev/" rel="noopener noreferrer"&gt;Retro UI&lt;/a&gt; and quite liked the brutalist aesthetic for an app that (for the time being) has just my wife and I as its only users. I’m quite fond of the Cloudflare Workers and Pages platform, and its ease of development and use should make it fast to develop and deploy for the agent. That’s the only guidance I gave it for stack - I wanted Retro UI (React implied) and I wanted the entire thing to be built on the Cloudflare Workers and Pages platform. I told it to come up with a plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Plan
&lt;/h2&gt;

&lt;p&gt;It thought that having a separate frontend and backend with a monorepo structure was best, tying the projects together using pnpm. The frontend uses Vite and React Router (which is one of the frameworks I quite like) and the aforementioned Retro UI. The backend uses Hono, which is quickly becoming the preferred backend framework for Typescript projects, as it has compatibility with a wide range of JS/TS runtimes (Deno, Node, Bun, Cloudflare, and more). For the database it chose to use Cloudflare D1 since its available, which is &lt;em&gt;fine&lt;/em&gt;. Given the tools I told it to use, it makes perfect sense, but &lt;em&gt;how&lt;/em&gt; it executed this integration is where we have some problems. I’ll get to that later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Execution
&lt;/h2&gt;

&lt;p&gt;Once OpenClaw gave me a definitive plan, I gave it an API key with the proper permissions it would need to deploy the application, and told it to execute. After some back and forth getting it to deploy, it deployed an MVP. A surprisingly functional MVP. I created an account, added a child, and decided to test out by adding his diaper we just changed. It worked first try. Feedings worked first try as well, thought I later had to ask it to allow the switching between measurement units (hospital used milliliters, most Americans use fluid oz) which I told it to store the amounts in the smaller unit integers (it stores in ml, converts on the fly based on the user’s preference and rounds the oz to the nearest tenth). There was some other back and forth for little bugs and feature requests I found here and there, but overall an incredibly good first attempt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it!
&lt;/h2&gt;

&lt;p&gt;I implore you to go try it out yourself, &lt;a href="https://babylog.chand1012.dev/" rel="noopener noreferrer"&gt;link here&lt;/a&gt;. Its super simple and my wife loves how easy it is to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problems
&lt;/h2&gt;

&lt;p&gt;The first big issue came up when I wanted to add naptime tracking. While its not something I’m doing with my, at the time of writing, 12 day old child, but it could be super useful in the future when he’s a bit older. OpenClaw noted that a bunch of the migrations are just missing from the local files, and that we really should have a migration system. Since I didn’t have the desire to fix it, I told it to work around it (which it did a great job at) but the lack of a migration system will definitely be an issue for the future when we want to add more features and update existing tables without breaking anything. On top of that while the app is written Typescript, there really isn’t super strong typing for the database due to the lack of ORM or migration system. This isn’t an issue in all cases, but I generally prefer strong typing for any of my projects. &lt;/p&gt;

&lt;p&gt;Getting the initial deployment was also quite annoying thanks to context poisoning. The OpenClaw kept hitting the wrong API endpoint to check if we had a valid API key and kept refusing to try and use it with the other API endpoints, until I finally gave it the API key with an example curl request then it started working. This process took me well over an hour, and was incredibly annoying since I got it consistently deploying and working in a different thread. This is what pushed me to set up proper CI/CD (technically I just told OpenClaw to do it) so that it didn’t have to deploy anything itself, just handle builds and pushing to the GitHub repo that I also had it create.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important note&lt;/strong&gt;: I did not use proper security practice when developing this, I went whole-hog no cares in the world just get it done ASAP. Under most circumstances, you should manually set up CI and deployment yourself and &lt;strong&gt;never, ever give an LLM your API keys.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;While this absolute zero to one development worked surprisingly well, I still think I’m going to scaffold the template first along with CI/CD pipelines before I set my AI agent lose on my project. While the code was fine, the lack of a migration system and the annoyance of getting the app properly deployed, I’d rather get that stuff working first so that development time can be even lower, spending less time on getting stuff working and more time iterating on features. Here’s a quick step-by-step on the Chandler Agentic Development flow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Chandler’s Agentic Prototype Flow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Think of a good problem to solve&lt;/li&gt;
&lt;li&gt;What kind of app do you want?

&lt;ol&gt;
&lt;li&gt;Hint - its probably a web app

&lt;ol&gt;
&lt;li&gt;You can make it a mobile app later, if you get more than yourself as a user.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;If its not, maybe a command line tool

&lt;ol&gt;
&lt;li&gt;This can evolve later into a local GUI based app&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;/li&gt;

&lt;li&gt;What frameworks?

&lt;ol&gt;
&lt;li&gt;If its a web app

&lt;ol&gt;
&lt;li&gt;If cloud hosted: React Router + Backend (&lt;a href="https://www.convex.dev/" rel="noopener noreferrer"&gt;Convex&lt;/a&gt;, &lt;a href="https://workers.cloudflare.com/" rel="noopener noreferrer"&gt;CF Workers&lt;/a&gt; + &lt;a href="https://developers.cloudflare.com/d1/" rel="noopener noreferrer"&gt;D1&lt;/a&gt; with &lt;a href="https://orm.drizzle.team/docs/get-started/d1-new" rel="noopener noreferrer"&gt;Drizzle&lt;/a&gt;, or Supabase)

&lt;ol&gt;
&lt;li&gt;If using Convex or Workers, use &lt;a href="https://clerk.dev/" rel="noopener noreferrer"&gt;Clerk&lt;/a&gt; for auth.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;If self hosted: NextJS App Router, Auth.js, SQLite via &lt;a href="https://orm.drizzle.team/docs/get-started/sqlite-new" rel="noopener noreferrer"&gt;Drizzle&lt;/a&gt;
&lt;/li&gt;

&lt;li&gt;For both: &lt;strong&gt;always use shadcn or a similar compatible component library&lt;/strong&gt;.&lt;/li&gt;

&lt;/ol&gt;

&lt;/li&gt;

&lt;li&gt;If its a command line app

&lt;ol&gt;
&lt;li&gt;Python for an MVP

&lt;ol&gt;
&lt;li&gt;Google’s Fire is great for a simple MVP&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;Go for a fast, easy to maintain CLI tool

&lt;ol&gt;
&lt;li&gt;Always use Cobra for CLI tools&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;/li&gt;

&lt;li&gt;If its a desktop GUI application

&lt;ol&gt;
&lt;li&gt;Tauri

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;always use shadcn or a similar compatible component library&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;/li&gt;

&lt;li&gt;If its a mobile app

&lt;ol&gt;
&lt;li&gt;React Native

&lt;ol&gt;
&lt;li&gt;Use Native-looking components with dark mode&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;Capacitor

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;always use shadcn or a similar compatible component library&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;/li&gt;

&lt;/ol&gt;

&lt;/li&gt;

&lt;li&gt;Scaffold the repo

&lt;ol&gt;
&lt;li&gt;Need CI/CD when deploying to main

&lt;ol&gt;
&lt;li&gt;Main is your release branch. All type checks, linting, and builds should pass.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;Need linters and type checkers via pre-commit

&lt;ol&gt;
&lt;li&gt;Type checking for &lt;strong&gt;all languages&lt;/strong&gt;, &lt;a href="https://docs.astral.sh/ty/" rel="noopener noreferrer"&gt;Python included&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;README and &lt;code&gt;CLAUDE.md&lt;/code&gt; should be well thought out and well written.

&lt;ol&gt;
&lt;li&gt;Follow &lt;a href="https://www.humanlayer.dev/blog/writing-a-good-claude-md" rel="noopener noreferrer"&gt;HumanLayer’s Claude best practices&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;For example, mention that you should use best practice, but you don’t need to give it examples.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;A proper &lt;code&gt;.gitignore&lt;/code&gt; with as much as you may need now or later added.

&lt;ol&gt;
&lt;li&gt;My hot take: I’d rather have too much in my ignore file than not enough.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;Add initial code

&lt;ol&gt;
&lt;li&gt;Simple “hello world” page for web apps with a hello world backend&lt;/li&gt;
&lt;li&gt;Set up the ORM properly&lt;/li&gt;
&lt;li&gt;Add scaffolding needed for shadcn components&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;Initial test deployment

&lt;ol&gt;
&lt;li&gt;Do an initial test deployment to make sure that CI/CD works&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;/li&gt;

&lt;li&gt;Now let the agent do its thing

&lt;ol&gt;
&lt;li&gt;Once you had the scaffolding complete, its much easier for the AI agent to quickly iterate on features&lt;/li&gt;
&lt;li&gt;This saves time and token costs, especially when using high quality LLMs like Opus 4.6.&lt;/li&gt;
&lt;li&gt;Since all the hard stuff is done, you can do parallel features via apps like &lt;a href="https://www.conductor.build/" rel="noopener noreferrer"&gt;Conductor&lt;/a&gt;, &lt;a href="https://cursor.com/docs/cloud-agent" rel="noopener noreferrer"&gt;Cursor Cloud Agents,&lt;/a&gt; or &lt;a href="https://github.com/features/copilot/agents" rel="noopener noreferrer"&gt;Copilot Agents on GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;If there’s a headline here, it’s that agentic coding is already good enough to be useful in the messiest, highest-stakes moments of real life, when you’re sleep deprived, context switching constantly, and you just need something that works.&lt;/p&gt;

&lt;p&gt;OpenClaw got me from idea to a working baby tracker in a day, from a hospital room, without the usual ceremony. That’s a big deal. The MVP was solid, the iteration loop was fast, and the app is now something we actually use.&lt;/p&gt;

&lt;p&gt;But it also made the tradeoffs impossible to ignore. When you skip fundamentals like migrations, typed data access, and a repeatable deploy pipeline, you can ship quickly, but you’re borrowing friction from your future self. The hour lost to context poisoned deployment and the awkward database setup were reminders that agents are powerful, but they still need guardrails.&lt;/p&gt;

&lt;p&gt;So my current takeaway is simple: let the agent sprint, but give it a track to run on. Scaffold the repo. Lock down CI/CD. Put migrations and typing in place. Then hand off the “build the feature” work to the agent and spend your own time making product calls, testing, and prioritizing.&lt;/p&gt;

&lt;p&gt;Babylog was a tiny project, but it changed how I think about prototyping. The bar for “I can just build this” has dropped dramatically, and with the right scaffolding, it’s only going to drop further.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The best way to do agentic development in 2026</title>
      <dc:creator>Chandler</dc:creator>
      <pubDate>Fri, 23 Jan 2026 21:25:36 +0000</pubDate>
      <link>https://forem.com/chand1012/the-best-way-to-do-agentic-development-in-2026-14mn</link>
      <guid>https://forem.com/chand1012/the-best-way-to-do-agentic-development-in-2026-14mn</guid>
      <description>&lt;p&gt;TLDR; I tried Claude Code, switched to OpenCode + Oh-My-Code, then finally switched to Conductor + Claude Code + Lots of Plugins and Skills.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa5ke7ih1q23l9txwmhmo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa5ke7ih1q23l9txwmhmo.png" alt="Opinionated meme" width="500" height="701"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Claude Code is good
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://code.claude.com/docs/en/overview" rel="noopener noreferrer"&gt;Claude Code&lt;/a&gt; by itself is an amazing tool, hell my coworkers and colleagues use it constantly. I was always a little more hesitant, preferring Cursor in most cases because I wanted the freedom to edit some code myself while the AI agent was doing its thing, while also keeping close watch on the agent to make sure that the code it was producing worked well and was up to my standards (it usually was, if it passes my strict CI its probably fine).&lt;/p&gt;

&lt;p&gt;The problem I always had with Claude Code wasn't the lack of editing: for a while (and still quite often now) I would run Claude Code in my VSCode/Cursor terminal while editing other files. It was price to performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  It was &lt;em&gt;just okay&lt;/em&gt;.
&lt;/h3&gt;

&lt;p&gt;While it always seemed to &lt;em&gt;work&lt;/em&gt;, it never always &lt;em&gt;worked well&lt;/em&gt;, nor did it ever seem to ever seem to work ever on the first try.&lt;/p&gt;

&lt;p&gt;Some of this was remedied when moving from Sonnet 3.x to Sonnet 4 series, and even more when moving to the 4.5 series of models, but especially Opus 4.5. However it was never perfect.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenCode + Oh-My-OpenCode
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqgliwyh0cl4ir93n5ndx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqgliwyh0cl4ir93n5ndx.png" alt="Me a few weeks ago" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A friend of mine introduced me to &lt;a href="https://github.com/code-yeongyu/oh-my-opencode" rel="noopener noreferrer"&gt;Oh-My-OpenCode&lt;/a&gt; (and I've known about OpenCode but always preferred Claude Code) at the beginning of the year, and &lt;strong&gt;IT. IS. WONDERFUL!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Feels like an actual developer that lives on your machine. Its basically a plugin that significantly improves the performance of OpenCode with subagents, and an "ultrawork" mode that allows more efficient background tasks and subtasks to be delegated to other agents.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftd2k8ucji5konomr1ftn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftd2k8ucji5konomr1ftn.png" alt="Their example screenshot of it working" width="800" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Plus, unlike Claude Code, OpenCode supports many AI providers (the main two they talk about are Codex and Claude Code.&lt;/p&gt;

&lt;p&gt;Now that all seems amazing, what's the catch? &lt;strong&gt;Cost.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Anthropic is kinda mad.
&lt;/h3&gt;

&lt;p&gt;When I first started using Oh-My-OpenCode, one of its selling points is that it allowed you to use your &lt;a href="https://claude.com/pricing" rel="noopener noreferrer"&gt;Claude Code Pro or Max&lt;/a&gt; subscriptions to use OpenCode, which made it &lt;em&gt;significantly&lt;/em&gt; more cost effective. Since then, &lt;a href="https://github.com/code-yeongyu/oh-my-opencode?tab=readme-ov-file#claude-oauth-access-notice" rel="noopener noreferrer"&gt;Anthropic has blocked this&lt;/a&gt; as they claim this was outside their ToS.&lt;/p&gt;

&lt;p&gt;I knew this may become an issue, and I had tons of Anthropic grant credits that expired and were burning a hole in my pocket, so I opted to use API keys from the start. &lt;/p&gt;

&lt;p&gt;So what's my problem then? While OpenCode + Oh-My-OpenCode has impressive performance, there's a lot of dead time where nothing is happening. I'm just sitting there watching it code. Now I could do what I normally do and complete other non-coding tasks that are related to my work, or just procrastinate by doing non-work tasks in the background, but I'm a productivity nerd. I want to get as much done as possible in the least amount of time possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conductor - trains or music?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feut8avqcoc1v58efjj5p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feut8avqcoc1v58efjj5p.png" alt="Example from their website" width="800" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.conductor.build/" rel="noopener noreferrer"&gt;Conductor&lt;/a&gt; is a unique tool. Its currently a macOS-only (Windows and Linux coming soon) developer tool that uses Claude Code (or OpenAI Codex) to orchestrate many git worktrees of a repo to accomplish many tasks at the same time. It has &lt;em&gt;tight&lt;/em&gt; integration with Linear and GitHub (Linear is especially fitting since they're one of the larger companies using it), allowing you to inject Linear (and GitHub) issues as context, provide feedback as it developers the app, run multiple Claude Code instances in a single or across multiple worktrees, handoff plans to other agents, review code, and open GitHub Pull Requests right from within the app. I don't leave the app unless I need to request a review on my PR (I should ask them for that feature...).&lt;/p&gt;

&lt;p&gt;It also handles GitHub PRs amazing. One of your CI checks fail? No problem, click the "fix" button in the top right to automatically fix it. Merge conflicts? No problem, one click fix those too!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qlktjoanv1tdxjlxekn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qlktjoanv1tdxjlxekn.png" alt="Fix CI errors with a single click!" width="800" height="596"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now this alone wouldn't get me to move over from Oh-My-OpenCode since the code from Claude Code was worse, however there's one more piece to this agentic puzzle that made the switch worth it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Superpowers (and friends)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/obra/superpowers" rel="noopener noreferrer"&gt;Superpowers&lt;/a&gt; is a plugin for Claude Code that just seems to make it smarter, especially when running it in planning mode (which you absolutely should be doing). It asks you more intelligent questions as it goes, fleshing out implementation details to make its actual implementation better. It'll spawn subagents (just like Oh-My-OpenCode) for gathering context from all your files in your repo or other MCP servers. It can even use your testing suites to make sure its new code is passing linting, formatting, and other CI/CD. It accomplishes this by providing a number of skills (basically just fancy prompts injected into the system prompt with hyper specific instructions for tasks) which allow it to perform within spitting distance of Oh-My-OpenCode, while still being able to use your existing Claude Code Max subscription.&lt;/p&gt;

&lt;p&gt;The planning part of Superpowers is definitely the reason it performs so much better &lt;/p&gt;

&lt;h3&gt;
  
  
  Other Plugins
&lt;/h3&gt;

&lt;p&gt;I don't just use the superpowers plugin, I also have a few others that I consider essential to making Claude Code perform at its best. &lt;/p&gt;

&lt;p&gt;An example of this is the Context7 plugin. &lt;a href="https://context7.com/" rel="noopener noreferrer"&gt;Context7&lt;/a&gt; is a documentation provider that is specifically designed to allow AI agents find and read documentation. This allows Claude Code to search for the latest documentation and use APIs properly the first time, minimizing required iteration.&lt;/p&gt;

&lt;p&gt;Another plugin I use that isn't listed in the Anthropic plugins store is &lt;a href="https://docs.tavily.com/documentation/claude-code#npx-recommended" rel="noopener noreferrer"&gt;Tavily&lt;/a&gt;. I use this to give Claude Code improved web search capabilities and to integrate research abilities into the repository, which has been especially useful when trying to find information about documentation that isn't yet in Context7, or to do a research task before accomplishing a complex feature like trying to find out how this is usually implemented in other projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I get this set up?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Claude Code + Plugins
&lt;/h3&gt;

&lt;p&gt;First step is to &lt;a href="https://code.claude.com/docs/en/quickstart" rel="noopener noreferrer"&gt;install Claude Code&lt;/a&gt;. If you're on macOS or Linux, this can be done the official script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://claude.ai/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once that's done, you should log into Claude by running &lt;code&gt;claude&lt;/code&gt; in your terminal then running &lt;code&gt;/login&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can leave Claude for now. Now we need to install all the good plugins. I prefer use level install for most things so that its used across all my projects, which can be done from the command line. Let's start with the easy ones.&lt;/p&gt;

&lt;p&gt;You don't need to install all of these, but I am going to list all plugins I have installed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude plugin marketplace add obra/superpowers-marketplace
claude plugin &lt;span class="nb"&gt;install &lt;/span&gt;superpowers@superpowers-marketplace
claude plugin &lt;span class="nb"&gt;install &lt;/span&gt;context7@claude-plugins-official
claude plugin &lt;span class="nb"&gt;install &lt;/span&gt;playwright@claude-plugins-official
claude plugin &lt;span class="nb"&gt;install &lt;/span&gt;frontend-design@claude-plugins-official
claude plugin &lt;span class="nb"&gt;install &lt;/span&gt;feature-dev@claude-plugins-official
claude plugin &lt;span class="nb"&gt;install &lt;/span&gt;commit-commands@claude-plugins-official
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tavily MCP Server
&lt;/h3&gt;

&lt;p&gt;Unlike many MCP servers, you don't need to run this one locally. You start by making an account on &lt;a href="https://www.tavily.com/" rel="noopener noreferrer"&gt;Tavily&lt;/a&gt;, then by following their official skill instructions. Here's a TLDR if you don't want to use their docs.&lt;/p&gt;

&lt;p&gt;Open your Claude settings, which is at &lt;code&gt;~/.claude/settings.json&lt;/code&gt;, using your preferred text editor.&lt;/p&gt;

&lt;p&gt;Once that's done, add a new section called env. You'll add your Tavily API key, (which you need an account for) Should look something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"TAVILY_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tvly-YOUR_API_KEY"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;tvly-YOUR_API_KEY&lt;/code&gt; with your actual API key. Once that's done, go to your terminal and run the following command, following the instructions to install the skill.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add https://github.com/tavily-ai/skills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once that's done, you can call those commands you added from anywhere, or you can tell Claude to use Tavily to perform searches to research anything you want!&lt;/p&gt;

&lt;h3&gt;
  
  
  Conductor
&lt;/h3&gt;

&lt;p&gt;Now that we have Claude Code set up for maximal productivity, we need the program that ties it all together: &lt;a href="https://www.conductor.build/" rel="noopener noreferrer"&gt;Conductor&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Install it, create your account, then (ideally) link your GitHub and Linear accounts to your Conductor accounts. This will let you quickly add context via injecting issues.&lt;/p&gt;

&lt;p&gt;Once that's all done you're ready to rip with Conductor! Utilize the superpower skills, research topics, link Linear and GitHub issues, &lt;strong&gt;always&lt;/strong&gt; use Planning mode, and dump as much context as you can into it to make your issues work as best as possible! I highly recommend use of the &lt;code&gt;/research&lt;/code&gt; command or telling it about its new skills when prompting to make it especially intelligent when accomplishing tasks!&lt;/p&gt;

&lt;p&gt;The real power when using Conductor though is that its not just a pretty UI: its a force multiplier. Now you can open many projects, many repos, and work using git worktrees (parallel workspaces) to accomplish many issues quickly. I'll run parallel agents on many issues across multiple project by dumping as much context as possible. Since I've started at &lt;a href="https://www.saphira.ai/" rel="noopener noreferrer"&gt;a new company&lt;/a&gt; I've needed to gather lots of context very quickly from existing documents, and the fastest way to accomplish this (due to their extensive use of Google Drive) was to use &lt;a href="https://notebooklm.google/" rel="noopener noreferrer"&gt;NotebookLM&lt;/a&gt; to gather context on projects and information on clients and what they (both my colleagues and clients) would want. Since we also switched to Linear for Issue and Project management, I can dump additional context from there into Conductor, and build in parallel extremely fast.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbvdgd0xuyh5dhitk9yp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbvdgd0xuyh5dhitk9yp.png" alt="Many issues" width="441" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The only issue I've ran into is that when you run commands with Conductor, (&lt;code&gt;/commit&lt;/code&gt;, any slash commands) it tends to ignore any attached issues. The solution is to attach them anyways and tell it to use the Linear/GitHub Issue to complete your task, and when it can't find it it'll ask for you to attach it again. I then attach it again to the new message, and it finds it and uses it.&lt;/p&gt;

&lt;p&gt;Any questions? Leave a comment below!&lt;/p&gt;

</description>
      <category>software</category>
      <category>tooling</category>
      <category>coding</category>
      <category>development</category>
    </item>
    <item>
      <title>Using LLMs in 3 lines of Python</title>
      <dc:creator>Chandler</dc:creator>
      <pubDate>Mon, 30 Jun 2025 19:26:33 +0000</pubDate>
      <link>https://forem.com/timesurgelabs/using-llms-in-3-lines-of-python-gm1</link>
      <guid>https://forem.com/timesurgelabs/using-llms-in-3-lines-of-python-gm1</guid>
      <description>&lt;p&gt;When working with LLMs, the first thing people generally install is the &lt;code&gt;openai&lt;/code&gt; or &lt;code&gt;anthropic&lt;/code&gt; packages, if you’re a little more adventurous with your LLM choice it may be &lt;code&gt;litellm&lt;/code&gt; or &lt;code&gt;ollama&lt;/code&gt;. The issue is that all of these require a bit of code to get your started. For example, assuming you have an API key in your environment like I do, you’ll need at least this code to make an LLM call with OpenAI (also assuming you’re using the older Chat Completions endpoint).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="c1"&gt;# retrieve API key from environment
&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# initialize client
&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# send a chat request
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o-mini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a helpful assistant.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Say something concise.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# print assistant's answer
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if you want to wrap your API call with a function so you can call it repeatedly, that’s even more lines!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;chat_with_openai&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a helpful assistant.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;chat_with_openai&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Say something concise.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that is simply unacceptable!&lt;/p&gt;

&lt;h2&gt;
  
  
  Do you really care?
&lt;/h2&gt;

&lt;p&gt;No, I’m being facetious. For most LLM projects, consistency of output trumps anything else, however sometimes its nice to have a super simple way to add LLMs to my one-off python scripts and tools without all the boilerplate. &lt;/p&gt;

&lt;h2&gt;
  
  
  Magentic
&lt;/h2&gt;

&lt;p&gt;Magentic is a Python package that lets you create functions that call LLMs in 3 lines of code. No, really! Here’s an example ripped straight from &lt;a href="https://magentic.dev/#usage" rel="noopener noreferrer"&gt;their docs&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;magentic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;

&lt;span class="nd"&gt;@prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Add more &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dude&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ness to: {phrase}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dudeify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;  &lt;span class="c1"&gt;# No function body as this is never executed
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks to some black box dark magic that I don’t feel like learning about, this is a completely valid Python function that’s callable anywhere in the script, assuming you have an OpenAI API Key in your environment variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;dudeify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, how are you?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;# "Hey, dude! What's up? How's it going, my man?"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A Note On Package Management
&lt;/h2&gt;

&lt;p&gt;I’m going to be using the &lt;a href="https://peps.python.org/pep-0723/" rel="noopener noreferrer"&gt;PEP 723&lt;/a&gt; standard at the top of all my scripts for the rest of this post. This allows you to use &lt;a href="https://docs.astral.sh/uv/" rel="noopener noreferrer"&gt;uv&lt;/a&gt;, the best package manager for Python, to run the scripts without you having to make a virtual environment, then install packages, then run the script. This automates all three of those tasks into a single command. Here’s an example.&lt;/p&gt;

&lt;p&gt;Here’s the above script with the added metadata and some slight modifications. This assumes you have &lt;a href="https://docs.astral.sh/uv/#installation" rel="noopener noreferrer"&gt;uv installed&lt;/a&gt; and the &lt;code&gt;OPENAI_API_KEY&lt;/code&gt; env var set.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env -S uv run --script
# /// script
# requires-python = "&amp;gt;=3.10"
# dependencies = [
#     "fire",
#     "magentic"
# ]
# ///
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;fire&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;magentic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;

&lt;span class="nd"&gt;@prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Add more &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dude&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ness to: {phrase}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dudeify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;  &lt;span class="c1"&gt;# No function body as this is never executed
&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fire&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Fire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dudeify&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script can now be downloaded and ran like an executable. I’ve uploaded to &lt;a href="https://gist.github.com/chand1012/218372f3e1101dfa7f915dc35c0e66d8" rel="noopener noreferrer"&gt;a gist&lt;/a&gt; for easy download.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget &lt;span class="nt"&gt;-O&lt;/span&gt; dudeify https://gist.githubusercontent.com/chand1012/218372f3e1101dfa7f915dc35c0e66d8/raw/363f720d21fa8ebe2e6a484f6b389496c3452064/dudeify.py
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x dudeify
./dudeify &lt;span class="s2"&gt;"Hello how are you"&lt;/span&gt;
&lt;span class="c"&gt;# Installed 23 packages in 45ms&lt;/span&gt;
&lt;span class="c"&gt;# Yo dude, how's it hangin'?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first time you run the script it’ll handle making a cached virtual environment for the next time you run it! For more information on how this works, you can check out the &lt;a href="https://docs.astral.sh/uv/guides/scripts/#using-a-shebang-to-create-an-executable-file" rel="noopener noreferrer"&gt;uv docs&lt;/a&gt;, and the &lt;a href="https://www.cottongeeks.com/articles/2025-06-24-fun-with-uv-and-pep-723" rel="noopener noreferrer"&gt;blog post&lt;/a&gt; that inspired my constant use of this feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structured Outputs
&lt;/h2&gt;

&lt;p&gt;If you want to have structured outputs, like for example for an API response or just to make it easier to parse and use the data with your scripts, you can use a &lt;a href="https://docs.pydantic.dev/latest/concepts/dataclasses/" rel="noopener noreferrer"&gt;Pydantic Dataclass&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env -S uv run --script
# /// script
# requires-python = "&amp;gt;=3.10"
# dependencies = [
#     "fire",
#     "magentic",
#     "pydantic",
# ]
# ///
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fire&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Fire&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;magentic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;species&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;legs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;latin_species&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;predators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;prey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nd"&gt;@prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Give me information on the animal {animal_name}.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;animal_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;animal_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nc"&gt;Fire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;animal_info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s an example of that method being ran.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb6fsnfs8f52p75cm1mtg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb6fsnfs8f52p75cm1mtg.png" alt="Example output" width="800" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prompting and Function Calls
&lt;/h2&gt;

&lt;p&gt;There’s two ways you can prompt the LLM with Magentic. You can either use the &lt;code&gt;@prompt&lt;/code&gt; decorator, as I’ve been using, which is the simplest and fastest way to create LLM methods. There’s also &lt;code&gt;@chatprompt&lt;/code&gt;, which allows you to pass a list of chat messages to the LLM. This is especially useful for few-shot prompting, where you give the LLM some examples of what output you want. After all, LLMs &lt;em&gt;are&lt;/em&gt; just fancy pattern matching black boxes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env -S uv run --script
# /// script
# requires-python = "&amp;gt;=3.10"
# dependencies = [
#     "fire",
#     "magentic",
#     "pydantic",
# ]
# ///
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fire&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Fire&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;magentic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;chatprompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AssistantMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SystemMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UserMessage&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;

&lt;span class="c1"&gt;# this is a modified version of magentic's example chatprompt code
# https://magentic.dev/#chatprompt
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Quote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;character&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

&lt;span class="nd"&gt;@chatprompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;SystemMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a movie buff.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;UserMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What is your favorite quote from Harry Potter?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;AssistantMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;Quote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;It does not do to dwell on dreams and forget to live.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;character&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Albus Dumbledore&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;UserMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What is your favorite quote from {movie}?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_movie_quote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Quote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nc"&gt;Fire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_movie_quote&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also pass &lt;a href="https://magentic.dev/#functioncall" rel="noopener noreferrer"&gt;function calls to LLMs&lt;/a&gt; to allow them to return a python callable that you can call later. Another use of this is the decorator &lt;code&gt;@prompt_chain&lt;/code&gt; which allows you to have an LLM call a function and use the returned results to generate its response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env -S uv run --script
# /// script
# requires-python = "&amp;gt;=3.10"
# dependencies = [
#     "fire",
#     "magentic",
#     "duckduckgo_search",
# ]
# ///
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fire&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Fire&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;magentic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;prompt_chain&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;duckduckgo_search&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DDGS&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;web_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Searches the web for a given query&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;DDGS&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ddgs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ddgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_results&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;

&lt;span class="nd"&gt;@prompt_chain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a helpful assistant that can search the web for information. Use your tools to answer the user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s question: {query}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;functions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;web_search&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nc"&gt;Fire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using Other LLMs
&lt;/h2&gt;

&lt;p&gt;If you’re a data conscious person, or just want your options to be open, Magentic can be configured to work with nearly all other LLMs as long as they are supported by &lt;a href="https://github.com/BerriAI/litellm" rel="noopener noreferrer"&gt;LiteLLM&lt;/a&gt; or offer an OpenAI compatible API. Here’s an example of a script that runs entirely locally using &lt;a href="https://ollama.com/" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; and &lt;a href="https://ollama.com/library/gemma3" rel="noopener noreferrer"&gt;Google’s Gemma 3&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env -S uv run --script
# /// script
# requires-python = "&amp;gt;=3.10"
# dependencies = [
#     "fire",
#     "magentic"
# ]
# ///
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;fire&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;magentic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OpenaiChatModel&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenaiChatModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemma3:27b-it-qat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:11434/v1/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Add more &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dude&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ness to: {phrase}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dudeify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;  &lt;span class="c1"&gt;# No function body as this is never executed
&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fire&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Fire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dudeify&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your chosen LLM is one of the &lt;a href="https://docs.litellm.ai/docs/providers" rel="noopener noreferrer"&gt;many supported by LiteLLM&lt;/a&gt;, you can use the LiteLLM extra feature of Magentic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env -S uv run --script
# /// script
# requires-python = "&amp;gt;=3.10"
# dependencies = [
#     "fire",
#     "magentic[litellm]"
# ]
# ///
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;fire&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;magentic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;magentic.chat_model.litellm_chat_model&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LitellmChatModel&lt;/span&gt;

&lt;span class="c1"&gt;# this specific example requires GEMINI_API_KEY env var to be set
&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LitellmChatModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini/gemini-2.0-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Add more &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dude&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ness to: {phrase}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dudeify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;  &lt;span class="c1"&gt;# No function body as this is never executed
&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fire&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Fire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dudeify&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use the LiteLLM method to use Anthropic’s Claude series of models, or you can use Magentic’s official Anthropic extension.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env -S uv run --script
# /// script
# requires-python = "&amp;gt;=3.10"
# dependencies = [
#     "fire",
#     "magentic[anthropic]"
# ]
# ///
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;fire&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;magentic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;magentic.chat_model.anthropic_chat_model&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AnthropicChatModel&lt;/span&gt;

&lt;span class="c1"&gt;# this specific example requires GEMINI_API_KEY env var to be set
&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AnthropicChatModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-4-sonnet-latest&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Add more &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dude&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ness to: {phrase}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dudeify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;  &lt;span class="c1"&gt;# No function body as this is never executed
&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fire&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Fire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dudeify&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No LLM left behind!&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Usage
&lt;/h2&gt;

&lt;p&gt;Need an async function? Just prefix with &lt;code&gt;async def&lt;/code&gt; instead of &lt;code&gt;def&lt;/code&gt; !&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# incomplete snippet
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;magentic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;

&lt;span class="nd"&gt;@prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tell me more about {topic}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;tell_me_more_about&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use Python’s &lt;code&gt;AsyncIterable&lt;/code&gt; to make multiple simultaneous calls to the LLM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# incomplete snippet
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AsyncIterable&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;magentic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;

&lt;span class="nd"&gt;@prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;List ten presidents of the United States&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;iter_presidents&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AsyncIterable&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;

&lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;president&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;iter_presidents&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# Use asyncio.create_task to schedule the coroutine for execution before awaiting it
&lt;/span&gt;    &lt;span class="c1"&gt;# This way descriptions will start being generated while the list of presidents is still being generated
&lt;/span&gt;    &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;tell_me_more_about&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;president&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;descriptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Need to stream the response back to the user? Use Magentic’s &lt;code&gt;StreamedStr&lt;/code&gt; to loop through the response chunks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env -S uv run --script
# /// script
# requires-python = "&amp;gt;=3.10"
# dependencies = [
#     "fire",
#     "magentic"
# ]
# ///
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;fire&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;magentic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StreamedStr&lt;/span&gt;

&lt;span class="nd"&gt;@prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tell me about {country}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;describe_country&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;StreamedStr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;describe_country&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fire&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Fire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This also works for multiple objects, simply wrap your objects in the &lt;code&gt;Iterable&lt;/code&gt; class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env -S uv run --script
# /// script
# requires-python = "&amp;gt;=3.10"
# dependencies = [
#     "fire",
#     "magentic",
#     "pydantic",
# ]
# ///
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections.abc&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Iterable&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fire&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Fire&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;magentic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;species&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;legs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;latin_species&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;predators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;prey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nd"&gt;@prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Give me information on the animals in the family {family}.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;animal_family_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Iterable&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;animal&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;animal_family_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;family&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nc"&gt;Fire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Working with LLMs is now easier than ever, and Magnetic makes it even easier than the standard methods to quick add LLMs to any Python script, regardless of the scale of complexity. Using this in tandem with something like uv and the new scripting metadata allows you to quickly make command line tools that can utilize AI quickly and effectively. I won’t always use Magentic for every project I need an LLM for, but I’ll definitely use it all the time with my small one-offs and utilities.&lt;/p&gt;

</description>
      <category>python</category>
      <category>ai</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Agentic Coding (Vibe Coding) Best Practices</title>
      <dc:creator>Chandler</dc:creator>
      <pubDate>Fri, 28 Mar 2025 21:49:53 +0000</pubDate>
      <link>https://forem.com/timesurgelabs/agentic-coding-vibe-coding-best-practices-b4b</link>
      <guid>https://forem.com/timesurgelabs/agentic-coding-vibe-coding-best-practices-b4b</guid>
      <description>&lt;h2&gt;
  
  
  TLDR
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwolb0rz23myp0eub2led.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwolb0rz23myp0eub2led.png" alt="Comic" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've been living under a rock, you may not be aware of the "vibe coding" phenomenon.&lt;br&gt;
If you want a good explanation of what "vibe coding", or to use a more technical term, Agentic Coding, is, check out &lt;a href="https://youtu.be/Tw18-4U7mts?si=wmgKylbi-gEEmXzU" rel="noopener noreferrer"&gt;Fireship's video&lt;/a&gt; on the subject. He does a great job of explaining the concept in a way that's both easy to understand and objective about the pros and cons.&lt;/p&gt;
&lt;h2&gt;
  
  
  Tooling
&lt;/h2&gt;

&lt;p&gt;If you're going to ignore all the cons and go ahead with agentic coding, there are some best practices I use to make sure my code doesn't turn into a complete mess of AI generated garbage. I personally use Cursor, so this guide is going to use their &lt;a href="https://docs.cursor.com/context/rules-for-ai" rel="noopener noreferrer"&gt;Rules feature&lt;/a&gt; to organize and apply rules to the LLM for code generation.&lt;/p&gt;
&lt;h2&gt;
  
  
  Rules
&lt;/h2&gt;

&lt;p&gt;Cursor has a concept of a rule file. This file is a markdown file found in the &lt;code&gt;.cursor/rules&lt;/code&gt; directory with some extra front matter that specifies when and how the rule is applied to the LLM, and ending in &lt;code&gt;.mdc&lt;/code&gt; rather than &lt;code&gt;.md&lt;/code&gt;. These can be broken down into 4 categories.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Language Rules

&lt;ul&gt;
&lt;li&gt;Applies to specific languages.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Framework Rules

&lt;ul&gt;
&lt;li&gt;Applies to specific frameworks.&lt;/li&gt;
&lt;li&gt;Can also apply to libraries that have special rules, like shadcn/ui.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Practice Rules

&lt;ul&gt;
&lt;li&gt;For coding practice guidelines.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Project Rules

&lt;ul&gt;
&lt;li&gt;Should be used to describe project specific guidelines like file structure, dependencies used, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rules can be applied with 4 different methods.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Always Apply&lt;/li&gt;
&lt;li&gt;Auto Apply

&lt;ul&gt;
&lt;li&gt;Uses a glob pattern to apply the rule to all files that match the pattern.&lt;/li&gt;
&lt;li&gt;Especially useful for language and framework rules where specific file extensions are used.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Agent Requested

&lt;ul&gt;
&lt;li&gt;Uses a description of the rule to allow the agent to decide when to apply the rule.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Manual Apply

&lt;ul&gt;
&lt;li&gt;Only applied when you directly ask the agent to apply the rule.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rules can also have other files from within your project linked to them and will also be loaded into context. This is especially useful for the project rules where you can link the README as well as any other documentation that the LLM should know about, like an Architecture or Contributing Guide.&lt;/p&gt;
&lt;h2&gt;
  
  
  Writing Rules
&lt;/h2&gt;

&lt;p&gt;The actual contents of the rules are written in markdown, and should be concise and clear guidelines for the LLM rules. They should be written to be both human and LLM readable, and should include very minimal code and command examples. Here's some examples of rules from my &lt;a href="https://github.com/chand1012/cursorrules" rel="noopener noreferrer"&gt;personal collection&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Example Rules
&lt;/h2&gt;

&lt;p&gt;Here's an example I made for best practices when using Go.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Go&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;coding&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;standards&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;best&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;practices&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;modern&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;development"&lt;/span&gt;
&lt;span class="na"&gt;globs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="err"&gt;**&lt;/span&gt;&lt;span class="s"&gt;/*.go&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Go Best Practices&lt;/span&gt;

&lt;span class="gu"&gt;## Package and Import Statements&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Use meaningful package names that reflect their purpose (e.g., &lt;span class="sb"&gt;`auth`&lt;/span&gt;, &lt;span class="sb"&gt;`config`&lt;/span&gt;).
&lt;span class="p"&gt;-&lt;/span&gt; Group imports in this order: standard library, third-party, then local packages, separated by blank lines.
&lt;span class="p"&gt;-&lt;/span&gt; Avoid import cycles to maintain clean dependency graphs.

&lt;span class="gu"&gt;## Type System&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Use &lt;span class="sb"&gt;`struct`&lt;/span&gt; types to define complex data structures.
&lt;span class="p"&gt;-&lt;/span&gt; Define &lt;span class="sb"&gt;`interface`&lt;/span&gt; types to specify behavior and enable polymorphism.
&lt;span class="p"&gt;-&lt;/span&gt; Use type aliases sparingly for clarity (e.g., &lt;span class="sb"&gt;`type ID string`&lt;/span&gt;).
&lt;span class="p"&gt;-&lt;/span&gt; Leverage Go’s built-in types (e.g., &lt;span class="sb"&gt;`map`&lt;/span&gt;, &lt;span class="sb"&gt;`slice`&lt;/span&gt;) and composite types effectively.
&lt;span class="p"&gt;-&lt;/span&gt; Avoid unnecessary type conversions to maintain type safety.
&lt;span class="p"&gt;-&lt;/span&gt; Use struct embedding for composition instead of inheritance.

&lt;span class="gu"&gt;## Naming Conventions&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Use &lt;span class="sb"&gt;`camelCase`&lt;/span&gt; for variable and function names (e.g., &lt;span class="sb"&gt;`getUser`&lt;/span&gt;).
&lt;span class="p"&gt;-&lt;/span&gt; Use &lt;span class="sb"&gt;`PascalCase`&lt;/span&gt; for type names and exported identifiers (e.g., &lt;span class="sb"&gt;`UserService`&lt;/span&gt;).
&lt;span class="p"&gt;-&lt;/span&gt; Use &lt;span class="sb"&gt;`ALL_CAPS`&lt;/span&gt; for constants (e.g., &lt;span class="sb"&gt;`MAX_RETRIES`&lt;/span&gt;).
&lt;span class="p"&gt;-&lt;/span&gt; Be descriptive yet concise in naming (e.g., &lt;span class="sb"&gt;`userCount`&lt;/span&gt; over &lt;span class="sb"&gt;`cnt`&lt;/span&gt;).

&lt;span class="gu"&gt;## Code Organization&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Follow the standard Go project layout (e.g., &lt;span class="sb"&gt;`cmd/`&lt;/span&gt;, &lt;span class="sb"&gt;`pkg/`&lt;/span&gt;, &lt;span class="sb"&gt;`internal/`&lt;/span&gt;).
&lt;span class="p"&gt;-&lt;/span&gt; Keep related code within the same package for cohesion.
&lt;span class="p"&gt;-&lt;/span&gt; Use subdirectories for larger packages to organize functionality (e.g., &lt;span class="sb"&gt;`api/handlers`&lt;/span&gt;).

&lt;span class="gu"&gt;## Functions and Methods&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Keep functions short and focused on a single responsibility.
&lt;span class="p"&gt;-&lt;/span&gt; Use named return values for clarity in complex functions (e.g., &lt;span class="sb"&gt;`func getData() (data string, err error)`&lt;/span&gt;).
&lt;span class="p"&gt;-&lt;/span&gt; Avoid side effects in functions to improve predictability.

&lt;span class="gu"&gt;## Best Practices&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Follow the Go proverb: "A little copying is better than a little dependency."
&lt;span class="p"&gt;-&lt;/span&gt; Use interfaces to define behavior and decouple components.
&lt;span class="p"&gt;-&lt;/span&gt; Prefer composition over inheritance using embedding.
&lt;span class="p"&gt;-&lt;/span&gt; Avoid unnecessary abstractions; prioritize simplicity.
&lt;span class="p"&gt;-&lt;/span&gt; Use the &lt;span class="sb"&gt;`init`&lt;/span&gt; function sparingly for package initialization.
&lt;span class="p"&gt;-&lt;/span&gt; Avoid global variables; if unavoidable, ensure they are thread-safe (e.g., with &lt;span class="sb"&gt;`sync.Mutex`&lt;/span&gt;).
&lt;span class="p"&gt;-&lt;/span&gt; Be mindful of memory allocations; use profiling tools (e.g., &lt;span class="sb"&gt;`pprof`&lt;/span&gt;) to optimize performance.
&lt;span class="p"&gt;-&lt;/span&gt; Use &lt;span class="sb"&gt;`gofmt`&lt;/span&gt; for consistent formatting and &lt;span class="sb"&gt;`go vet`&lt;/span&gt; for static analysis.

&lt;span class="gu"&gt;## Error Handling&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Always check errors explicitly (e.g., &lt;span class="sb"&gt;`if err != nil`&lt;/span&gt;).
&lt;span class="p"&gt;-&lt;/span&gt; Use descriptive error messages for debugging (e.g., &lt;span class="sb"&gt;`errors.New("failed to open file")`&lt;/span&gt;).
&lt;span class="p"&gt;-&lt;/span&gt; Consider error wrapping with &lt;span class="sb"&gt;`fmt.Errorf`&lt;/span&gt; and &lt;span class="sb"&gt;`%w`&lt;/span&gt; for context (e.g., &lt;span class="sb"&gt;`fmt.Errorf("query failed: %w", err)`&lt;/span&gt;).
&lt;span class="p"&gt;-&lt;/span&gt; Use &lt;span class="sb"&gt;`defer`&lt;/span&gt; with &lt;span class="sb"&gt;`recover`&lt;/span&gt; to handle panics in critical sections (e.g., HTTP handlers).

&lt;span class="gu"&gt;## Concurrency&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Use goroutines for concurrent tasks (e.g., &lt;span class="sb"&gt;`go processData()`&lt;/span&gt;).
&lt;span class="p"&gt;-&lt;/span&gt; Use channels for safe communication between goroutines (e.g., &lt;span class="sb"&gt;`ch := make(chan int)`&lt;/span&gt;).
&lt;span class="p"&gt;-&lt;/span&gt; Avoid shared state when possible; prefer message passing via channels.

&lt;span class="gu"&gt;## Testing&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Write tests for all public functions using the &lt;span class="sb"&gt;`testing`&lt;/span&gt; package.
&lt;span class="p"&gt;-&lt;/span&gt; Use table-driven tests for multiple test cases (e.g., &lt;span class="sb"&gt;`tests := []struct{...}`&lt;/span&gt;).
&lt;span class="p"&gt;-&lt;/span&gt; Aim for high test coverage with &lt;span class="sb"&gt;`go test -cover`&lt;/span&gt;.

&lt;span class="gu"&gt;## Documentation&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Write doc comments for all exported identifiers (e.g., &lt;span class="sb"&gt;`// UserService handles user operations`&lt;/span&gt;).
&lt;span class="p"&gt;-&lt;/span&gt; Follow the standard Go doc format, starting with the identifier name (e.g., &lt;span class="sb"&gt;`// Package auth provides...`&lt;/span&gt;).
&lt;span class="p"&gt;-&lt;/span&gt; Include examples in doc comments when possible (e.g., &lt;span class="sb"&gt;`// Example: ...`&lt;/span&gt;).

&lt;span class="gu"&gt;## Patterns&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Use interfaces for dependency injection to improve testability.
&lt;span class="p"&gt;-&lt;/span&gt; Implement the Repository pattern for data access (e.g., &lt;span class="sb"&gt;`UserRepository`&lt;/span&gt; interface).
&lt;span class="p"&gt;-&lt;/span&gt; Use the Factory pattern for object creation (e.g., &lt;span class="sb"&gt;`NewUserService()`&lt;/span&gt;).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows the LLM to properly structure Go code, and its output is great! &lt;a href="https://gist.github.com/chand1012/05bbe89f2d41c2cc335f684f7281a2fa" rel="noopener noreferrer"&gt;Here&lt;/a&gt; is some code generated using the rule.&lt;/p&gt;

&lt;p&gt;Here's another example of a project-level rule that I use for a Supabase backend project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
&lt;span class="na"&gt;globs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
&lt;span class="na"&gt;alwaysApply&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="gh"&gt;# Lancer DB&lt;/span&gt;

This is our monorepo for our Supabase Database migrations as well as our Supabase Edge Functions written in Deno.

&lt;span class="gu"&gt;## Directory Structure&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; docs/: Markdown documentation relevant to the repo and development.
&lt;span class="p"&gt;-&lt;/span&gt; supabase/: Contains all the Supabase related configurations, migrations, and edge functions.
&lt;span class="p"&gt;  -&lt;/span&gt; supabase/migrations/: Contains the migrations. All migrations names should be formatted like so: &lt;span class="sb"&gt;`20240821194157_subnets.sql`&lt;/span&gt;. That is a raw date with no spaces or formatting + &lt;span class="sb"&gt;`_`&lt;/span&gt; + followed by a snake case description of the migration.
&lt;span class="p"&gt;  -&lt;/span&gt; supabase/functions/: Contains Deno edge functions.
&lt;span class="p"&gt;    -&lt;/span&gt; supabase/functions/&lt;span class="ge"&gt;**&lt;/span&gt;/index.ts: Each of the main entrypoints for each edge function. Edge functions have folders which are their name, and any related files that the edge function uses that are not shared between functions should be included in the same directory as &lt;span class="sb"&gt;`index.ts`&lt;/span&gt;.
&lt;span class="p"&gt;    -&lt;/span&gt; supabase/functions/_shared/: Directory of all shared code that gets reused between multiple functions.
&lt;span class="p"&gt;  -&lt;/span&gt; supabase/seed.sql: Seed data for local development and testing only. If dummy data is needed for local testing, it should be added here.
&lt;span class="p"&gt;  -&lt;/span&gt; supabase/config.toml: Configuration data for the local Supabase instance for local dev and testing.
&lt;span class="p"&gt;-&lt;/span&gt; scripts/: Deno scripts for development and testing.
&lt;span class="p"&gt;-&lt;/span&gt; Justfile: Command runner script. Holds commands and bash scripts we use frequently as we work on the project. Automatically loads a &lt;span class="sb"&gt;`.env`&lt;/span&gt; if present. Commands can be run with &lt;span class="sb"&gt;`just &amp;lt;command name&amp;gt;`&lt;/span&gt;

&lt;span class="gu"&gt;## Code Style&lt;/span&gt;

&lt;span class="gu"&gt;### General Guidelines&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Follow DRY (DO NOT REPEAT YOURSELF)
&lt;span class="p"&gt;-&lt;/span&gt; Code should be well-named while following the case practices defined below for the language.
&lt;span class="p"&gt;-&lt;/span&gt; Code should be readable by human devs as well as LLMs alike.
&lt;span class="p"&gt;-&lt;/span&gt; Use meaningful variable and function names.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This basically just tells the LLM to follow the project's overall coding standards and file structure. In other repos, I've also linked other documentation that the LLM should know about via an &lt;code&gt;@&lt;/code&gt; symbol.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Rules
&lt;/h2&gt;

&lt;p&gt;Create a new file in the &lt;code&gt;.cursor/rules&lt;/code&gt; directory followed by &lt;code&gt;.mdc&lt;/code&gt; as the extension.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; .cursor/rules
&lt;span class="nb"&gt;touch&lt;/span&gt; .cursor/rules/go.mdc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cursor will by default open the rule file using a special editor that allows you to set the rule type and globs without having to manually edit the front matter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjaub6s8lir0yee1s2p9e.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjaub6s8lir0yee1s2p9e.gif" alt="Cursor Rule Editor" width="720" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For manual and always apply rules, you can simply write the rule contents and save the file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw04eaprjibls6fa3j40m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw04eaprjibls6fa3j40m.png" alt=" " width="580" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For auto apply rules, you can use a glob pattern to apply the rule to all files that match the pattern.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4btn9dtbfk9ei6067av1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4btn9dtbfk9ei6067av1.png" alt=" " width="561" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For agent requested rules, you should write a good description of the rule and the conditions that should trigger the rule.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4c8440xkv1rkyeg7bdo3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4c8440xkv1rkyeg7bdo3.png" alt=" " width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once that's done your rules are finished and will be loaded into context when you open Cursor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Documentation
&lt;/h2&gt;

&lt;p&gt;Sometimes you'll need to link both internal and external documentation to the LLM. For internal documentation, such as a project's README, you can use the &lt;code&gt;@&lt;/code&gt; which will bring up a menu of files you can select from. You can start typing the name of the file you want to link to and it will filter down the list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwqkokhrslezk9r3h4sas.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwqkokhrslezk9r3h4sas.gif" alt=" " width="560" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For external documentation, you should link it via a markdown link.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjuqc1eqm2ch3aragavwh.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjuqc1eqm2ch3aragavwh.gif" alt=" " width="562" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I've been using these rules for a while now and they've helped me write better code. I've also found that the LLM is able to follow the rules more often than not, and when it doesn't, it's usually because I need to update the rule to be more specific.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Command Line Power-Ups: Boost Your Workflow with Mods and Freeze</title>
      <dc:creator>Chandler</dc:creator>
      <pubDate>Thu, 27 Jun 2024 23:05:53 +0000</pubDate>
      <link>https://forem.com/timesurgelabs/command-line-power-ups-boost-your-workflow-with-mods-and-freeze-407j</link>
      <guid>https://forem.com/timesurgelabs/command-line-power-ups-boost-your-workflow-with-mods-and-freeze-407j</guid>
      <description>&lt;p&gt;For developers and tech enthusiasts, the command line is a powerful tool. But did you know there are ways to make it even more efficient and visually appealing? Two of my favorite tools I’ve been using lately are &lt;strong&gt;Mods&lt;/strong&gt; and &lt;strong&gt;Freeze&lt;/strong&gt;. These tools, brought to you by the innovative team at Charm Bracelet (charm.sh), will revolutionize how you interact with your terminal, automating tasks and creating beautiful code snippets. &lt;/p&gt;

&lt;h3&gt;
  
  
  Mods
&lt;/h3&gt;

&lt;p&gt;Imagine having the capabilities of ChatGPT directly in your command line. That's the power of Mods. This AI-driven tool excels at scripting and automation, allowing you to generate code snippets and streamline repetitive tasks with ease.&lt;/p&gt;

&lt;p&gt;Let's say you need a basic Python script to print "Hello World" with user input. With Mods, it's as simple as typing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mods -f "Generate a python hello world app with user input. Only output the code and no other text" -r &amp;gt; test.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command instructs Mods to generate the code, output it in raw format (without Markdown), and save it to a file named &lt;code&gt;test.py&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;Mods is still under development, so you might need to make minor adjustments to the output format. However, its ability to understand natural language commands and generate code is truly impressive. Plus, Mods remembers your conversation history, allowing you to reference previous commands and build upon your work seamlessly. &lt;/p&gt;

&lt;h3&gt;
  
  
  Freeze
&lt;/h3&gt;

&lt;p&gt;Sharing code snippets for documentation, presentations, or blog posts can be cumbersome. Freeze comes to the rescue, enabling you to generate visually stunning code screenshots with just a single command.&lt;/p&gt;

&lt;p&gt;To create a beautiful image of your Python script (&lt;code&gt;test.py&lt;/code&gt;), simply type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;freeze test.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will generate a PNG image file showcasing your code with elegant syntax highlighting. Freeze also offers a range of customization options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;--window&lt;/code&gt;&lt;/strong&gt;: Adds macOS-style window controls for a realistic look. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;--theme&lt;/code&gt;&lt;/strong&gt;: Allows you to apply various themes like the popular GitHub dark mode.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;--execute&lt;/code&gt;&lt;/strong&gt;: Captures the output of terminal commands within the screenshot. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With Freeze, you can effortlessly create professional-looking code visuals, enhancing your projects and communication.&lt;/p&gt;

&lt;p&gt;Mods and Freeze offer developers and tech enthusiasts powerful tools to enhance their productivity and creativity. Whether you're automating tasks, generating scripts, or creating eye-catching code visuals, these tools will streamline your workflow and elevate your projects. Explore these and other innovative command line tools to unlock the full potential of your terminal!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mods:&lt;/strong&gt; &lt;a href="https://github.com/charmbracelet/mods" rel="noopener noreferrer"&gt;https://github.com/charmbracelet/mods&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Freeze:&lt;/strong&gt; &lt;a href="https://github.com/charmbracelet/freeze" rel="noopener noreferrer"&gt;https://github.com/charmbracelet/freeze&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What are your favorite command line tools? Share them in the comments below!&lt;/strong&gt; &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Video Tutorial - How To Run Llama 3 locally with Ollama and OpenWebUI!</title>
      <dc:creator>Chandler</dc:creator>
      <pubDate>Thu, 16 May 2024 16:52:07 +0000</pubDate>
      <link>https://forem.com/timesurgelabs/video-tutorial-how-to-run-llama-3-locally-with-ollama-and-openwebui-1dn1</link>
      <guid>https://forem.com/timesurgelabs/video-tutorial-how-to-run-llama-3-locally-with-ollama-and-openwebui-1dn1</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/GT-Fwg124-I"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Learn how to run LLaMA 3 locally on your computer using Ollama and Open WebUI! In this tutorial, we'll take you through a step-by-step guide on how to install and set up Ollama, and demonstrate the power of LLaMA 3 in action. Whether you're a developer, AI enthusiast, or just curious about the possibilities of local AI, this video is for you. So sit back, relax, and let's dive into the world of LLaMA 3, Ollama, and OpenWeb UI!&lt;/p&gt;

&lt;h3&gt;
  
  
  Links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Recommended &lt;a href="https://youtu.be/eGz9DS-aIeY?feature=shared" rel="noopener noreferrer"&gt;Docker Tutorial&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ollama.com" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.openwebui.com" rel="noopener noreferrer"&gt;Open WebUI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://openwebui.com" rel="noopener noreferrer"&gt;Open WebUI Repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Follow TimeSurge Labs!
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/TimeSurgeLabs" rel="noopener noreferrer"&gt;Twitter/X&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/company/timesurge-labs" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/timesurgelabs"&gt;Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  AI Disclosure
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Thumbnail Background by &lt;a href="https://openai.com/index/dall-e-3/" rel="noopener noreferrer"&gt;OpenAI Dalle 3&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Title and Description partially AI generated by Llama 3 on &lt;a href="https://console.groq.com/" rel="noopener noreferrer"&gt;GroqCloud&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;All music generated by &lt;a href="https://suno.com" rel="noopener noreferrer"&gt;Suno&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Video filmed and edited by &lt;a href="https://twitter.com/Chand1012Dev" rel="noopener noreferrer"&gt;Chandler&lt;/a&gt; (NOT AI).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Music Links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://suno.com/song/73419c49-e237-47eb-8b11-c644e0384e8c" rel="noopener noreferrer"&gt;Putting In The Hours&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://suno.com/song/4fd4615d-43e1-45e8-bb7a-32cb10848cab" rel="noopener noreferrer"&gt;The Chase Scene&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://suno.com/song/e213b6a8-6785-409d-a869-cdd60f66d72e" rel="noopener noreferrer"&gt;TimeSurge Labs Outro&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>ai</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I Said Goodbye to ChatGPT and Hello to Llama 3 on Open WebUI - You Should Too</title>
      <dc:creator>Chandler</dc:creator>
      <pubDate>Wed, 24 Apr 2024 18:29:03 +0000</pubDate>
      <link>https://forem.com/timesurgelabs/i-said-goodbye-to-chatgpt-and-hello-to-llama-3-on-open-webui-you-should-too-4g6k</link>
      <guid>https://forem.com/timesurgelabs/i-said-goodbye-to-chatgpt-and-hello-to-llama-3-on-open-webui-you-should-too-4g6k</guid>
      <description>&lt;p&gt;I’m a huge fan of open source models, especially the newly release &lt;a href="https://llama.meta.com/llama3/" rel="noopener noreferrer"&gt;Llama 3&lt;/a&gt;. Because of the performance of both the large 70B Llama 3 model as well as the smaller and self-host-able 8B Llama 3, I’ve actually cancelled my ChatGPT subscription in favor of &lt;a href="https://docs.openwebui.com/" rel="noopener noreferrer"&gt;Open WebUI&lt;/a&gt;, a self-hostable ChatGPT-like UI that allows you to use &lt;a href="https://ollama.com/" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; and other AI providers while keeping your chat history, prompts, and other data locally on any computer you control.&lt;/p&gt;

&lt;p&gt;My &lt;a href="https://dev.to/timesurgelabs/how-to-run-llama-3-locally-with-ollama-and-open-webui-297d"&gt;previous article&lt;/a&gt; went over how to get Open WebUI set up with &lt;a href="https://ollama.com/" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; and Llama 3, however this isn’t the only way I take advantage of Open WebUI. The other way I use it is with external API providers, of which I use three. I’ll go over each of them with you and given you the pros and cons of each, then I’ll show you how I set up all 3 of them in my Open WebUI instance!&lt;/p&gt;

&lt;h2&gt;
  
  
  External AIs
&lt;/h2&gt;

&lt;h3&gt;
  
  
  OpenAI
&lt;/h3&gt;

&lt;p&gt;OpenAI can either be considered the classic or the monopoly. Their AI tech is the most mature, and trades blows with the likes of Anthropic and Google. Even though Llama 3 70B (and even the smaller 8B model) is good enough for 99% of people and tasks, sometimes you just need the best, so I like having the option either to just quickly answer my question or even use it along side other LLMs to quickly get options for an answer. &lt;/p&gt;

&lt;p&gt;OpenAI is the example that is most often used throughout the Open WebUI docs, however they can support any number of OpenAI-compatible APIs. Here’s another favorite of mine that I now use even more than OpenAI!&lt;/p&gt;

&lt;h3&gt;
  
  
  Groq Cloud
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://wow.groq.com/why-groq/" rel="noopener noreferrer"&gt;Groq&lt;/a&gt; is an AI hardware and infrastructure company that’s developing their own hardware LLM chip (which they call &lt;a href="https://wow.groq.com/groq-lpu-inference-engine-crushes-first-public-llm-benchmark/" rel="noopener noreferrer"&gt;an LPU&lt;/a&gt;). They offer an API to use their new LPUs with a number of open source LLMs (including Llama 3 8B and 70B) on their &lt;a href="https://console.groq.com" rel="noopener noreferrer"&gt;GroqCloud platform&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Their claim to fame is their insanely fast inference times - sequential token generation in the hundreds per second for 70B models and thousands for smaller models. Here’s Llama 3 70B running in real time on Open WebUI.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1782783466406322202-998" src="https://platform.twitter.com/embed/Tweet.html?id=1782783466406322202"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1782783466406322202-998');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1782783466406322202&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Here’s the best part - GroqCloud is &lt;strong&gt;free&lt;/strong&gt; for most users. With no credit card input, they’ll grant you some pretty high rate limits, significantly higher than most AI API companies allow. Here’s the limits for my newly created account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff628pyddn7ssjp8ay4kk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff628pyddn7ssjp8ay4kk.png" alt="API Example" width="800" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;14k requests per day is a lot, and 12k tokens per minute is significantly higher than the average person can use on an interface like Open WebUI. &lt;/p&gt;

&lt;p&gt;Using GroqCloud with Open WebUI is possible thanks to an &lt;a href="https://console.groq.com/docs/openai" rel="noopener noreferrer"&gt;OpenAI-compatible API&lt;/a&gt; that Groq provides. All you have to do is generate an API Key &lt;a href="https://console.groq.com/keys" rel="noopener noreferrer"&gt;via the dashboard&lt;/a&gt;, change the URL in the dashboard to &lt;code&gt;https://api.groq.com/openai/v1&lt;/code&gt;, and it’ll work just like OpenAI’s API!&lt;/p&gt;

&lt;p&gt;This is how I was able to use and evaluate Llama 3 as my replacement for ChatGPT!&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloudflare Workers AI
&lt;/h3&gt;

&lt;p&gt;This is the part where I toot my own horn a little. Using Open WebUI via Cloudflare Workers is not natively possible, however I developed my own &lt;a href="https://github.com/chand1012/openai-cf-workers-ai" rel="noopener noreferrer"&gt;OpenAI-compatible API for Cloudflare Workers&lt;/a&gt; a few months ago. I recently &lt;a href="https://github.com/chand1012/openai-cf-workers-ai/pull/8" rel="noopener noreferrer"&gt;added the &lt;code&gt;/models&lt;/code&gt; endpoint&lt;/a&gt; to it to make it compable with Open WebUI, and its been working great ever since. The main advantage of using Cloudflare Workers over something like GroqCloud is their &lt;a href="https://developers.cloudflare.com/workers-ai/models/#text-generation" rel="noopener noreferrer"&gt;massive variety of models&lt;/a&gt;. This allows you to test out many models quickly and effectively for many use cases, such as &lt;a href="https://developers.cloudflare.com/workers-ai/models/deepseek-math-7b-instruct/" rel="noopener noreferrer"&gt;DeepSeek Math&lt;/a&gt; (&lt;a href="https://huggingface.co/deepseek-ai/deepseek-math-7b-instruct" rel="noopener noreferrer"&gt;model card&lt;/a&gt;) for math-heavy tasks and &lt;a href="https://developers.cloudflare.com/workers-ai/models/llamaguard-7b-awq/" rel="noopener noreferrer"&gt;Llama Guard&lt;/a&gt; (&lt;a href="https://huggingface.co/meta-llama/LlamaGuard-7b" rel="noopener noreferrer"&gt;model card&lt;/a&gt;) for moderation tasks. They even support &lt;a href="https://developers.cloudflare.com/workers-ai/models/llama-3-8b-instruct/" rel="noopener noreferrer"&gt;Llama 3 8B&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;The main con of Workers AI is token limits and model size. Currently Llama 3 8B is the largest model supported, and they have &lt;a href="https://developers.cloudflare.com/workers-ai/models/llama-2-7b-chat-int8/#properties" rel="noopener noreferrer"&gt;token generation limits&lt;/a&gt; much smaller than some of the models available. I still think they’re worth having in this list due to the sheer variety of models they have available with no setup on your end other than of the API. If you want to set up OpenAI for Workers AI yourself, check out &lt;a href="https://github.com/chand1012/openai-cf-workers-ai?tab=readme-ov-file#deploying" rel="noopener noreferrer"&gt;the guide in the README&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding External AIs to Open WebUI
&lt;/h2&gt;

&lt;p&gt;Now, how do you add all these to your Open WebUI instance? Assuming you’ve installed Open WebUI (&lt;a href="https://docs.openwebui.com/getting-started/" rel="noopener noreferrer"&gt;Installation Guide&lt;/a&gt;), the best way is via environment variables.&lt;/p&gt;

&lt;p&gt;When running Open WebUI using Docker, you can set the &lt;code&gt;OPENAI_API_BASE_URLS&lt;/code&gt; and &lt;code&gt;OPENAI_API_KEYS&lt;/code&gt; environment variables to configure the API endpoints.&lt;/p&gt;

&lt;p&gt;For example, to integrate OpenAI, GroqCloud, and Cloudflare Workers AI, you would set the environment variables as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:8080 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; open-webui:/app/backend/data &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;OPENAI_API_BASE_URLS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://api.openai.com/v1;https://api.groq.com/openai/v1;https://openai-cf.yourusername.workers.dev/v1"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;OPENAI_API_KEYS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"sk-proj-ABCDEFGHIJK1234567890abcdef;gsk_1234567890abcdefabcdefghij;0123456789abcdef0123456789abcdef"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; open-webui &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--restart&lt;/span&gt; always &lt;span class="se"&gt;\&lt;/span&gt;
  ghcr.io/open-webui/open-webui:main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;sk-proj-ABCDEFGHIJK1234567890abcdef&lt;/code&gt;, &lt;code&gt;gsk_1234567890abcdefabcdefghij&lt;/code&gt;, and &lt;code&gt;0123456789abcdef0123456789abcdef&lt;/code&gt; with your actual API keys. Make sure to put the keys for each API in the same order as their respective API. If you don’t, you’ll get errors saying that the APIs could not authenticate.&lt;/p&gt;

&lt;p&gt;When using Docker Compose, you can define the environment variables in your &lt;code&gt;docker-compose.yaml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;open-webui&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;OPENAI_API_BASE_URLS=${OPENAI_API_BASE_URLS}'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;OPENAI_API_KEYS=${OPENAI_API_KEYS}'&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, you can define the values of these variables in an &lt;code&gt;.env&lt;/code&gt; file, placed in the same directory as the &lt;code&gt;docker-compose.yaml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;OPENAI_API_BASE_URLS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://api.openai.com/v1;https://api.groq.com/openai/v1;https://openai-cf.yourusername.workers.dev/v1"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;OPENAI_API_KEYS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"sk-proj-ABCDEFGHIJK1234567890abcdef;gsk_1234567890abcdefabcdefghij;0123456789abcdef0123456789abcdef"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By following these steps, you can easily integrate multiple OpenAI-compatible APIs with your Open WebUI instance, unlocking the full potential of these powerful AI models.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Open WebUI has opened up a whole new world of possibilities for me, allowing me to take control of my AI experiences and explore the vast array of OpenAI-compatible APIs out there. With the ability to seamlessly integrate multiple APIs, including OpenAI, Groq Cloud, and Cloudflare Workers AI, I've been able to unlock the full potential of these powerful AI models. By leveraging the flexibility of Open WebUI, I've been able to break free from the shackles of proprietary chat platforms and take my AI experiences to the next level. If you're tired of being limited by traditional chat platforms, I highly recommend giving Open WebUI a try and discovering the vast possibilities that await you.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>ai</category>
      <category>productivity</category>
      <category>api</category>
    </item>
    <item>
      <title>How to Run Llama 3 Locally with Ollama and Open WebUI</title>
      <dc:creator>Chandler</dc:creator>
      <pubDate>Sun, 21 Apr 2024 14:26:46 +0000</pubDate>
      <link>https://forem.com/timesurgelabs/how-to-run-llama-3-locally-with-ollama-and-open-webui-297d</link>
      <guid>https://forem.com/timesurgelabs/how-to-run-llama-3-locally-with-ollama-and-open-webui-297d</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/GT-Fwg124-I"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I’m a big fan of Llama. Meta releasing their LLM open source is a net benefit for the tech community at large, and their permissive license allows most medium and small businesses to use their LLMs with little to no restrictions (within the bounds of the law, of course). Their latest release is Llama 3, which has been highly anticipated.&lt;/p&gt;

&lt;p&gt;Llama 3 comes in two sizes: 8 billion and 70 billion parameters. This kind of model is trained on a massive amount of text data and can be used for a variety of tasks, including generating text, translating languages, writing different kinds of creative content, and answering your questions in an informative way. Meta touts Llama 3 as one of the best open models available, but it is still under development. Here’s the 8B model benchmarks when compared to Mistral and Gemma (according to Meta).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fax9r9z2w2zghv81grbh7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fax9r9z2w2zghv81grbh7.png" alt="Benchmarks" width="800" height="899"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This begs the question: how can I, the regular individual, run these models locally on my computer?&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started with Ollama
&lt;/h2&gt;

&lt;p&gt;That’s where &lt;a href="https://ollama.com/" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; comes in! Ollama is a free and open-source application that allows you to run various large language models, including Llama 3, on your own computer, even with limited resources. Ollama takes advantage of the performance gains of llama.cpp, an open source library designed to allow you to run LLMs locally with relatively low hardware requirements. It also includes a sort of package manager, allowing you to download and use LLMs quickly and effectively with just a single command. &lt;/p&gt;

&lt;p&gt;The first step is &lt;a href="https://ollama.com/download" rel="noopener noreferrer"&gt;installing Ollama&lt;/a&gt;. It supports all 3 of the major OSes, with &lt;a href="https://ollama.com/blog/windows-preview" rel="noopener noreferrer"&gt;Windows being a “preview”&lt;/a&gt; (nicer word for beta).&lt;/p&gt;

&lt;p&gt;Once this is installed, open up your terminal. On all platforms, the command is the same.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama run llama3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait a few minutes while it downloads and loads the model, and then start chatting! It should bring you to a chat prompt similar to this one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama run llama3
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; Who was the second president of the united states?
The second President of the United States was John Adams. He served from 1797 to 1801, succeeding
George Washington and being succeeded by Thomas Jefferson.

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; Who was the 30th?
The 30th President of the United States was Calvin Coolidge! He served from August 2, 1923, to March 4,
1929.

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; /bye
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can chat all day within this terminal chat, but what if you want something more ChatGPT-like?  &lt;/p&gt;

&lt;h2&gt;
  
  
  Open WebUI
&lt;/h2&gt;

&lt;p&gt;Open WebUI is an extensible, self-hosted UI that runs entirely inside of &lt;a href="https://docs.docker.com/desktop/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;. It can be used either with Ollama or other OpenAI compatible LLMs, like LiteLLM or my own &lt;a href="https://github.com/chand1012/openai-cf-workers-ai" rel="noopener noreferrer"&gt;OpenAI API for Cloudflare Workers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Assuming you already have &lt;a href="https://docs.docker.com/desktop/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; and Ollama running on your computer, &lt;a href="https://docs.openwebui.com/getting-started/#quick-start-with-docker-" rel="noopener noreferrer"&gt;installation&lt;/a&gt; is super simple.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:8080 &lt;span class="nt"&gt;--add-host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host.docker.internal:host-gateway &lt;span class="nt"&gt;-v&lt;/span&gt; open-webui:/app/backend/data &lt;span class="nt"&gt;--name&lt;/span&gt; open-webui &lt;span class="nt"&gt;--restart&lt;/span&gt; always ghcr.io/open-webui/open-webui:main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The simply go to &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;, make an account, and start chatting away!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frdi1d35zh09s78o8vqvb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frdi1d35zh09s78o8vqvb.png" alt="OpenWebUI Example" width="800" height="1169"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you didn’t run Llama 3 earlier, you’ll have to pull some models down before you can start chatting. Easiest way to do this is to click the settings icon after clicking your name in the bottom left.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftqyetksyn0y4a0p12ylu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftqyetksyn0y4a0p12ylu.png" alt="Settings" width="634" height="744"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then clicking on “models” on the left side of the modal, then pasting in a name of a model from the &lt;a href="https://ollama.com/models" rel="noopener noreferrer"&gt;Ollama registry&lt;/a&gt;. Here are some models that I’ve used that I recommend for general purposes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;llama3&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mistral&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;llama2&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftxc581jf4w3xszymjfbg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftxc581jf4w3xszymjfbg.png" alt="Models Setting Page" width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ollama API
&lt;/h2&gt;

&lt;p&gt;If you want to integrate Ollama into your own projects, Ollama offers both its own API as well as an OpenAI Compatible API. The APIs automatically load a locally held LLM into memory, run the inference, then unload after a certain timeout. You do have to pull whatever models you want to use before you can run the model via the API, which can easily be done via the command line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull mistral
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Ollama API
&lt;/h3&gt;

&lt;p&gt;Ollama has their own API available, which also has a &lt;a href="https://github.com/ollama/ollama?tab=readme-ov-file#libraries" rel="noopener noreferrer"&gt;couple of SDKs&lt;/a&gt; for Javascript and Python.&lt;/p&gt;

&lt;p&gt;Here is how you can do a simple text generation inference with the API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:11434/api/generate &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
  "model": "mistral",
  "prompt":"Why is the sky blue?"
}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here’s how you can do a Chat generation inference with the API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:11434/api/chat &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
  "model": "mistral",
  "messages": [
    { "role": "user", "content": "why is the sky blue?" }
  ]
}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the &lt;code&gt;model&lt;/code&gt; parameter with whatever model you want to use. See the &lt;a href="https://github.com/ollama/ollama/blob/main/docs/api.md" rel="noopener noreferrer"&gt;official API docs&lt;/a&gt; for more information.&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenAI Compatible API
&lt;/h3&gt;

&lt;p&gt;You can also use Ollama as a drop in replacement (depending on use case) with the OpenAI libraries. Here’s an example from &lt;a href="https://github.com/ollama/ollama/blob/main/docs/openai.md" rel="noopener noreferrer"&gt;their documentation&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Python
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;http://localhost:11434/v1/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;# required but ignored
&lt;/span&gt;    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ollama&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;chat_completion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Say this is a test&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mistral&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This also works for Javascript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Javascript&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;OpenAI&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;openai&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;openai&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:11434/v1/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="c1"&gt;// required but ignored&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ollama&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chatCompletion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Say this is a test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;llama2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The release of Meta's Llama 3 and the open-sourcing of its Large Language Model (LLM) technology mark a major milestone for the tech community. With these advanced models now accessible through local tools like Ollama and Open WebUI, ordinary individuals can tap into their immense potential to generate text, translate languages, craft creative writing, and more. Furthermore, the availability of APIs enables developers to seamlessly integrate LLMs into new projects or enhance existing ones. Ultimately, the democratization of LLM technology through open-source initiatives like Llama 3 unlocks a vast realm of innovative possibilities and fuels creativity in the tech industry.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>ai</category>
      <category>productivity</category>
      <category>api</category>
    </item>
    <item>
      <title>Building a Fast, Efficient Web App: The Technology Stack of PromptSmithy Explained</title>
      <dc:creator>Chandler</dc:creator>
      <pubDate>Tue, 26 Mar 2024 17:08:07 +0000</pubDate>
      <link>https://forem.com/timesurgelabs/building-a-fast-efficient-web-app-the-technology-stack-of-promptsmithy-explained-184f</link>
      <guid>https://forem.com/timesurgelabs/building-a-fast-efficient-web-app-the-technology-stack-of-promptsmithy-explained-184f</guid>
      <description>&lt;p&gt;I’ve written a lot of one-off project, internal scripts for my own use, B2C apps, B2B apps, and everything in between. Every time I start a new project I like to use a new stack to try and diversify my own skillset, and so that if I’m ever tasked with doing another similar project in the future, my knowledge can accelerate my workflow. &lt;a href="https://promptsmithy.com/" rel="noopener noreferrer"&gt;PromptSmithy&lt;/a&gt; was slightly different though, as the stack hadn’t changed from other recent projects of mine, however the frontend tooling did greatly. In this article I’m going to break down the stack we used and talk about the new development flow we used for rapid development.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;h3&gt;
  
  
  React + Vite + React Router
&lt;/h3&gt;

&lt;p&gt;We all know what &lt;a href="https://react.dev/" rel="noopener noreferrer"&gt;React&lt;/a&gt; is at this point, but why use it with &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt; and &lt;a href="https://reactrouter.com/en/main" rel="noopener noreferrer"&gt;React Router DOM&lt;/a&gt; over something like &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;NextJS&lt;/a&gt;? &lt;/p&gt;

&lt;p&gt;The reasons are twofold: We didn’t need any of the backend functionality of NextJS, and I wanted something that wouldn’t get in the way of our development with SSR or any other special cases that are only found on NextJS.&lt;/p&gt;

&lt;p&gt;On top of that, Vite’s compiler is super fast, supports &lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;Typescript&lt;/a&gt; (which we of course used), and built just fine on our host, which was &lt;a href="https://pages.cloudflare.com/" rel="noopener noreferrer"&gt;Cloudflare Pages. Cloudflare Pages&lt;/a&gt; is a super fast static website hosting service by Cloudflare, which allows your site to take advantage of their global CDN to make sure your site is as close to your users as possible. It supports nearly any JS framework you could want to use for your site, and can even host plan old HTML if you’re of that persuasion.&lt;/p&gt;

&lt;p&gt;React Router is also super minimal and doesn’t get in the way, and provides all the same functionality of NextJS’s static output router without making your compile sizes massive. Our entire built site (before we added all the fancy physics animations) was just a bit over 135KB. &lt;/p&gt;

&lt;h3&gt;
  
  
  Tailwind + shadcn/ui + v0.dev
&lt;/h3&gt;

&lt;p&gt;For development of the UI components, we tried something new. Vercel has this new AI tool called &lt;a href="http://v0.dev" rel="noopener noreferrer"&gt;v0.dev&lt;/a&gt; that allows developers to take advantage of &lt;a href="https://ui.shadcn.com/" rel="noopener noreferrer"&gt;shadcn/ui&lt;/a&gt; and &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind&lt;/a&gt; using nothing but words, which can then be easily downloaded to your local project using nothing but a simple &lt;code&gt;npx&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjxoy51g12efo45ozzr77.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjxoy51g12efo45ozzr77.png" alt="Here is the original example code for a 404 page that I ended up using in the final app!" width="800" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the &lt;a href="https://v0.dev/t/RB8eJs2Kd6R" rel="noopener noreferrer"&gt;original example code&lt;/a&gt; for a 404 page that I ended up using in the final app! &lt;code&gt;npx v0 add RB8eJs2Kd6R&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;While I have experience with Tailwind and frontend development, I don’t really have the patience to use it. I usually end up using something like &lt;a href="https://mantine.dev/" rel="noopener noreferrer"&gt;Mantine&lt;/a&gt;, which is a complete component library UI kit, or &lt;a href="https://daisyui.com/" rel="noopener noreferrer"&gt;Daisy UI&lt;/a&gt;, which is a component library built on top of Tailwind. Shadcn/ui is quite similar to Daisy in this sense, but being able to customize the individual components, since they get installed to your components folder, made development more streamlined and more customizable. On top of that being able to change my components style with natural language thanks to v0 made development super easy and fast. Shadcn may be too minimalist of a style for some, but thanks to all the components being local, you can customize them quickly and easily!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsijgkghiwn9ibl4bru0x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsijgkghiwn9ibl4bru0x.png" alt="This is the structure of the project’s components directory" width="746" height="740"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the structure of the project’s components directory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Supabase
&lt;/h3&gt;

&lt;p&gt;Here the thing that accelerated my development the most: &lt;a href="https://supabase.com/" rel="noopener noreferrer"&gt;Supabase&lt;/a&gt;. Thanks to its Database, Authentication, and Edge Functions, we were able to rapidly develop the app. Their JS library made development super seamless, and their local development stack made testing a breeze. &lt;/p&gt;

&lt;p&gt;The development process is simple: install their &lt;a href="https://supabase.com/docs/guides/cli" rel="noopener noreferrer"&gt;CLI&lt;/a&gt;,  run &lt;code&gt;supabase init&lt;/code&gt;, run &lt;code&gt;supabase start&lt;/code&gt;. That’s it. (Assuming you have Docker installed that is.)&lt;/p&gt;

&lt;p&gt;The database service is pretty self explanatory. Rather than having to write SQL queries in a remote API, hosting that API as well as the database to go with it, you simply create tables with migrations (created using &lt;code&gt;supabase migrations new name_here&lt;/code&gt;), then you can query the migrations using the frontend API. From there you can configure row level security, which restricts access to specific rows on a per user basis, using either the migrations themselves or using the local UI. I opted for the former so that I could easily apply the migrations. Here is one I wrote for the project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;prompts&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;bigint&lt;/span&gt; &lt;span class="k"&gt;primary&lt;/span&gt; &lt;span class="k"&gt;key&lt;/span&gt; &lt;span class="k"&gt;generated&lt;/span&gt; &lt;span class="n"&gt;always&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="k"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;metaprompt_id&lt;/span&gt; &lt;span class="nb"&gt;bigint&lt;/span&gt; &lt;span class="k"&gt;references&lt;/span&gt; &lt;span class="n"&gt;metaprompts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;variables&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="nb"&gt;timestamp&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt; &lt;span class="k"&gt;zone&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="n"&gt;updated_at&lt;/span&gt; &lt;span class="nb"&gt;timestamp&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt; &lt;span class="k"&gt;zone&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nb"&gt;boolean&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;alter&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;prompts&lt;/span&gt;
  &lt;span class="n"&gt;enable&lt;/span&gt; &lt;span class="k"&gt;row&lt;/span&gt; &lt;span class="k"&gt;level&lt;/span&gt; &lt;span class="k"&gt;security&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="nv"&gt;"Users can insert their own prompts"&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;prompts&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;insert&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="k"&gt;check&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="nv"&gt;"Users can read their own prompts that are private"&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;prompts&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="nv"&gt;"Users can read all prompts that are public"&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;prompts&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This then got applied locally by running &lt;code&gt;supabase db reset&lt;/code&gt;, and deployed remotely with &lt;code&gt;supabase db push&lt;/code&gt;. We could then query on the frontend using the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prompts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;created_at&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;ascending&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see &lt;a href="https://supabase.com/docs/guides/getting-started/quickstarts/reactjs" rel="noopener noreferrer"&gt;Supabase’s excellent guides&lt;/a&gt; on how to do this for more information.&lt;/p&gt;

&lt;p&gt;We also took advantage of Supabase’s Authentication service that allows us to quickly and effectively log in a user so we can handle authenticated requests (which once Row Level Security is set up is automatic) quickly. Since this was a weekend project sort of app, we went with Supabase Magic Links, which allows our users to log in by simply entering their email and clicking a link that gets sent. Here’s all the code to do that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;me@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signInWithOtp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it! Then all we had to do is have the user click the link (assuming your website URL is configured properly in the Supabase settings) and they were logged in!&lt;/p&gt;

&lt;p&gt;Finally we used Supabase Edge Functions to handle payments with Stripe, as well as hold the business logic of PromptSmithy, which primarily just calling Anthropic AI. Edge Functions are written in Deno, which is a NodeJS alternative that I like very much. You create a new edge function by running &lt;code&gt;supabase functions new name_here&lt;/code&gt; and then deploying with &lt;code&gt;supabase functions deploy&lt;/code&gt; . You can also run these functions locally for testing (which is what we did along with the Stripe CLI’s webhook feature) with &lt;code&gt;supabase functions serve&lt;/code&gt; . &lt;/p&gt;

&lt;p&gt;Calling your functions on the frontend is super simple too. Whenever we wanted to call the AI, this is the code we run on the frontend.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Write me an email response to my boss asking for a raise&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoke&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;create-task-prompt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;public&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;metapromptID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The value of &lt;code&gt;resp&lt;/code&gt; would be whatever we responded with, which is always JSON for our application. &lt;/p&gt;

&lt;p&gt;Functions can also be invoked by remote applications, for example Stripe webhooks. If you want this, you’ll need to make sure that JWT verification is disabled for that function, which can be done simply in the &lt;code&gt;config.toml&lt;/code&gt; in the &lt;code&gt;supabase&lt;/code&gt;  directory of your project. Here’s an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[functions.stripe-webhook]&lt;/span&gt;
&lt;span class="py"&gt;verify_jwt&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now whenever this function is deployed you can check your Edge Functions page for a URL to give to Stripe!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, our choice of stack for PromptSmithy’s project was primarily based on the speed of development and the performance of the end product. Using tools like Vite, React, Supabase, and the innovative v0.dev, we were able to develop rapidly and effectively, resulting in a highly functional and efficient application.&lt;/p&gt;

&lt;p&gt;Want to give &lt;a href="https://promptsmithy.com/" rel="noopener noreferrer"&gt;PromptSmithy&lt;/a&gt; a try? All new users get &lt;strong&gt;$5 in free credits!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>productivity</category>
    </item>
    <item>
      <title>🦉 AthenaDB: Distributed Vector Database Powered by Cloudflare 🌩️</title>
      <dc:creator>Chandler</dc:creator>
      <pubDate>Mon, 19 Feb 2024 18:47:15 +0000</pubDate>
      <link>https://forem.com/timesurgelabs/athenadb-distributed-vector-database-powered-by-cloudflare-4p59</link>
      <guid>https://forem.com/timesurgelabs/athenadb-distributed-vector-database-powered-by-cloudflare-4p59</guid>
      <description>&lt;h2&gt;
  
  
  What is AthenaDB?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/TimeSurgeLabs/athenadb" rel="noopener noreferrer"&gt;AthenaDB&lt;/a&gt; is a serverless vector database designed to be highly distributed and easily accessible as an API. It leverages &lt;a href="https://developers.cloudflare.com/workers-ai/" rel="noopener noreferrer"&gt;Cloudflare’s Workers AI&lt;/a&gt; platform to create the vectors, &lt;a href="https://developers.cloudflare.com/vectorize/" rel="noopener noreferrer"&gt;Cloudflare Vectorize&lt;/a&gt; for handling vector querying, and &lt;a href="https://developers.cloudflare.com/d1/" rel="noopener noreferrer"&gt;Cloudflare D1&lt;/a&gt; as its database for storing text. This combination allows AthenaDB to offer a simple yet powerful set of API endpoints for inserting, querying, retrieving, and deleting vector text data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features of AthenaDB
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simple API Endpoints&lt;/strong&gt;: AthenaDB provides straightforward endpoints for various database operations, making it accessible for developers of all skill levels.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distributed Nature&lt;/strong&gt;: With data replication across multiple data centers, AthenaDB ensures high availability and resilience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-In Data Replication&lt;/strong&gt;: Due to Cloudflare Workers’ underlying architecture, data is replicated across data centers automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: AthenaDB is designed to handle large amounts of vector text data, making it suitable for projects with high data volumes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Serverless Architecture&lt;/strong&gt;: With AthenaDB being serverless, you don't have to worry about managing infrastructure, allowing for more focus on development.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Are Vector Databases?
&lt;/h2&gt;

&lt;p&gt;Vector databases are a special kind of computer storage that helps artificial intelligence (AI) programs quickly understand and use information. They work by turning data into numbers (called vectors) that the AI can easily compare to find similarities. This is really useful for things like online searches, suggesting products you might like, or creating smart chatbots. &lt;/p&gt;

&lt;p&gt;For example, if a vector database has the following three items: “Python is cool”, “Java is cool”, and “C is statically typed”, and the user uses a search query “coffee”, it would return “Java is cool”. Why? Because while the user may not have been talking about the programming language Java, the words “java” and “coffee” have similar root meaning, which the neural network that created the vectors relates using complex math. &lt;/p&gt;

&lt;p&gt;You can learn more about them &lt;a href="https://www.cloudflare.com/learning/ai/what-is-vector-database/" rel="noopener noreferrer"&gt;in this article&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Cloudflare?
&lt;/h2&gt;

&lt;p&gt;Cloudflare has a serverless compute platform called &lt;a href="https://workers.cloudflare.com/" rel="noopener noreferrer"&gt;Workers&lt;/a&gt;. Workers are automatically replicated across all Cloudflare data centers, meaning that the developer can make an API or other application that automatically scales with zero infrastructure! Workers also automatically routes user requests to their nearest data center, meaning that latency is reduced significantly!&lt;/p&gt;

&lt;p&gt;By using this, it means AthenaDB gets many of the features of Cloudflare’s Platform - Data replication, distribution across data centers, and an infinitely scalable serverless architecture - with no complicated code base or management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started with AthenaDB
&lt;/h2&gt;

&lt;p&gt;Deploying and using AthenaDB involves a few steps, starting from setting up your environment to deploying your instance of AthenaDB.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before you begin, make sure you have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloudflare account&lt;/li&gt;
&lt;li&gt;Node.js and npm installed&lt;/li&gt;
&lt;li&gt;Wrangler CLI installed (&lt;code&gt;npm install -g @cloudflare/wrangler&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Deployment Steps
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Clone the Repository&lt;/strong&gt;: Start by cloning the AthenaDB repository to your local machine, installing dependencies, and logging in to Wrangler.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/TimeSurgeLabs/athenadb.git
&lt;span class="nb"&gt;cd &lt;/span&gt;athenadb
npm i
npx wrangler login
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a Vector and Database&lt;/strong&gt;: Use the provided npm scripts to create a vector and database for your AthenaDB instance.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run create-vector
npm run create-db
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;After running these commands, copy the output Database ID and update the &lt;code&gt;wrangler.toml&lt;/code&gt; file under &lt;code&gt;database_id&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Initialize the Database&lt;/strong&gt;: Run the initialization script to set up the database schema.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run init-db
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deploy AthenaDB&lt;/strong&gt;: Finally, deploy your instance of AthenaDB using Wrangler.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run deploy
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Upon successful deployment, you will receive an output with your API URL, which indicates that AthenaDB is now ready for use.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Using AthenaDB
&lt;/h3&gt;

&lt;p&gt;With AthenaDB deployed, you can start interacting with the database through its API endpoints. Here are some examples of how you can use AthenaDB:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Inserting Text Data&lt;/strong&gt;: Use the &lt;code&gt;/insert&lt;/code&gt; endpoint to add text data into the database.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://athenadb.yourusername.workers.dev/your-namespace/insert&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Your text here&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Querying the Database&lt;/strong&gt;: To find similar text embeddings, use the &lt;code&gt;/query&lt;/code&gt; endpoint.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://athenadb.yourusername.workers.dev/your-namespace/query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Query text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Retrieving an Entry&lt;/strong&gt;: Retrieve specific entries using their UUID with the &lt;code&gt;GET&lt;/code&gt; endpoint.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://athenadb.yourusername.workers.dev/your-namespace/your-uuid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deleting Data&lt;/strong&gt;: Use the &lt;code&gt;/delete&lt;/code&gt; endpoint to remove data from the database.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://athenadb.yourusername.workers.dev/your-namespace/your-uuid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DELETE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;AthenaDB stands out as a powerful tool for developers needing a scalable, serverless database solution for managing vector text data. By following the steps outlined in this blog post, you can deploy your own instance of AthenaDB and begin leveraging its capabilities for your projects. Whether you're building search engines, recommendation systems, or any application that requires efficient handling of vector data, AthenaDB provides a robust, easy-to-use solution.&lt;/p&gt;

&lt;p&gt;If you’re looking to integrate AI into your existing workflow or products, &lt;a href="https://timesurgelabs.com/" rel="noopener noreferrer"&gt;TimeSurge Labs&lt;/a&gt; is here to help. Specializing in AI consulting, development, internal tooling, and LLM hosting, our team of passionate AI experts is dedicated to building the future of AI and helping your business thrive in this rapidly changing industry. &lt;a href="https://timesurgelabs.com/#contact" rel="noopener noreferrer"&gt;Contact us&lt;/a&gt; today!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>database</category>
      <category>cloud</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Credit Card Skimmers &amp; Open Source | Causal Coders Podcast</title>
      <dc:creator>Chandler</dc:creator>
      <pubDate>Mon, 12 Feb 2024 13:46:47 +0000</pubDate>
      <link>https://forem.com/casualcoders/credit-card-skimmers-open-source-causal-coders-podcast-362g</link>
      <guid>https://forem.com/casualcoders/credit-card-skimmers-open-source-causal-coders-podcast-362g</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/pKY3kB39iWc"&gt;
&lt;/iframe&gt;
&lt;br&gt;
Season 2 of the Casual Coders podcast is live! I was not in the first episode, but it’s still a good one! In this first episode they talk about credit card skimmers and how credit cards work, the best open source tools, and a long running web server project by one of our hosts! Available on Spotify, Apple Podcasts, YouTube, or wherever you get your podcasts!&lt;br&gt;
&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://creators.spotify.com/pod/profile/casual-coders/embed" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fd3t3ozftmdmh3i.cloudfront.net%2Fstaging%2Fpodcast_uploaded_nologo400%2F16776332%2F16776332-1707408112500-5db323d9bbb53.jpg" height="400" class="m-0" width="400"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://creators.spotify.com/pod/profile/casual-coders/embed" rel="noopener noreferrer" class="c-link"&gt;
            Casual Coders Podcast • A podcast on Spotify for Creators
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Welcome to the Casual Coders Podcast! We're a group of makers and engineers who talk nerd and make cool stuff! 

We strive to release two podcasts a month!

Follow our socials!
YouTube | https://www.youtube.com/c/CasualCodersOfficial
Instagram | https://www.instagram.com/casualcodersprojects/
Twitter | https://twitter.com/CasualCoders 
Facebook | https://www.facebook.com/CasualCodersProjects 
TikTok | https://www.tiktok.com/@casualcoders 

          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fd12xoj7p9moygp.cloudfront.net%2Ffavicon%2Ffavicon-s4p-196x196.png" width="196" height="196"&gt;
          creators.spotify.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>podcast</category>
      <category>opensource</category>
      <category>programming</category>
    </item>
    <item>
      <title>How I Use Google's Gemini Pro with LangChain</title>
      <dc:creator>Chandler</dc:creator>
      <pubDate>Thu, 04 Jan 2024 17:00:26 +0000</pubDate>
      <link>https://forem.com/timesurgelabs/how-to-use-googles-gemini-pro-with-langchain-1eje</link>
      <guid>https://forem.com/timesurgelabs/how-to-use-googles-gemini-pro-with-langchain-1eje</guid>
      <description>&lt;p&gt;Google's Gemini Pro is one of the newest LLMs publicly available, and to the surprise of some its relatively price competitive.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvin3nlq60w8hd6m2wc99.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvin3nlq60w8hd6m2wc99.png" alt="Gemini Pro Pricing" width="800" height="816"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Its effectively free while you're developing, and after you development is complete its relatively cheap, costing around $0.00025 per 1K characters (&lt;strong&gt;characters&lt;/strong&gt;, not &lt;strong&gt;tokens&lt;/strong&gt; like OpenAI), which is slightly more expensive than GPT-3.5-Turbo, and $0.0025 per image, which is effectively the same as OpenAI's GPT-4).&lt;/p&gt;

&lt;h2&gt;
  
  
  Okay, I get it, how do I use it?
&lt;/h2&gt;

&lt;p&gt;Let's start fresh with a new project. Assuming you're using Python &amp;gt;= 3.10, let's initialize a new virtual environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; venv &lt;span class="nb"&gt;env
source env&lt;/span&gt;/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And let's install LangChain and our dotenv file loader first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install langchain python-dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once that's done, we can install Gemini Pro's libraries and its LangChain adapter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install google-generativeai langchain-google-genai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next you need to acquire an API key, which can be done on the &lt;a href="https://makersuite.google.com" rel="noopener noreferrer"&gt;Google MakerSuite&lt;/a&gt;. In the top left of the page you should see a "Get API Key" button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff9icwjzh0oco2n5d0zgl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff9icwjzh0oco2n5d0zgl.png" alt="API Key Button" width="620" height="523"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click that button, then click "Create API Key in new project". &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiw4uv7wwo2baq2ge5rim.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiw4uv7wwo2baq2ge5rim.png" alt="New Key Button" width="800" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy the new API Key and save it to a .env file in your project directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;GOOGLE_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;new_api_key_here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can create a script that calls Gemini Pro via LangChain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_google_genai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatGoogleGenerativeAI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.prompts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PromptTemplate&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.chains&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LLMChain&lt;/span&gt;

&lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;GOOGLE_API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GOOGLE_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChatGoogleGenerativeAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-pro&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;google_api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;GOOGLE_API_KEY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;tweet_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PromptTemplate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a content creator. Write me a tweet about {topic}.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;tweet_chain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LLMChain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tweet_prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;topic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;how ai is really cool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tweet_chain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it! You've now integrated Gemini Pro with LangChain! If you're interested in learning more about LangChain and AI, follow us here on Dev.to as well as on &lt;a href="https://twitter.com/TimeSurgeLabs" rel="noopener noreferrer"&gt;X&lt;/a&gt;! I also post a lot of AI and developer stuff on my &lt;a href="https://twitter.com/Chand1012Dev" rel="noopener noreferrer"&gt;personal X account&lt;/a&gt;! We also have more articles on LangChain an AI on &lt;a href="https://dev.to/timesurgelabs"&gt;our Dev Page&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Happy coding! &lt;/p&gt;

</description>
      <category>python</category>
      <category>ai</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
