Categories
Meetups Players Presentations Programming Tampa Bay

Notes from Venkat Subramaniam’s presentation on finding and fixing code with AI (Monday, December 8, 2025)

It’s always a treat to see one of Dr. Venkat Subramaniam’s presentations, and Monday evening’s session, Identifying and fixing Issues in Code using AI-based tools, was no exception!

On behalf of the Tampa Bay Artificial Intelligence Meetup, Anitra and I would like to thank Ammar Yusuf, Tampa Java User Group, and Tampa Devs for inviting us to participate in this meetup, and to thank Venkat for an excellent lecture.

Here are my notes and photos…

Part 1: What AI actually Is (and isn’t)

Think of AI as “Accelerated Inference”

  • The reality check: The term “Artificial Intelligence” is misleading. It suggests that an application has sentience or wisdom. Venkat suggests a more accurate definition for AI: Accelerated Inference.
  • Inference vs. intelligence:
    • If you see a purple chair and then another purple chair, you infer that chairs are purple. That isn’t necessarily true, but it is a logical conclusion based on available data.
    • AI does this on a massive scale. It doesn’t “know” the answer; it infers the most statistically probable answer based on the massive volume of data it was fed.
  • Speed vs. accuracy: Machines are “wicked fast,” but they are also error-prone. Humans are slow and error-prone. AI allows us to make mistakes at a much higher velocity if we aren’t careful.

Karma

  • Garbage in, garbage out: AI models are trained on billions of lines of code, most of it written by humans (at least for now).
  • The problem: Humans write bugs. We write security vulnerabilities. We write bad variable names.
  • The consequence: Because AI learns from human code, it learns our bad habits. Venkat says this is karma. When we complain about AI writing bad code, we’re really complaining about our own collective history of programming mistakes coming back to haunt us.
  • The takeaway: Don’t assume AI output is “production-ready.” Treat AI-generated code with the same skepticism you would treat code copied from a random forum post in 2010.

The “novice vs. expert ” paradox

Venkat described a specific phenomenon regarding how we perceive AI’s competence:

  • The novice view: When you ask an AI to do something you know nothing about (e.g., writing a poem in a language you don’t speak), the result looks amazing. You find it awesome because you lack the expertise to judge it.
  • The expert view: When you ask AI to do something you are an expert in (e.g., writing high-performance Java code), you often find the result “awful.” You can spot the subtle bugs, the global variables, and the inefficiencies immediately.
  • The danger zone: As a developer, you are often in the middle. You know enough to be dangerous. Be careful not to be dazzled by the “novice view” when generating code for a new framework or language.


Part 2: Strategies for using AI effectively

1. Use AI for ideas instead of solutions

  • Don’t ask for the answer immediately. If you treat AI as a maker of solutions, you bypass the critical thinking process required to be a good engineer.
  • Ask for approaches. Instead of “Write this function,” ask: “I need to solve X problem. What are three different design patterns I could use?”
  • Love the weirdness: AI is great at throwing out random, sometimes hallucinated ideas. Use these as inspirations or starting points for brainstorming. “Accept weird ideas, but reject strange solutions,” Venkat said.

2. Managing cognitive load

  • The human limit: We struggle to keep massive amounts of context in our heads. We get tired. We get “analysis paralysis.”
  • AI’s strong suit: AI doesn’t get tired. It can read a 7,000-line legacy function with terrible variable names and not get a headache or confused.
  • The “Translator” technique:
    • Venkat used the analogy of translating a foreign language into your “mother tongue” to understand it emotionally and logically.
    • Try this: Paste a complex, confusing block of legacy code into an AI tool and ask, “Explain this to me in plain English.” This helps you understand intent without getting bogged down in syntax.

3. The Δt (“delta t”) approach

  • Don’t “one-shot” it: Just as numerical analysis (calculus) requires taking small steps (Δt) to get an accurate curve, working with AI requires small iterations.
  • Workflow:
    1. Present the AI with the problem and ask it for possible approaches.
    2. Review its replies. Chances are that at least some of them (or maybe all of them) will be wrong, buggy, or not the answer you’re looking for.
    3. Don’t give up. Instead, provide feedback: “This code isn’t thread-safe,” or “This variable is null.”
    4. The AI will often correct itself. This back-and-forth “dance” is where the actual development happens.

Part 3: Code examples

Venkat demonstrated several scenarios where code looked correct but had problems that weren’t immediately apparent, and showed how AI helped (or didn’t).

Case study: Fruit

The first case study was a version of a problem presented to Venkat by a client. He couldn’t present the actual code without violating the client NDA, so he presented a simplified version that still captured the general idea of the problem with the code.

Here’s the first version of the code:

// Java

import java.util.*;

public class Sample {
    public static List stringsOfLength5InUpperCase(List strings) {
        List result = new ArrayList<>();

        strings.stream()
            .map(String::toUpperCase)
            .filter(string -> string.length() == 5)
            .forEach(result::add);

        return result;
    }

    public static void main(String[] args) {
        var fruits = List.of("Apple", "Banana", "Orange", "Grape", "Guava", "Kiwi",
                "Mango", "Nance", "Papaya", "Peach", "Lime", "Lemon");

        var result = stringsOfLength5InUpperCase(fruits);

        System.out.println(result);
    }
}

This version of the code works as expected, printing the 7 fruit names in the list that are 5 characters long.

Right now, it’s single-threaded, and it could be so much more efficient! A quick change from .stream() to .parallelStream()should do the trick, and the resulting code becomes

// Java

import java.util.*;

public class Sample {
    public static List stringsOfLength5InUpperCase(List strings) {
        List result = new ArrayList<>();

        //  Here's the change
        strings.parallelStream()
            .map(String::toUpperCase)
            .filter(string -> string.length() == 5)
            .forEach(result::add);

        return result;
    }

    public static void main(String[] args) {
        var fruits = List.of("Apple", "Banana", "Orange", "Grape", "Guava", "Kiwi",
                "Mango", "Nance", "Papaya", "Peach", "Lime", "Lemon");

        var result = stringsOfLength5InUpperCase(fruits);

        System.out.println(result);
    }
}

The code appears to work — until you run it several times and notice that it will occasionally produce a list of less than 7 fruit names.

Why did this happen? Because Java’sArrayList isn’t thread-safe, and writing to a shared variable from inside a parallel stream causes race conditions. But this is the kind of bug that’s hard to spot.

Venkat fed the code to Claude and asked what was wrong with it, and after a couple of tries (because AI responses aren’t consistent), it identified the problem: creating a side effect in a stream and relying on its value. It suggested using a collector like toList() to capture the the 5-character fruit names; it’s thread-safe.

Claude also suggested applying the filter before converting the list values to uppercase, so as not to perform work on values that would be filtered out.

The takeaway: AI is excellent at spotting errors that  we humans often miss because we’re so focused on the business logic.

Case study: Parameters

I didn’t get a photo of this code example, but it featured a function that looked like this:

public String doSomething(String someValue) {

    // Some code here

    someValue = doSomethisElse(someValue)

    // More code here

}

I’m particularly proud of the fact that I spotted the mistake was the first one to point it out: mutating a parameter.

Venkat fed the code to Claude, and it dutifully reported the same error.

It was easy for me to spot such an error in a lone function. But spotting errors like this in an entire project of files? I’d rather let AI do that.

Case study: Currency converter

I didn’t get a photo of this one, but it featured base class CurrencyConverter with a method convert(float amount). A subclass NokConverter attempted to override it to handle Norwegian Krone.

The problem was that NokConverter’s conversion method’s signature was convert(int amount), which meant that it was overloaded instead of overridden. As a result, polymorphism was lost, and the client code ends up calling the base class method instead of the subclass method. But that’s pretty easy to miss — after all, the code appears to work properly.

A quick check with the AI pointed out that the method was not actually overriding, and it also suggested adding the @Override annotation, which is meant to prevent this kind of subtle error.

Remember: don’t just let AI fix it; understand why the fix works. In this case, it was about strictly enforcing contract hierarchy.

Case study: Wordle

Venkat asked Claude to write a Wordle clone, and it did so in seconds.

But: the logic regarding how yellow/green squares were calculated was slightly off in edge cases.

AI sometimes implements logic that looks like the rules but fails on specific boundary conditions. It’s a good idea to write unit tests for AI-generated logic. Never trust that the algorithmic logic is sound just because the syntax is correct.


Part 4: The “Testing” Gap

Missing test suites

  • Venkat noted a disturbing trend: he sees very few test cases accompanying AI-generated code.
  • Developers tend to generate the solution and manually verify it once (“It works on my machine”), then ship it.
  • The Risk: AI code is brittle. If you ask it to refactor later, it might break the logic. Without a regression test suite (which the AI didn’t write for you), you won’t know.

How to use AI for testing

  • Invert the flow! Instead of asking AI to write the code, write the code yourself (or design it), and ask AI to:
    • “Generate 10 unit tests for this function, including edge cases.”
    • “Find input values that would cause this function to crash.”
  • AI is often better at playing “Devil’s Advocate” (breaking code) than being the Architect (building code).

Part 5: Takeaways

Job security in the age of AI

  • The Fear: “Will I lose my job to AI?”
  • The Reality: You will not lose your job to AI. You will lose your job to another programmer who knows how to use AI better than you do.
  • The “Code Monkey” extinction: If your primary skill is just typing syntax (converting a thought into Java/Python syntax), you are replaceable. AI does that better.
  • The value-add: Your value is now as a problem solver and solution reviewer. You’re paid to understand the business requirements and ensure the machine code actually meets them.

Adaptation is key!

  • Venkat used a quote commonly attributed to Charles Darwin (see here for more): “It is not the strongest of the species that survives, nor the most intelligent that survives. It is the one that is most adaptable to change.”
  • Action Plan:
    • Don’t fight the tool
    • Don’t blindly trust the tool
    • Learn to verify the tool
    • Shift your focus from “How do we write a loop?” to “Why are we writing this loop?”

Empathy and code review

  • When AI generates bad code, we analyze it dispassionately. When humans write bad code, we get angry or judgmental.
  • The Shift: We need to extend the “AI Review” mindset to human code reviews. Be objective. Find the fault in the logic, not the person.
  • AI has shown us that everyone (including the machine trained on everyone’s code) writes bad code. It’s the universal developer experience.
Categories
Design Hardware Humor Programming

The toaster from the “toaster programmer” joke of the 1990s is now real!

While doing Christmas shopping, I stumbled across the device pictured above — the Revolution InstaGLO R180 Connect Plus toaster, which retails for $400 — and thought: Do they not remember the “toaster programmer” joke from the 1990s?

In case you’re not familiar with the joke, it’s one that made the rounds on internet forums back then, as a sort of “text meme.” Here it is…


Once upon a time, in a kingdom not far from here, a king summoned two of his advisors for a test. He showed them both a shiny metal box with two slots in the top, a control knob, and a lever. “What do you think this is?”

One advisor, an Electrical Engineer, answered first. “It is a
toaster,” he said.

The king asked, “How would you design an embedded
computer for it?”

The advisor: “Using a four-bit microcontroller, I would write a simple program that reads the darkness knob and
quantifies its position to one of 16 shades of darkness, from snow white to coal black. The program would use that darkness level as the index to a 16-element table of initial timer values. Then it would turn on the heating elements and start the timer with the initial value selected from the table. At the end of the time delay, it would turn off the heat and pop up the toast. Come back next week, and I’ll show you a working prototype.”

The second advisor, a software developer, immediately recognized the danger of such short-sighted thinking. He said, “Toasters don’t just turn bread into toast, they are also used to warm frozen waffles. What you see before you is really a breakfast food cooker. As the subjects of your kingdom become more sophisticated, they will demand more capabilities. They will need a breakfast food cooker that can also cook sausage, fry bacon, and make scrambled eggs. A toaster that only makes toast will soon be obsolete. If we don’t look to the future, we will have to completely redesign the toaster in just a few years.”

“With this in mind, we can formulate a more intelligent solution to the problem. First, create a class of breakfast foods. Specialize this class into subclasses: grains, pork, and poultry. The specialization process should be repeated with grains divided into toast, muffins, pancakes, and waffles; pork divided into sausage, links, and bacon; and poultry divided into scrambled eggs, hard- boiled eggs, poached eggs, fried eggs, and various omelette classes.”

“The ham and cheese omelette class is worth special attention because it must inherit characteristics from the pork, dairy, and poultry classes. Thus, we see that the problem cannot be properly solved without multiple inheritance. At run time, the program must create
the proper object and send a message to the object that says, ‘Cook yourself.’ The semantics of this message depend, of course, on the kind of object, so they have a different meaning to a piece of toast than to scrambled eggs.”

“Reviewing the process so far, we see that the analysis phase has revealed that the primary requirement is to cook any kind of breakfast food. In the design phase, we have discovered some derived requirements. Specifically, we need an object-oriented language with multiple inheritance. Of course, users don’t want the eggs to get
cold while the bacon is frying, so concurrent processing is
required, too.”

“We must not forget the user interface. The lever that lowers the food lacks versatility, and the darkness knob is confusing. Users won’t buy the product unless it has a user-friendly, graphical interface. When the breakfast cooker is plugged in, users should see a cowboy boot on the screen. Users click on it, and the message ‘Booting UNIX v.8.3’ appears on the screen. (UNIX 8.3 should be out by the time the product gets to the market.) Users can pull down a menu and click on the foods they want to cook.”

“Having made the wise decision of specifying the software first in the design phase, all that remains is to pick an adequate hardware platform for the implementation phase. An Intel Pentium with 48MB
of memory, a 1.2GB hard disk, and a SVGA monitor should be sufficient. If you select a multitasking, object oriented language that supports multiple inheritance and has a built-in GUI, writing the program will be a snap.”

The king wisely had the software developer beheaded, and they all lived happily ever after.

 

Categories
Artificial Intelligence Hardware Programming What I’m Up To

One last endorsement for the ZGX Nano AI workstation

Today’s my last day in my role as the developer advocate for HP’s GB10-powered AI workstation, the ZGX Nano. As I’ve written before, I’m grateful to have had the the opportunity to talk about this amazing little machine.

Of course, you could expect me to talk about how good the ZGX Nano is; after all, I’m paid to do so — at least until 5 p.m. Eastern today. But what if a notable AI expert also sang its praises?

That notable expert is Sebastian Raschka (pictured above), author of a book I’m working my way through right now: Build a Large Language Model (from Scratch), and it’s quite good. He’s also working on a follow-up book, Build a Reasoning Model (from Scratch).

Sebastian has been experimenting on NVIDIA’s DGX Spark, which has the same specs as the ZGX Nano (as well as a few other similar small desktop computers built around the NVIDIA’s GB10 “superchip”), and he’s published his observations on his blog in a post titled DGX Spark and Mac Mini for Local PyTorch Development. He ran some benchmark AI programs comparing his Mac Mini M4 computer (a fine developer platform, by the bye) and the NVIDIA H100 GPU (and NVIDIA’s A100 GPU when an H100 wasn’t available), pictured below:

Keep in mind that the version of the H100 that comes with 80GB of VRAM sells for about $30,000, which is why most people don’t buy one, but instead rent time on it from server farms, typically at about $2/hour.

Let me begin from the end of Raschka’s article, where he writes his conclusions:

Overall, the DGX Spark seems to be a neat little workstation that can sit quietly next to a Mac Mini. It has a similarly small form factor, but with more GPU memory and of course (and importantly!) CUDA support.

I previously had a Lambda workstation with 4 GTX 1080Ti GPUs in 2018. I needed the machine for my research, but the noise and heat in my office was intolerable, which is why I had to eventually move the machine to a dedicated server room at UW-Madison. After that, I didn’t consider buying another GPU workstation but solely relied on cloud GPUs. (I would perhaps only consider it again if I moved into a house with a big basement and a walled-off spare room.) The DGX Spark, in contrast, is definitely quiet enough for office use. Even under full load it’s barely audible.

It also ships with software that makes remote use seamless and you can connect directly from a Mac without extra peripherals or SSH tunneling. That’s a huge plus for quick experiments throughout the day.

But, of course, it’s not a replacement for A100 or H100 GPUs when it comes to large-scale training.
I see it more as a development and prototyping system, which lets me offload experiments without overheating my Mac. I consider it as an in-between machine that I can use for smaller runs, and testing models in CUDA, before running them on cloud GPUs.

In short: If you don’t expect miracles or full A100/H100-level performance, the DGX Spark is a nice machine for local inference and small-scale fine-tuning at home.

You might as well replace “DGX Spark” in his article with “ZGX Nano” — the hardware specs are the same. The ZGX Nano shines with HP’s exclusive ZGX Toolkit, a Visual Studio Code extension that lets you configure, manage, and deploy to the ZGX Nano. This lets you use your favorite development machine and coding environment to write code, and then use the ZGX Nano as a companion device / on-premises server.

The article features graphs showing his benchmarking results…

In his first set of benchmarks, he took a home-built 600 million parameter LLM — the kind that you learn how to build in his book, Build a Large Language Model (from Scratch) — and ran it on his Mac Mini M4, the ZGX Nano’s twin cousin, and an H100 from a cloud provider. From his observations, you can conclude that:

  • With smaller models, the ZGX Nano can match a Mac Mini M4. Both can crunch about 45 tokens per second with 20 billion parameter m0dels.
  • The ZGX Nano has the advantage of coming with 128GB  of VRAM, meaning that it can handle larger models than the MacMini could, as it’s limited by memory.

Raschka’s second set of benchmarks tested how the Mac Mini, the ZGX Nano’s twin cousin, and the H100 handle two variants of a model that have been presented with MATH-500, a collection of 500 mathematical word problems:

  • The base variant, which was a standard LLM that gives short, direct answers
  • The reasoning variant, which was a version of the base model that was modified to “think out loud” through problems step-by-step

He ran two versions of this benchmark. The first was the sequential test, where the model was presented on MATH-500 question at a time. From the results, you can expect the ZGX Nano to perform almost as well as the H100, but at a significantly smaller fraction of the cost! It also runs circles around the Mac Mini.

In the second version of the benchmark, the batch test, the model was served 128 questions at the same time, to simulate serving multiple users at once and to. test memory bandwidth and parallel processing.

This is a situation where the H100 would vastly outperform the ZGX Nano thanks to the H100’s much better memory bandwidth. However, the ZGX Nano isn’t for doing inference at production scale; it’s for developers to try out their ideas on a system that’s powerful enough to get a better sense of how they’d operate in the real world, and do so affordably.

Finally, with the third benchmark, Rashcka trained and fine-tuned a model. Note that this time, the data center GPU was the A100 instead of the H100 due to availability.

This benchmark tests training and fine-tuning performance. It compares how fast you can modify and improve an AI model on the Mac Mini M4 vs. the ZGX Nano’s twin vs. an A100 GPU. He presents three scenarios in training and fine-tuning a 355 million parameter model:

  1. Pre-training (3a in the graphs above): Training a model from scratch on raw text
  2. SFT, or Supervised fine-tuning (3b): Teaching an existing model to follow instructions
  3. DPO (direct preference optimization), or preference Tuning (3c): Teaching the model which responses are “better” using preference data

All these benchmarks say what I’ve been saying: the ZGX Nano lets you do real model training locally and economically. You get a lot of bang for your ZGX Nano buck.

As with a lot of development workflows, where there’s a development database and a production database, you don’t need production scale for every experiment. The ZGX Nano gives you a working local training environment that isn’t glacially slow or massively expensive.

Want to know more? Go straight to the source and check out Raschka’s article, DGX Spark and Mac Mini for Local PyTorch Development.

And with this article, I end my stint as the “spokesmodel” for the ZGX Nano. It’s not the end of my work in AI; just the end of this particular phase.

Keep watching this blog, as well as the Global Nerdy YouTube channel, for more!

Categories
Artificial Intelligence Editorial Programming

My AI technique, captured in a single social media post (with one exception)

Screen capture: A tweet by Yuchen Jin (@Yuchenj_UW), which reads “I saw a guy coding today. Tab 1 ChatGPT. Tab 2 Gemini. Tab 3 Claude. Tab 4 Grok. Tab 5 DeepSeek. He asked every AI the same exact question. Patiently waited, then pasted each response into 5 different Python files. Hit run on all five. Pick the best one. Like a psychopath. It's me.” My additional caption below reads “I do this, too — but with the excpetion of Grok, which I think of as ‘ChatKKK.’”

Here’s Yuchen Jin’s original tweet.

Categories
Conferences Programming What I’m Up To

Slides from my upcoming Ren’Py presentation for KCDC 2025

A couple of months back, I wrote that one of my proposed talks was accepted for this year’s edition of KCDC — Kansas City Developer Conference, which takes place from August 13th through 15th (Wednesday, August 13 is the workshop day, while the conference days are Thursday and Friday, August 14 and 15).

KCDC draws 2000+ attendees each year and features tracks for the following topics:

  • Architecture
  • AI and Data Science
  • Cloud
  • Data
  • DevOps
  • Human Skills
  • Java
  • JavaScript
  • Methodologies and Process Management
  • .NET
  • Other Technologies
  • Security
  • Testing and QA
  • UI/UX and Design

My talk’s title is The Best, Most Fun Python Platform You’ve Never Heard Of. It’s a programmer’s introduction to the powerful, fun, and all-too-often-ignored Ren’Py. While Ren’Py is called a “visual novel engine,” I prefer to think of it as the fastest, most fun way to create Python applications.

I’ve been working on my talk for the past little while, and I thought I’d share the first couple of slides from my presentation. I may update them between now and mid-August, but if you’re curious, it should give you a sense of what my presentation will be like.

Here’s the description for my talk:

Python’s occupied the number one spot on the TIOBE Programming Community Index for the past couple of years, and it’s the preferred programming language in for AI and data science. Perhaps you’ve been thinking about learning it, but the thought of having to do another set of “Hello World” style exercises is filling you with dread. Is there a more fun way to get up to speed with Python?

Yes, there is, and it’s called Ren’Py. It’s billed as a visual novel engine and often used for writing dating simulation games, but it’s so much more than that. It’s a platform that lets you code in Python (and more) and deploy to desktop, web, and even mobile platforms, and with a fraction of the effort required by React, Vue, or Angular. It’s a fun framework that’s been used to produce games you can find on Steam, but it’s got applications well beyond amusement.

In this session, we’ll look not just at the basics of Ren’Py development, but the building of a dating game based on KFC’s official game, “I Love You Colonel Sanders,” a simple turn-based combat game starring Florida Man, and building mobile apps in a way that’s less frustrating than usual.

I’m thinking about doing a dry run of my presentation here in Tampa — and for free! — at a Tampa Bay Python meetup in early August. Watch this space (or my LinkedIn account) for the announcement.

Would you like to get the anime template that I used for my slides? You can get it from SlidesGo for free — it’s called Lovely Chibis Anime Characters for Marketing!

Categories
Artificial Intelligence Meetups Programming

The code for the Tampa Bay AI Meetup’s “AI job application helper app” is now online!

Back in mid-March, the Tampa Bay AI Meetup hosted a session at Embarc Collective called Build an AI job application helper app, where we did just that: we built an application that helps you apply for jobs.

I’ve since refined the app and posted it on GitHub, where you can download it and try it out for yourself.

According to the Silicon Valley-based career guidance service Pathrise, job seekers who sent 20+ job applications every week got more interviews and landed a job sooner.

That’s a lot of work, especially since the general advice is to customize your résumé for every job application, and then write a cover letter too. This app makes it easier to take on this big task by taking your résumé and the description of the job you’re applying for, then uses an LLM to generate a résumé and cover letter optimized for that job application.

The app is written in Python and uses Jupyter Notebook as a platform. I wrote this as a Jupyter Notebook rather than a regular command-line Python app because Jupyter Notebooks also allow me to mix explanatory documentation with my code:

Give it a try! You can either clone the GitHub repo for this application, or simply download a .zip file containing all its files.

Categories
Artificial Intelligence Meetups Programming

Wednesday, June 18: Intro to AI agents with MCP!

At 6 p.m. on Wednesday, June 18 at Embarc Collective, I’ll be presenting Intro to AI Agents with MCP, which will be a joint gathering of Tampa Bay Artificial Intelligence Meetup and Tampa Bay Python!

LLMs like ChatGPT, Claude, Gemini, DeepSeek, and others are great for taking in natural language questions and producing complex but useful natural language replies.

However, they can’t do anything except output text. without the help of additional code. Until recently, the way to connect LLMs to other systems was to develop custom code for each LLM and each online system it connects to, which is an “m by n” problem.

One solution is MCP, short for “Model Context Protocol.” Introduced to world by Anthropic not too long ago, MCP is an open source, open standard that gives AI models connection to external data sources and tools. You could describe MCP as “a universal API for AIs to interact with online services.”

We’ll explain what it is, why it was made and how it came about, and then show you actual working code by building a simple MCP server connected to an LLM. Joey will demonstrate a couple of examples of MCP in action, and they’ll be examples that you can take home and experiment with!

Bring your laptop — you’ll have the opportunity to try out the MCP demos for yourself!

And yes, there’ll be food, and water and soft drinks will be provided. If that doesn’t work for you, feel free to bring your own.

Want to register (it’s free)? You can do so at either of the following Meetup pages: