<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Alex's Adventures on the Infobahn - chatgpt</title><link href="https://www.bennee.com/~alex/" rel="alternate"></link><link href="https://www.bennee.com/~alex/blog/tag/chatgpt/feed" rel="self"></link><id>https://www.bennee.com/~alex/</id><updated>2023-12-10T19:28:00+00:00</updated><subtitle>the wanderings of a supposed digital native</subtitle><entry><title>A Systems Programmer's Perspectives on Generative AI</title><link href="https://www.bennee.com/~alex/blog/2023/12/10/a-systems-programmers-perspectives-on-generative-ai/" rel="alternate"></link><published>2023-12-10T19:28:00+00:00</published><updated>2023-12-10T19:28:00+00:00</updated><author><name>alex</name></author><id>tag:www.bennee.com,2023-12-10:/~alex/blog/2023/12/10/a-systems-programmers-perspectives-on-generative-ai/</id><summary type="html">&lt;p&gt;Alex discusses his experience playing with the current crop of large language models and muses on the power of processors multiplying lots of numbers together.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Like many people over the last few months I've been playing with a number of Large Language Models (LLMs). LLMs are
perhaps best typified by the current media star ChatGPT. It is hard to avoid the current media buzz while every tech
titan is developing their "AI" play and people are exposed to tools where the label of Artificial Intelligence is
liberally applied. The ability of these models to spit out &lt;a href="https://www.bennee.com/~alex/blog/2023/10/22/comparing-forge-based-and-email-based-workflow-for-open-source-projects/"&gt;competent comprehensible
text&lt;/a&gt; is seemingly a step change in ability compared to previous generations of tech.&lt;/p&gt;
&lt;p&gt;I thought I would try and collect some of my thoughts and perspectives on this from the point of view of a &lt;a href="https://en.wikipedia.org/wiki/Systems_programming" title="link to wikipedia definition"&gt;systems
programmer&lt;/a&gt;. For those not familiar
with the term is refers to the low level development of providing platforms for the applications people actually use. In
my case a lot of the work I do on &lt;a href="https://www.qemu.org" title="link to QEMU homepage"&gt;QEMU&lt;/a&gt; which involves emulating the very
lowest level instructions a computer can do: the simple arithmetic and comparison of numbers that all code is eventually
expressed as.&lt;/p&gt;
&lt;h1&gt;Magic numbers and computing them&lt;/h1&gt;
&lt;p&gt;I claim no particular expertise on machine learning so expect this to be a very superficial explanation of whats going
on.&lt;/p&gt;
&lt;p&gt;In normal code the CPU tends to execute a lot of different instruction sequences as a program runs through solving the
problem you have set it. The code that calculates where to draw your window will be different to the code checking the
network for new data, or the logic that stores information safely on your file system. Each of those tasks is decomposed
and abstracted into simpler and simpler steps until eventually it is simple arithmetic dictating what the processor
should do do next. You occasionally see hot spots where a particular sequence of instructions are doing a lot of heavy
lifting. There is a whole discipline devoted to managing computational complexity and ensuring algorithms are as
efficient as possible.&lt;/p&gt;
&lt;p&gt;However the various technologies that are currently wowing the world work very differently. They are models of various
networks represented by a series of magic numbers or "weights" arranged in a hierarchical structure of interconnected
&lt;a href="https://en.wikipedia.org/wiki/Matrix_(mathematics)"&gt;matrices&lt;/a&gt;. While there is a lot of nuance to how problems are
encoded and fed into these models fundamentally the core piece of computation is multiplying a bunch of numbers with
another bunch of numbers feeding their results into the next layer of the network. At the end of the process the model
spits out a prediction of the most likely next word is going to be. After selecting one the cycle repeats taking to
account our expanded context to predict the most likely next word.&lt;/p&gt;
&lt;p&gt;The "models" that drive these things are described mostly by the number of parameters they have. This encompasses the
number of inputs and outputs they have and the number of numbers in between. For example common small open source models
start at 3 billion parameters with 7, 13 and 34 billion also being popular sizes. Beyond that it starts getting hard to
run models locally on all but the most tricked out desktop PCs. As a developer my desktop is pretty beefy (32 cores,
64Gb RAM) and can chew through computationally expensive builds pretty easily. However as I can't off-load processing
onto my GPU a decent sized model will chug out a few words a second while maxing out my CPU. The ChatGPT v4 model is
speculated to run about 1.7 trillion parameters which needs to be run on expensive cloud hardware - I certainly don't
envy &lt;a href="https://openai.com/"&gt;OpenAI&lt;/a&gt; their infrastructure bill.&lt;/p&gt;
&lt;p&gt;Of course the computational power needed to run these models is a mere fraction of what it took to train them. In fact
the bandwidth and processing requirements are so large it pays to develop custom silicon that is really good at
multiplying large amounts of numbers and not much else. You can get a lot more bang for your buck compared to running
those calculations on a general purpose CPU designed for tackling a wide range of computation problems.&lt;/p&gt;
&lt;h1&gt;The Value of Numbers&lt;/h1&gt;
&lt;p&gt;Because of the massive investment in synthesising these magic numbers they themselves become worth something. The "magic
sauce" behind a model is more about how it was trained and what data was used to do it. We already know its possible to
encode societies biases into models due to sloppy selection of the input data. One of the principle criticisms of
proprietary generative models is how opaque the training methods are making it hard to judge their safety. The degree to
which models may regurgitate data without any transformation is hard to quantify when you don't know what went into it.&lt;/p&gt;
&lt;p&gt;As I'm fundamentally more interested in knowing how the technology I use works under the hood its fortunate there is a
growing open source community working on building their own models. Credit should be given to Meta who made their
language model &lt;a href="https://ai.meta.com/llama/" title="link to Meta's Llama page"&gt;LLaMA 2&lt;/a&gt; freely available on fairly permissive
terms. Since then there has been an explosion of open source projects that can run the models (e.g:
&lt;a href="https://github.com/ggerganov/llama.cpp" title="link to the llama.cpp project for running CPU bound models"&gt;llama.cpp&lt;/a&gt;,
&lt;a href="https://ollama.ai/" title="link to Ollama, another tool for locally running models"&gt;Ollama&lt;/a&gt;) and provide front-ends (e.g:
&lt;a href="https://github.com/oobabooga/text-generation-webui" title="link to Oobabooga's text generation UI"&gt;Oobabooga's text generation UI&lt;/a&gt;, &lt;a href="https://github.com/s-kostyaev/ellama" title="link to the Ellama github page"&gt;Ellama front-end for Emacs&lt;/a&gt;) for them.&lt;/p&gt;
&lt;h1&gt;Smaller Magic Numbers&lt;/h1&gt;
&lt;p&gt;The principle place where this work is going on is &lt;a href="https://huggingface.co/" title="link to the Hugging Face website"&gt;Hugging Face&lt;/a&gt;. Think of it as the &lt;a href="https://github.com" title="GitHub"&gt;GitHub&lt;/a&gt; of the machine learning community. It provides an
environment for publishing and collaborating on data sets and models as well hosting and testing their effectiveness in
various benchmarks. This make experimenting with models accessible to developers who aren't part of the well funded
research divisions of the various tech titans. Datasets for example come with
&lt;a href="https://huggingface.co/docs/hub/datasets-cards"&gt;cards&lt;/a&gt; which describe the sources that went into these multi-terabyte
files.&lt;/p&gt;
&lt;p&gt;One example of a such is the &lt;a href="https://huggingface.co/datasets/togethercomputer/RedPajama-Data-1T" title="link to the RedPajama dataset"&gt;RedPajama dataset&lt;/a&gt;. This is an open source initiative to recreate the LLaMA training data which combines
data from the open web and well as numerous permissively licensed source such as Wikipedia, GitHub, StackExchange and
ArXiv. This dataset has been used to train models like &lt;a href="https://huggingface.co/openlm-research" title="link to OpenLM research Hugging Face pages"&gt;OpenLLaMA&lt;/a&gt; in an attempt to provide an unencumbered version of Meta's LLaMA 2. However
training up these foundational models is an expensive and time consuming task, the real action is taking these models
and then fine tuning them for particular tasks.&lt;/p&gt;
&lt;p&gt;To fine tune a model you first take a general purpose model and further train it against data with a specific task in
mind. The purpose of this is not only to make your new model better suited for a particular task but also to optimise
the number of calculations that model has to do to achieve acceptable results. This is also where the style of prompting
will be set as you feed the model examples of the sort of questions and answers you want it to give.&lt;/p&gt;
&lt;p&gt;The are further stages that be applied including "alignment" where you ensure results are broadly in tune with the
values of the organisation. This is the reason the various chatbots around won't readily cough up the recipe to build
nukes or make it easier to explicitly break the law. This can be augmented with Reinforcement Learning through Human
Feedback (RHLF) which is practically the purpose of every &lt;a href="https://en.wikipedia.org/wiki/CAPTCHA"&gt;CAPTCHA&lt;/a&gt; you'll have
filled in over the last 25 years online.&lt;/p&gt;
&lt;p&gt;Finally the model can be quantised to make it more manageable. This takes advantage of the fact that a lot of the
numbers will be have a negligible effect on the result for a wide range of inputs. In those cases there is no point
storing them at full precision. As computation is a function of the number of bits of information being processed this
also reduces the cost of computation. While phones and other devices are increasingly including dedicated hardware to
process these models they are still constrained by physics - and the more you process the more heat you need to
dissipate, the more battery you use and the more bandwidth you consume. Obviously the more aggressively you quantise the
models the worse it will perform so there is an engineering trade off to make. Phones work best with multiple highly
tuned models solving specific tasks as efficiently as possible. Fully flexible models giving a
&lt;a href="https://en.wikipedia.org/wiki/J.A.R.V.I.S."&gt;J.A.R.V.I.S&lt;/a&gt; like experience will probably always need to run in the cloud
where thermal management is simply an exercise in plumbing.&lt;/p&gt;
&lt;h1&gt;Making magic numbers work for you&lt;/h1&gt;
&lt;p&gt;Before we discuss using models I want to discuss 3 more concepts: "prompts", "context" and "hallucinations".&lt;/p&gt;
&lt;p&gt;The prompt is the closest thing there is to "programming" the model. The prompt can be purely explicit or include other
inputs behind the scenes. For example the prompt can instruct the model to be friendly or terse, decorate code snippets
with markdown, make changes as diffs or in full functions. Generally the more explicit your prompt is about what you
want the better the result you get from the model. &lt;a href="https://en.wikipedia.org/wiki/Prompt_engineering"&gt;Prompt
engineering&lt;/a&gt; has the potential to be one of those newly created job
titles that will have to replace the jobs obsoleted by advancing AI. One of the ways to embed AI APIs into your app is
to create a task specific prompt that will be put in front of user input that guides the results to what you want.&lt;/p&gt;
&lt;p&gt;The "context" is the rest of the input into the model. That could be the current conversation in a chat or the current
page of source code in a code editor. The larger the context the more reference the model has for its answer although
that does come at the cost of even more computation as the context makes for more input parameters into the model.&lt;/p&gt;
&lt;p&gt;In a strong candidate for 2023's word of the year "hallucination" describes the quirky and sometime unsettling behaviour
of models outputting weird sometimes contradictory information. They will sincerely and confidently answer questions
with blatant lies or start &lt;a href="https://www.theregister.com/2023/12/01/chatgpt_poetry_ai/"&gt;regurgitating training data&lt;/a&gt; when
given certain prompts. It is a salient reminder that the statistical nature of these generative models will mean they
occasionally spout complete rubbish. They are also very prone to following the lead of their users - the longer you chat
with a model the more likely it is to end up agreeing with you.&lt;/p&gt;
&lt;p&gt;So lets talk about what these models can and can't do. As a developer one of the areas I'm most interested in is their
ability to write code. Systems code especially is an exercise in precisely instructing a computer what to do in explicit
situations. I'd confidently predicted my job would be one of the last to succumb to the advance of AI as systems aren't
something you can get "mostly" right. It was quite a shock when I first saw quite how sophisticated the generated code
can be.&lt;/p&gt;
&lt;h2&gt;Code Review&lt;/h2&gt;
&lt;p&gt;One of the first things I asked ChatGPT to do was review a function I'd written. It manged to make 6 observations about
the code, 3 of which where actual logic problems I'd missed and 3 where general points about variable naming and
comments. The prompt is pretty important though. If not constrained to point out actual problems LLMs tend to have a
tendency to spit out rather generic advice about writing clean well commented code.&lt;/p&gt;
&lt;p&gt;They can be super useful when working with an unfamiliar language or framework. If you are having trouble getting
something to work it might be faster to ask an LLM how to fix your function that spending time reading multiple
&lt;a href="https://stackoverflow.com/"&gt;StackOverflow&lt;/a&gt; answers to figure out what you've misunderstood. If compiler errors are
confusing supplying the message alongside the code can often be helpful in understanding whats going on.&lt;/p&gt;
&lt;h2&gt;Writing Code&lt;/h2&gt;
&lt;p&gt;However rather than just suggesting changes one very tempting use case is writing code from scratch based on a
description of what you want. Here the context is very important, the more detail you provide the better chance of
generating something useful. My experience has been that the solutions are usually fairly rudimentary and can often
benefit from a manual polishing step once you have something working.&lt;/p&gt;
&lt;p&gt;For my &lt;a href="https://www.bennee.com/~alex/presentations/kvm23-qemu-keynote.html"&gt;QEMU KVM Forum 2023 Keynote&lt;/a&gt; I got ChatGPT
to write the first draft of a number of my data processing scripts. However it missed obvious optimisations by
repeatedly reading values inside inner loops that made the scripts slower than they needed to be.&lt;/p&gt;
&lt;p&gt;If the task is a straight transformation they are very good. Ask an LLM to convert a function in one language into
another and it will do a pretty good job - and probably with less mistakes than your first attempt. However there are
limitations. For example I asked a model to convert some Aarch64 assembler into the equivalent 32 bit Arm assembler. It
did a very good job of the mechanical part of that but missed the subtle differences in how to setup the MMU. This
resulted in code which compiled but didn't work until debugged by a human who was paying close attention to the
architecture documentation as they went.&lt;/p&gt;
&lt;p&gt;One of the jobs LLM's are very well suited for is writing code that matches an existing template. For example if you are
mechanically transforming a bunch of enums into a function to convert them to strings you need only do a few examples
before there is enough context for the LLM to reliably figure out what you are doing. LLM's are a lot more powerful than
a simple template expansion because you don't need to explicitly define a template first. The same is true of tasks like
generating test fixtures for your code.&lt;/p&gt;
&lt;p&gt;There is a potential trap however with using LLMs to write code. As there is no source code and the proprietary models
are fairly cagey about exactly what data the models where trained on there are worries about them committing copyright
infringement. There are active debates ongoing in the open source community (e.g. &lt;a href="https://lists.gnu.org/archive/html/qemu-devel/2023-11/msg05007.html" title="link to archive of discussion about LLM code generation"&gt;on
qemu-devel&lt;/a&gt;) about the potential ramifications of a model regurgitating its training data. Without clarity on what
license that data has there is a risk of contaminating projects with code of an unknown province. While I'm sure these
issues will be resolved in time it's certainly a problem you need to be cognisant off.&lt;/p&gt;
&lt;h2&gt;Prose&lt;/h2&gt;
&lt;p&gt;Writing prose is a much more natural problem territory for LLM's and an area where low-effort text generation will be
rapidly replaced by generative models like ChatGPT. "My" previous &lt;a href="https://www.bennee.com/~alex/blog/2023/10/22/comparing-forge-based-and-email-based-workflow-for-open-source-projects/#comparing-forge-based-and-email-based-workflow-for-open-source-projects"&gt;blog
post&lt;/a&gt;
was mostly written by a ChatGPT based on a simple brief and a few requests for rewrites in a chat session. While it made
the process fairly quick the result comes across as a little bland and "off". I find there is a tendency for LLM's to
fall back on fairly obvious generalisations and erase any unique authorial voice there may have been.&lt;/p&gt;
&lt;p&gt;However if you give enough structure its very easy to get an LLM to expand on a bullet list into more flowery prose.
They are more powerful when being fed a large piece of text and asked to summarise key information in a more accessible
way.&lt;/p&gt;
&lt;p&gt;They are certainly an easy way to give a first pass review of your writing although I try to re-phrase things myself
rather than accept suggestions verbatim to keep my voice coming through the text.&lt;/p&gt;
&lt;h1&gt;Final Thoughts&lt;/h1&gt;
&lt;p&gt;The recent advances in LLM's and the public's exposure to popular tools like ChatGPT have certainly propelled the topic
of AI in the zeitgeist. While we are almost certainly approaching the "Peak of Inflated Expectations" stage of the &lt;a href="https://en.wikipedia.org/wiki/Gartner_hype_cycle"&gt;hype
cycle&lt;/a&gt; they will undoubtedly be an important step on the road to the
eventual goal of &lt;a href="https://en.wikipedia.org/wiki/Artificial_general_intelligence"&gt;Artificial General Intelligence (AGI)&lt;/a&gt;.
We are still a long way from being able to ask computers to solve complex problems they way they can in for example in
Star Trek. However in their current form they will certainly have a big impact on the way we work over the next decade
or so.&lt;/p&gt;
&lt;p&gt;It's important as a society we learn about how they are built, what their limitations are and understand the
computational cost and resultant impact on the environment. It will be awhile before I'd want to trust a set of magic
numbers over a carefully developed algorithm to actuate the control surfaces on a plane I'm flying on. However they are
already well placed to help us learn new information through interactive questioning and summarising random information
on the internet. We must learn to recognise when we've gone down hallucinatory rabbit hole and verify what we've learned
with reference to trusted sources.&lt;/p&gt;</content><category term="geek"></category><category term="ai"></category><category term="llms"></category><category term="systems"></category><category term="programming"></category><category term="chatgpt"></category><category term="qemu"></category><category term="open source"></category></entry><entry><title>Comparing Forge-Based and Email-Based Workflow for Open Source Projects</title><link href="https://www.bennee.com/~alex/blog/2023/10/22/comparing-forge-based-and-email-based-workflow-for-open-source-projects/" rel="alternate"></link><published>2023-10-22T12:22:00+01:00</published><updated>2023-10-22T12:22:00+01:00</updated><author><name>chatgpt</name></author><id>tag:www.bennee.com,2023-10-22:/~alex/blog/2023/10/22/comparing-forge-based-and-email-based-workflow-for-open-source-projects/</id><summary type="html">&lt;p&gt;Comparing Forge-Based and Email-Based Workflow for Open Source Projects&lt;/p&gt;</summary><content type="html">&lt;p&gt;In the open source technology universe, how teams coordinate,
collaborate and contribute is determined by the workflow they opt for.
At a high level, workflows can fall into one of two camps: Forge-based
or Email-based workflows. Forge-based workflows gained popularity with
platforms such as GitHub and GitLab, while Email-based workflows have
been a stalwart mechanism for open source software development with
mailing list platforms like GNU Mailman and SourceHut.&lt;/p&gt;
&lt;p&gt;In this post, we will look at the benefits and drawbacks of the
various approaches, hopefully lending insight to what will work best
for your project.&lt;/p&gt;
&lt;h2&gt;Forge-Based Workflow&lt;/h2&gt;
&lt;p&gt;Forge-based workflows have revolutionised open source software
development. Various advantages have made it an accessible choice for
many, including:&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;1. User-Friendly&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Forge-based platforms such as GitHub or GitLab feature a friendly GUI
and offer excellent documentation, making it super easy for beginners
to contribute to open source projects without needing an in-depth
understanding of git and email tools.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;2. Centralised and Organised&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;These platforms provide central repositories that make project
management streamlined. Access controls, issue tracking, continuous
integration, and other tools all exist in one place.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;3. Collaborative Environment&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;The pull-request model common to forge platforms encourages
collaborative code review, making it an excellent tool for open-source
projects where code quality is a priority.&lt;/p&gt;
&lt;p&gt;However, there's a flip side to this coin:&lt;/p&gt;
&lt;h4&gt;Cons: Risk of Vendor Lock-in&lt;/h4&gt;
&lt;p&gt;Choosing a specific forge platform means accepting their choices of
features, tools, standard practices, and policies which subtly enforce
vendor lock-in. For most open source projects this also means relying
on the forge supporting projects with cost free access to features and
CI time.&lt;/p&gt;
&lt;h2&gt;Email-Based Workflow&lt;/h2&gt;
&lt;p&gt;Despite being considered 'old school', email-based workflows still
have merit in today's software development world. They offer:&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;1. Decentralized and Flexible&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;In sharp contrast to forge-based workflows, email workflows are
inherently decentralized. This approach offers more flexibility for
contributors and maintainers alike, as they are not bound to tools
offered by a single platform.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;2. Line-by-Line Review and Inline Feedback&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Email-based workflows stand out when it comes to the review process.
The nature of emails allows for contributors and reviewers to break
down commits line-by-line. This allows for more granular attention to
detail, leading to clearer communication about specific code changes.
Additionally, the threading mechanism of emails allows for inline
commentary during reviews, making it easier for contributors to
respond and iterate on feedback. This approach can encourage deeper
understanding and discussion around code changes, leading to
well-reviewed and robust code contributions.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;3. Enhances git Understanding&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Contributors working with email-based workflows generally have a
better understanding of git because it requires more hands-on actions
when sharing code.&lt;/p&gt;
&lt;p&gt;However, they too have potential drawbacks.&lt;/p&gt;
&lt;h4&gt;Cons: Less Beginner-Friendly&lt;/h4&gt;
&lt;p&gt;Email-based workflows requires a steeper learning curve and are less
friendly for collaborative code reviewing, making it challenging for
new contributors to a project.&lt;/p&gt;
&lt;h1&gt;Adapting Open Source Projects: Email to Forge Workflow Transitions&lt;/h1&gt;
&lt;p&gt;Transitioning from an email-based workflow to a forge-based one should
be a meticulously planned process that respects the existing
community's culture and comfort. It's pivotal to keep this move as an
evolution rather than an abrupt change.&lt;/p&gt;
&lt;p&gt;Initial steps in such transitions can include moving non-code elements
to the forge platform. Functions such as issue tracking,
documentation, and discussions could be the first set of activities
transferred to the forge platform. This strategy allows the
contributors to become proficient with the platform’s tools and
interfaces while keeping the code contributions intact on email lists.&lt;/p&gt;
&lt;p&gt;Your project might encompass several sub-systems, and it could be
worth considering this while transitioning. Instead of transforming
the entire project at once, one could start by moving individual
sub-systems to the new workflow. This incremental, phased approach can
prevent chaos and reduce the chances of any significant disruption in
the project's flow.&lt;/p&gt;
&lt;p&gt;Following the sub-system shifts, the project should then introduce
acceptance of pull requests or merge requests created by maintainers.
These PRs should still contain code that underwent email list reviews
in the previous workflow, ensuring the robustness of code quality.&lt;/p&gt;
&lt;p&gt;The final stage of the transition is welcoming all contributors to
submit merge requests through the forge platform. The key is to ensure
that contributors understand the reasons behind the shift towards a
complete merge request approach. They should be given clear guidelines
about how and why to use merge requests, making them comfortable with
the transition, and empowering them to take full advantage of the
tool's capabilities.&lt;/p&gt;
&lt;p&gt;In transition, it's necessary to alleviate concerns, clarify intents,
and provide resources to learn and help the contributors adjust to the
new workflow. Both email and forge-based workflows hold their place
and value in open-source. So, when transiting, the project needs and
the contributor adaptability should be the cornerstone of your
strategy. No two projects are the same, and neither are their paths in
adopting new workflow models.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(Fuller disclosure: as
&lt;a href="https://chaos.social/@epilys/111280150345667417" title="comment spotting the chatgpt origins"&gt;@epilys&lt;/a&gt; noticed this post was generated via
chatgpt. I may have spent more time fiddling with my pelican settings
to make sure the author slug was properly shown than I did iterating
with GPT4 on the article. It has had some light copy-editing since to
clean up some copy and paste errors between iterations and some of the
more artificial phrasing it used)&lt;/em&gt;&lt;/p&gt;</content><category term="geek"></category><category term="email"></category><category term="workflow"></category><category term="git"></category><category term="gitlab"></category><category term="github"></category><category term="floss"></category><category term="development"></category><category term="chatgpt"></category></entry></feed>