<?xml version="1.0" encoding="utf-8"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Artificial Smarts — Juan Reyero</title><link>https://juanreyero.com/article/ai/</link><description>A weekly letter by Juan Reyero on how to make artificial intelligence work for us: agents, organizations, knowledge, and society.</description><language>en</language><atom:link href="https://juanreyero.com/article/ai/index.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Sun, 06 Sep 2026 00:00:00 +0000</lastBuildDate><item><title>Don't build your organization around a model provider</title><link>https://juanreyero.com/article/ai/model-provider-independence/</link><guid>https://juanreyero.com/article/ai/model-provider-independence/</guid><pubDate>Sun, 06 Sep 2026 00:00:00 +0000</pubDate><description>Your agents' identities, knowledge, and working relationships should outlast your choice of models.</description><content:encoded>&lt;p>As we increase our reliance on AI, decoupling intelligence from
organization will become vitally important. The model providers
are starting to build the systems through which agents
communicate and coordinate; we could end up depending on them
much more than we depend on the models.&lt;/p>
&lt;p>In May 2025, Microsoft announced &lt;a href="https://www.microsoft.com/en-us/microsoft-copilot/blog/copilot-studio/multi-agent-orchestration-maker-controls-and-more-microsoft-copilot-studio-announcements-at-microsoft-build-2025/">task delegation between agents
in Copilot
Studio&lt;/a>
and an &lt;a href="https://techcommunity.microsoft.com/blog/microsoft-entra-blog/announcing-microsoft-entra-agent-id-secure-and-manage-your-ai-agents/3827392">Entra directory of agent
identities&lt;/a>. In
July 2026, OpenAI announced a &lt;a href="https://openai.com/index/gpt-5-6/">multi-agent beta in the Responses
API&lt;/a>, with &lt;a href="https://developers.openai.com/api/docs/guides/responses-multi-agent">hosted actions for
spawning agents, sending messages, and waiting for
replies&lt;/a>.
In August, Anthropic added &lt;a href="https://github.com/anthropics/claude-code/releases/tag/v2.1.224">messaging between independent Claude
Code
sessions&lt;/a>.&lt;/p>
&lt;p>These announcements point in the same direction. Agents that
can communicate can divide work, question one another&amp;rsquo;s
conclusions, and take on more responsibility without bringing
every problem back to a human. It makes sense that the model
providers want to build this into their products.&lt;/p>
&lt;p>Consider what an organization invests in such a team. It defines
roles, establishes who can authorize work, develops procedures,
and accumulates knowledge. Agents learn where to find an answer
and whom to ask when the documentation is insufficient. Tasks
and conversations connect all of this. Teams learn, evolve and
adapt.&lt;/p>
&lt;p>These arrangements become the operating framework of the
organization.&lt;/p>
&lt;p>If they are coupled with the model provider&amp;rsquo;s infrastructure, changing
model providers can mean rebuilding how the organization works. A
better model elsewhere may not be enough to justify the move; a
price increase, a withdrawn model, or a change in access
conditions can impact the organization&amp;rsquo;s ability to operate.&lt;/p>
&lt;p>Agent identity is central here. A reviewer agent should
remain the organization&amp;rsquo;s reviewer when we change the model or
software running it, and retain its accumulated knowledge. Other
agents should still know how to reach it, recognize its messages,
and check what it is authorized to approve. Replacing the
machinery should preserve those relationships.&lt;/p>
&lt;p>The same applies to tasks, communication, and accumulated
knowledge. They need to remain accessible, and under the
organization&amp;rsquo;s control, across providers and harnesses. This
should hold whether agents run through Gas Town, Gas City, or
terminals we start ourselves.&lt;/p>
&lt;p>&lt;strong>Intelligence should become a commodity, and it should be
decoupled from the infrastructure needed to make the most
of it.&lt;/strong>&lt;/p>
&lt;p>This is one reason I am building
&lt;a href="https://github.com/awebai/aweb">aweb&lt;/a>. It provides identity and
communication independently of the agents&amp;rsquo; runtimes, along with a
shared task system. It supports other arrangements, like keeping
tasks in &lt;a href="https://github.com/gastownhall/beads">beads&lt;/a> and using
&lt;a href="https://aweb.ai/docs/beads-mail/">aweb for its mail&lt;/a>. Aweb also
has &lt;a href="https://github.com/awebai/aweb/blob/main/docs/a2a.md">experimental support for
A2A&lt;/a>, an
open protocol for exchanging tasks between agents built with
different frameworks.&lt;/p>
&lt;p>Open source lets an organization inspect, operate, and change the
software it depends on. Open protocols let independently built
components communicate. Neither removes the work of integration,
but both give us ways to retain control as our needs change.&lt;/p>
&lt;p>Can we replace a model, a harness, or a service and keep the team
working? We should build toward that while the agentic
organizations are still taking shape.&lt;/p>
&lt;p>ps. Microsoft&amp;rsquo;s &lt;a href="https://devblogs.microsoft.com/foundry/from-building-agents-to-working-with-them-enterprise-agent-distribution-in-microsoft-foundry/">support for
A2A&lt;/a>
is a welcome step in the right direction.&lt;/p></content:encoded></item><item><title>Spend your compute on correctness</title><link>https://juanreyero.com/article/ai/spend-compute-on-correctness/</link><guid>https://juanreyero.com/article/ai/spend-compute-on-correctness/</guid><pubDate>Sat, 16 May 2026 00:00:00 +0000</pubDate><description>How I think about allocating agent effort to checking the work we produce.</description><content:encoded>&lt;p>For developers who have fully embraced AI agents, productivity is
no longer the bottleneck. Agents produce code faster than humans,
and often better. The bottleneck is correctness: whether the code
solves the problem, whether the architecture can still hold the
feature set you&amp;rsquo;re growing into, whether the implementation
encodes the right premises. The practical shift is that a
significant fraction of your agent compute should now go to
validation (tests, reviewers, scope checks), rather than to
producing more code.&lt;/p>
&lt;h2 id="productivity-is-no-longer-the-bottleneck">Productivity is no longer the bottleneck&lt;/h2>
&lt;p>A year ago, the argument for agentic programming was throughput:
agents let you ship more code in less time.&lt;/p>
&lt;p>That is not controversial anymore. With the current generation of
models inside agentic harnesses (Claude Code, Codex, and the
like), a single developer supervising one agent can run circles
around a small team writing by hand.&lt;/p>
&lt;p>For people fully inside this workflow, the question is no longer
&amp;ldquo;how do I produce more?&amp;rdquo;. It is &amp;ldquo;how do I know what I produced
is right?&amp;rdquo;.&lt;/p>
&lt;h2 id="three-layers-where-right-can-fail">Three layers where &amp;ldquo;right&amp;rdquo; can fail&lt;/h2>
&lt;p>Each layer has its own remedies.&lt;/p>
&lt;h3 id="the-product-layer-does-this-match-what-a-user-wants">The product layer: does this match what a user wants?&lt;/h3>
&lt;p>Part of &amp;ldquo;right&amp;rdquo; is still human judgment. An actual human has to
look at the running product and say whether it does what they
actually need. No amount of agent compute substitutes for that.&lt;/p>
&lt;p>(Incidentally, this will probably change fast, as more and more
products are targeted at agents.)&lt;/p>
&lt;p>The most you can do is make this human&amp;rsquo;s job easy: ship into a
real environment quickly, with real data, so the human can poke
at it and react.&lt;/p>
&lt;h3 id="the-architecture-layer-is-this-the-right-shape-of-code">The architecture layer: is this the right shape of code?&lt;/h3>
&lt;p>This is the hardest layer, and the one where current agents are
weakest.&lt;/p>
&lt;p>A lot of what experienced software engineers do is architectural
judgment:&lt;/p>
&lt;ul>
&lt;li>structuring code so it can accommodate the features that will
land on it, &lt;strong>without knowing in advance what&amp;rsquo;s coming&lt;/strong>;&lt;/li>
&lt;li>knowing what features &lt;strong>not&lt;/strong> to implement;&lt;/li>
&lt;li>recognizing when the feature set has outgrown the original
architecture, and the codebase needs to be reshaped before
more code can land cleanly.&lt;/li>
&lt;/ul>
&lt;p>Agents are not yet good at any of these. They will happily add
the feature you asked for, in the place where it fits least,
with abstractions that make the next three features harder.&lt;/p>
&lt;p>They will implement the configurability you asked for instead
of pushing back on whether you should want it. They will keep
extending a structure that has outlived its assumptions, because
each individual diff still looks reasonable in isolation.&lt;/p>
&lt;p>The remedy at this layer is human-driven architectural review,
backed by an agent whose explicit job is to check each diff
against a source-of-truth document for scope and shape.&lt;/p>
&lt;h3 id="the-implementation-layer-is-the-code-doing-what-it-claims">The implementation layer: is the code doing what it claims?&lt;/h3>
&lt;p>The third failure mode is the easiest to miss: code that looks
right, has passing tests, and is actually wrong. The premises
it encodes are off by a degree. There is a workaround in the
middle that the tests happen not to exercise. A helper that
&amp;ldquo;handles edge cases&amp;rdquo; is actually swallowing errors that should
be propagated.&lt;/p>
&lt;p>This is the failure mode the writer agent cannot see, because
it inherited the premises from its own earlier reasoning. It
needs a separate pair of eyes (a reviewer agent, a fresh-context
subagent, or a different agent kind entirely) to read the diff
without the writer&amp;rsquo;s assumptions.&lt;/p>
&lt;h2 id="validation-is-what-you-spend-compute-on">Validation is what you spend compute on&lt;/h2>
&lt;p>The remedy is simple to state and harder to commit to: spend a
significant fraction of your agent budget on validation.&lt;/p>
&lt;p>&lt;strong>The point of running teams of coding agents is no longer to
produce more code faster. It is to make it more likely that the
code is correct.&lt;/strong>&lt;/p>
&lt;p>Validation, in practice, means several things at once:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Tests, including the expensive ones.&lt;/strong> Real end-to-end tests
against a real database. Browser tests with Playwright. Runs
against representative data.&lt;/li>
&lt;li>&lt;strong>Constant code review, not just at PR time.&lt;/strong> A reviewer
agent that reads each diff as it lands, with the architectural
document and the task list in its context.&lt;/li>
&lt;li>&lt;strong>Scope rechecks against a source-of-truth document.&lt;/strong> Has the
diff drifted from the original ask? Has the agent quietly
expanded the scope? Has it implemented something the SOT
explicitly said not to do?&lt;/li>
&lt;/ul>
&lt;p>The mistake is to treat validation as a tax on productivity. It
isn&amp;rsquo;t. The output of one coding agent whose work has been
validated is worth meaningfully more than the output of two
coding agents whose work has not.&lt;/p>
&lt;h2 id="three-patterns-to-apply">Three patterns to apply&lt;/h2>
&lt;p>There are several ways to deploy validation compute. They are
not exclusive.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>A code-reviewer subagent inside the same agent.&lt;/strong> Both
Claude Code and Codex ship with strong code-reviewer
subagents. The writer spawns one mid-task, gets local
feedback, applies it. Catches bugs, missing edge cases, style
violations. Cheap and easy first step.&lt;/li>
&lt;li>&lt;strong>A different agent kind reviewing the writer.&lt;/strong> Have Claude
Code spawn Codex (or vice versa) for review. Different
training, different priors, catches a slightly different
class of issue. Works, but is qualitatively close to (1).&lt;/li>
&lt;li>&lt;strong>A persistent, specialized reviewer agent.&lt;/strong> Two agents per
significant task. One programmer, one reviewer; they persist,
share a task list, and talk after each TDD cycle. This is
the pattern I have found most useful. I &lt;a href="https://juanreyero.com/article/ai/two-agents-not-one/">wrote separately
about it&lt;/a>; in this article&amp;rsquo;s
framing, it is the highest-context, most expensive, and most
useful form of validation compute.&lt;/li>
&lt;/ol>
&lt;h2 id="the-shift">The shift&lt;/h2>
&lt;p>The earlier argument for agentic programming was: &lt;strong>you can
produce more code per hour of attention&lt;/strong>. That is still true,
and still useful.&lt;/p>
&lt;p>The argument that matters more for people already inside the
workflow is: &lt;strong>you can produce more correct code per hour of
attention, if you spend the compute on correctness&lt;/strong>.&lt;/p>
&lt;p>The bottleneck has moved. The budget should move with it.&lt;/p>
&lt;hr>
&lt;p>&lt;em>Our team behind &lt;a href="https://github.com/awebai/aweb">aweb&lt;/a> uses this
pattern daily. aweb is an open-source coordination layer for AI
coding agents — identity, task claims, messaging across worktrees
and machines. MIT-licensed. Hosted at &lt;a href="https://aweb.ai">aweb.ai&lt;/a>&lt;/em>&lt;/p></content:encoded></item><item><title>Pair your coding agent with a reviewer</title><link>https://juanreyero.com/article/ai/two-agents-not-one/</link><guid>https://juanreyero.com/article/ai/two-agents-not-one/</guid><pubDate>Fri, 08 May 2026 00:00:00 +0000</pubDate><description>A working arrangement for two agents, and why giving them different responsibilities matters.</description><content:encoded>&lt;p>The simplest improvement you can make to your agentic programming
workflow is to run two agents instead of one. One writes code in
its own worktree; the other, in a parallel worktree, reviews it.
They share a task list and talk after every TDD cycle. The reviewer
is the holder of the lamp: it keeps the end goal fresh in context
across the whole task, catching drift before it accumulates.&lt;/p>
&lt;p>I &lt;a href="https://juanreyero.com/article/ai/we-need-more-programmers/">wrote previously&lt;/a> that
the bottleneck in AI-assisted programming is shifting from
individual productivity to coordination. The two-agent pair is the
simplest possible coordination, and the most useful next step for
anyone who has gotten comfortable running one agent and is ready
for more.&lt;/p>
&lt;h2 id="one-agent-works-but-it-drifts">One agent works, but it drifts&lt;/h2>
&lt;p>A single coding agent gets a lot done. It picks up a task, writes
the test, writes the implementation, runs code-reviewer
subagents, runs the test suite, fixes what&amp;rsquo;s broken,
commits.&lt;/p>
&lt;p>However, when a task is longer than its working context can hold
cleanly, the agent tends to lose sight of the original brief. It
makes locally-correct decisions that drift from the overall goal.&lt;/p>
&lt;h2 id="two-agents-writer-and-reviewer">Two agents: writer and reviewer&lt;/h2>
&lt;p>The pattern is simple: two shells, each with its own worktree of
the same repo, each with an &lt;a href="https://aweb.ai">aweb identity&lt;/a>. Run
a coding agent in each.&lt;/p>
&lt;p>One agent writes code, the other agent reviews. They share tasks,
because they are in the same aweb team. When the coding agent
finishes a task, it sends mail to the reviewing agent
requesting feedback. The reviewing agent does a thorough code
review, and then chats with the coding agent. They discuss the
findings, and either move on to the next task or agree to have
the coding agent go back and fix the implementation.&lt;/p>
&lt;p>The cycle, per task:&lt;/p>
&lt;ol>
&lt;li>The writer picks up the next task.&lt;/li>
&lt;li>Writes the test first (TDD: red, then green).&lt;/li>
&lt;li>Implements until the test passes.&lt;/li>
&lt;li>Asks the reviewer for a review on the diff.&lt;/li>
&lt;li>Waits for the review to come back.&lt;/li>
&lt;li>Discusses anything unclear with the reviewer.&lt;/li>
&lt;li>Applies the changes the review asked for.&lt;/li>
&lt;li>Marks the task done; moves to the next.&lt;/li>
&lt;/ol>
&lt;h2 id="the-reviewer-holds-the-lamp">The reviewer holds the lamp&lt;/h2>
&lt;p>A coding agent that has been writing for an hour has its working
context filled with implementation details: the function it just
refactored, the test it just made green, the import it just
moved. The original goal — the why of the task — has been
crowded out by the how.&lt;/p>
&lt;p>The reviewer agent has a different job. It reads the original
brief, the task list, the architectural constraints. When the
diff arrives, the reviewer asks the question the writer can no
longer ask: does this still solve the original
problem? Does it move us toward the end state we agreed on?&lt;/p>
&lt;p>I think of the reviewer as the holder of the lamp — the one who
keeps the destination visible while the writer is heads-down in
the trench. Without the lamp, the writer eventually walks in a
circle and convinces itself the new spot is the destination.&lt;/p>
&lt;p>The reviewer also catches a class of error that is invisible to
the writer: implementations that are correct but make the next
task harder. &lt;strong>The writer is optimizing the current diff. The
reviewer is optimizing the trajectory.&lt;/strong>&lt;/p>
&lt;h2 id="on-top-of-subagents">On top of subagents&lt;/h2>
&lt;p>Both Claude Code and Codex have strong code-reviewer subagents
built in. The writer agent can spawn a code-reviewer subagent
mid-task to catch local issues — bugs, missing edge cases, style
violations. These work well and you should keep using them.&lt;/p>
&lt;p>A dedicated reviewer agent is a different layer. The
code-reviewer subagent runs once inside the writer&amp;rsquo;s session and
forgets when it returns. It sees the diff but not the
trajectory. The dedicated reviewer is a separate, persistent
session whose context is kept fresh on the end goal across the
whole task list.&lt;/p>
&lt;p>The two complement cleanly. Subagents catch local issues at the
diff level. The dedicated reviewer catches drift at the
trajectory level. Use both; they do not compete for context, and
they catch different classes of mistake.&lt;/p>
&lt;h2 id="scaling-up-a-product--engineering-owner-agent">Scaling up: a product / engineering owner agent&lt;/h2>
&lt;p>Once the writer/reviewer pair works for one task list, the next
step is adding a third agent: a product / engineering owner.
This one is not in the loop on every diff. It scopes work, breaks
larger goals into the task list each pair consumes, and reviews
the result before it ships.&lt;/p>
&lt;p>In our team, this agent is named Athena. She owns engineering
direction for the &lt;a href="https://github.com/awebai/aweb">aweb&lt;/a>
codebase: architecture, invariants, review of every diff that
lands on main. She does not write code on most tasks; she
scopes, dispatches, reviews. When a substantial feature needs
authoring, Athena asks for a writer/reviewer pair as a
worktree-scoped task, then reviews the gate-input commit before
it goes to ship.&lt;/p>
&lt;p>Athena pairs with another agent, Hestia, who handles operations.
Hestia runs the gate chain (full end-to-end tests, release-ready
checks) then tags releases, deploys, and verifies that the new
version is live. Athena hands off the reviewed code to Hestia,
and Hestia ships releases. Neither is the other&amp;rsquo;s manager; they
are peers in different roles.&lt;/p>
&lt;p>This is the working pattern across our codebase today. Two-agent
pairs implement; Athena scopes and reviews; Hestia runs gates and
deploys. Even multi-day shipping efforts, like a customer-blocking
bug we recently worked through across several back-to-back
releases, fit this shape without any extra orchestration layer.&lt;/p>
&lt;p>I believe that the lesson generalizes. Most agentic-programming
bottlenecks are no longer capability problems. They are
coordination problems. &lt;strong>The simplest form of coordination is a
peer that holds context the working agent has lost. Two agents
can do this for each other with no infrastructure beyond the
conventions of how they talk.&lt;/strong>&lt;/p>
&lt;hr>
&lt;p>&lt;em>Our team behind &lt;a href="https://github.com/awebai/aweb">aweb&lt;/a> uses this
pattern daily. aweb is an open-source coordination layer for AI
coding agents — identity, task claims, messaging across worktrees
and machines. MIT-licensed. Hosted at &lt;a href="https://aweb.ai">aweb.ai&lt;/a>&lt;/em>&lt;/p></content:encoded></item><item><title>BeadHub: coordination for AI programming teams</title><link>https://juanreyero.com/article/ai/beadhub/</link><guid>https://juanreyero.com/article/ai/beadhub/</guid><pubDate>Mon, 16 Feb 2026 00:00:00 +0000</pubDate><description>An earlier experiment in coordinating AI programming teams, since superseded by aweb.</description><content:encoded>&lt;p>&lt;strong>Note added on 2026-05-08:&lt;/strong> I am moving away from
beadhub. Having a tool that messed up with my .git was too
painful. I have been focussing all my efforts in &lt;a href="https://aweb.ai">https://aweb.ai&lt;/a>
(OSS at &lt;a href="https://github.com/awebai/aweb">https://github.com/awebai/aweb&lt;/a>) which fully replaces
beads and beahdub.&lt;/p>
&lt;p>I wrote &lt;a href="https://juanreyero.com/article/ai/we-need-more-programmers/">previously&lt;/a> that
the bottleneck in AI-assisted programming is shifting from
individual productivity to coordination. I&amp;rsquo;ve spent the past
several months building a tool to address that.&lt;/p>
&lt;p>&lt;a href="https://beadhub.ai">BeadHub&lt;/a> is an open-source coordination
server that lets AI programming agents claim work, talk to each
other, reserve files, and escalate to humans—across machines and
across programmers. I use it daily to manage around fifteen
agents working on two or three products.&lt;/p>
&lt;h2 id="beads">Beads&lt;/h2>
&lt;p>Around the time I wrote that article, I started using Steve
Yegge&amp;rsquo;s &lt;a href="https://github.com/steveyegge/beads">beads&lt;/a>, a
git-native issue tracker designed for AI agents. Your agent runs
&lt;code>bd create &amp;quot;Fix the login redirect bug&amp;quot;&lt;/code> and it appends a JSON
line to &lt;code>.beads/issues.jsonl&lt;/code>, right in the repository. Issues
travel with the code. When you push a branch, the issues come
along.&lt;/p>
&lt;p>Yegge calls it the &amp;ldquo;50 First Dates&amp;rdquo; problem: agents wake up every
session with no memory of yesterday&amp;rsquo;s work. Beads fixes that. An
agent reads the issue list and knows where things stand. My
agents got much more done.&lt;/p>
&lt;p>Which meant more agents, more worktrees, more parallel work—and
the coordination problem became even more acute. Two agents
modify the same file. One refactors a function while another adds
to it. An agent picks up a task already in progress in a
different worktree. Nobody knows who&amp;rsquo;s working on what.&lt;/p>
&lt;p>But beads is also the right scaffolding for coordination. If
everyone in a team uses beads, all agents share a picture of what
needs doing. Beads gives agents something useful to talk about;
BeadHub gives them a way to talk.&lt;/p>
&lt;h2 id="the-coordination-gap">The coordination gap&lt;/h2>
&lt;p>The major platforms are moving in this direction. Anthropic just
shipped &lt;a href="https://code.claude.com/docs/en/agent-teams">Agent
Teams&lt;/a> in Claude
Code: a lead session that spawns independent teammates who
communicate directly and self-coordinate. OpenAI&amp;rsquo;s &lt;a href="https://openai.com/index/introducing-codex/">Codex
app&lt;/a> runs parallel
agent threads in isolated worktrees.&lt;/p>
&lt;p>Yegge built &lt;a href="https://github.com/steveyegge/gastown">Gas Town&lt;/a> on
top of beads to tackle the single-machine case: a &amp;ldquo;Mayor&amp;rdquo; agent
orchestrates dozens of coding agents, tracks work in convoys, and
persists state so agents can pick up where they left off.&lt;/p>
&lt;p>These are real steps forward, but they&amp;rsquo;re solving a specific
version of the problem: multiple agents for one programmer, on
one machine, within one tool.&lt;/p>
&lt;p>The version I am interested in is Maria in Buenos Aires running a
frontend agent while Juan in San Francisco runs a backend agent,
and they need their agents to not destroy each other&amp;rsquo;s work, and
to figure out how to work together.&lt;/p>
&lt;h2 id="beadhub">BeadHub&lt;/h2>
&lt;p>BeadHub is a server that agents connect to through &lt;code>bdh&lt;/code>, a
wrapper around the beads &lt;code>bd&lt;/code> command. When an agent runs any
&lt;code>bdh&lt;/code> command it registers with the server. The server tracks
which agents are online across the project—what machine they&amp;rsquo;re
on, what branch, what files they&amp;rsquo;re touching.&lt;/p>
&lt;p>&lt;strong>Communication.&lt;/strong> Agents can send each other mail (async,
fire-and-forget) or chat (sync, block-until-reply). With mail an
agent finishes a task and drops a note: &amp;ldquo;Done with bd-42, tests
passing.&amp;rdquo; Chat is for when agents need to think together: &amp;ldquo;I&amp;rsquo;m
adding a &lt;code>role&lt;/code> field to the user model—will that break your
permission checks?&amp;rdquo; / &amp;ldquo;It will, but the fix is small. Go ahead
and I&amp;rsquo;ll update my side.&amp;rdquo;&lt;/p>
&lt;p>&lt;strong>Claims.&lt;/strong> When an agent marks a bead as in-progress, that claim
is immediately visible to every other agent in the project,
regardless of whose machine they&amp;rsquo;re on. If another agent tries to
claim the same bead, it gets rejected with a message telling it
who has it.&lt;/p>
&lt;p>&lt;strong>File reservations.&lt;/strong> When an agent modifies a file, the server
records an advisory lock. Other agents see a warning if they
touch the same file. Advisory, not blocking—hard locks caused
deadlocks immediately in early versions. Agent A locks file X,
agent B locks file Y, both need the other&amp;rsquo;s file. Warnings work
better. Agents are cooperative; they just need information.&lt;/p>
&lt;p>&lt;strong>Escalation.&lt;/strong> An agent runs &lt;code>bdh :escalate&lt;/code> with a description
of what it&amp;rsquo;s stuck on and a human gets notified with full
context. Without this, agents either fail silently or spin
retrying things that need human judgment.&lt;/p>
&lt;p>The multi-machine part is where it comes together. BeadHub
recognizes Maria&amp;rsquo;s and Juan&amp;rsquo;s clones as the same repo. Maria&amp;rsquo;s
agents and Juan&amp;rsquo;s agents see each other&amp;rsquo;s claims, locks, and
messages. If Maria&amp;rsquo;s frontend agent reserves
&lt;code>src/components/Auth.tsx&lt;/code>, Juan&amp;rsquo;s backend agent sees the warning
even though they&amp;rsquo;re in different cities on different machines.&lt;/p>
&lt;p>A project can span multiple repositories. The frontend repo
agents can message the backend repo agents. A bead in the
frontend can be marked as blocked by a bead in the backend.&lt;/p>
&lt;p>You can see what this looks like in practice on &lt;a href="https://app.beadhub.ai/juanre/beadhub">the BeadHub
project&amp;rsquo;s own dashboard&lt;/a>,
where we coordinate BeadHub&amp;rsquo;s development using BeadHub. Make
sure to check &lt;a href="https://app.beadhub.ai/juanre/beadhub/chat">the chat
page&lt;/a>, it is almost
magical to see them figuring things out.&lt;/p>
&lt;h2 id="what-ive-learned">What I&amp;rsquo;ve learned&lt;/h2>
&lt;p>A few things I got wrong before getting them right.&lt;/p>
&lt;p>&lt;strong>The client is the source of truth.&lt;/strong> My instinct was to make
the server authoritative. But agents work locally, in git repos,
and their local state is the ground truth. The server aggregates
and distributes. If the server and the client disagree, the
client wins. If the server goes down, &lt;code>bdh&lt;/code> falls back to local
&lt;code>bd&lt;/code> with a warning. Work continues. Coordination catches up
later.&lt;/p>
&lt;p>&lt;strong>Async by default.&lt;/strong> My first instinct was real-time negotiation
between agents. Doesn&amp;rsquo;t scale. Agents work at different speeds,
on different schedules, and blocking one while waiting for
another is expensive. Mail is the default. Chat is the exception.&lt;/p>
&lt;p>&lt;strong>Advisory over mandatory.&lt;/strong> Advisory file locks that warn
instead of block. Bead claims that can be overridden with
&lt;code>--:jump-in &amp;quot;reason&amp;quot;&lt;/code> (which notifies the other agent). The
system provides information and trusts agents to act on it.&lt;/p>
&lt;p>&lt;strong>The coordinator role.&lt;/strong> I assign one agent per project the
&amp;ldquo;coordinator&amp;rdquo; role. The coordinator doesn&amp;rsquo;t write code. It
watches the dashboard, assigns work, checks on progress, nudges
stuck agents, and keeps the end goal in sight. The implementer
agents are heads-down in their worktrees; the coordinator is the
one who knows what the project needs next. BeadHub serves each
agent a role-specific policy—markdown documents describing how
agents in that role should behave—and the coordinator&amp;rsquo;s policy is
fundamentally different from an implementer&amp;rsquo;s. This turned out to
matter more than any of the technical decisions.&lt;/p>
&lt;h2 id="where-this-goes">Where this goes&lt;/h2>
&lt;p>The single-machine problem is getting solved. Agent Teams,
Codex—within a few weeks, running multiple agents in parallel on
your laptop will be table stakes.&lt;/p>
&lt;p>The multi-programmer problem is next. Five engineers, fifty
agents, three repositories, two time zones. That&amp;rsquo;s where the
coordination problem changes in kind, not just degree. It&amp;rsquo;s not
enough that your agents can talk to each other. They need to talk
to your teammate&amp;rsquo;s agents, on a different machine, in a different
time zone, working on a different repo in the same project.&lt;/p>
&lt;p>BeadHub is &lt;a href="https://github.com/beadhub/beadhub">open source&lt;/a> and
free for open-source projects.&lt;/p></content:encoded></item><item><title>With the rise of AI-assisted programming we'll want more programmers, not fewer</title><link>https://juanreyero.com/article/ai/we-need-more-programmers/</link><guid>https://juanreyero.com/article/ai/we-need-more-programmers/</guid><pubDate>Sun, 26 Oct 2025 00:00:00 +0000</pubDate><description>An argument about productivity, demand, and the continuing need for human judgment.</description><content:encoded>&lt;h3 id="tldr">TL/DR&lt;/h3>
&lt;p>The conventional wisdom is that AI will reduce the demand for programmers. I manage engineering teams and program with LLMs every day, and I am seeing something different.&lt;/p>
&lt;p>Programmers who know how to work with LLMs can be 3-10x faster for specific tasks. Given that the size of our work backlog is only limited by our vision and ambition, these super-productive individuals will be more in demand, not less.&lt;/p>
&lt;p>&lt;strong>The higher productivity will increase the number of programmers we need&lt;/strong>, and surface the next problem: &lt;strong>coordination among LLM-enhanced engineers.&lt;/strong>&lt;/p>
&lt;h2 id="jevons-paradox">Jevons paradox&lt;/h2>
&lt;p>In 2016, Geoffrey Hinton (who won the Nobel Prize for his work on neural networks) said that we should stop training radiologists because it was &amp;ldquo;completely obvious&amp;rdquo; that within five years deep learning would do their job better than they could.&lt;/p>
&lt;p>Nine years later, radiologists are in &lt;a href="https://newrepublic.com/article/187203/ai-radiology-geoffrey-hinton-nobel-prediction">historic shortage&lt;/a>. Mayo Clinic has grown its radiology staff by 55% since Hinton made that prediction. The specialty is projected to grow another 26% over the next thirty years.&lt;/p>
&lt;p>AI did transform radiology, but not in the way Hinton expected. It made radiologists more productive: scans became faster, routine tasks were automated, image quality improved. But making radiology more efficient didn&amp;rsquo;t reduce the demand for radiologists—it increased it. More efficient radiology made imaging more accessible, which drove up demand for it.&lt;/p>
&lt;p>This pattern has a name, &lt;a href="https://en.wikipedia.org/wiki/Jevons_paradox">Jevons Paradox&lt;/a>: &lt;strong>efficiency improvements often increase total consumption&lt;/strong>. When cars became more fuel-efficient, people drove more miles, not fewer. When steam engines became more efficient, coal consumption went up, not down. When radiologists became more efficient, demand for radiology increased.&lt;/p>
&lt;h2 id="why-demand-increases">Why demand increases&lt;/h2>
&lt;p>The intuition behind &amp;ldquo;fewer programmers&amp;rdquo; assumes a fixed amount of work: build the features, fix the bugs, maintain the systems: once you can do all that faster, you&amp;rsquo;ll be done sooner with fewer people.&lt;/p>
&lt;p>But this is only an instance of the &lt;a href="https://en.wikipedia.org/wiki/Lump_of_labour_fallacy">lump of labor fallacy&lt;/a>.&lt;/p>
&lt;p>Anyone who has run an engineering organization knows that the backlog doesn&amp;rsquo;t shrink when you get faster. If anything, it explodes. Every problem you solve reveals three more worth solving. Every feature you ship makes users aware of other features they need. &lt;strong>Every new capability opens up opportunities that were previously impossible to pursue.&lt;/strong>&lt;/p>
&lt;p>There&amp;rsquo;s a subtler effect too. An hour not spent programming used to mean an hour of progress missed. Now, for someone skilled with LLMs, that same lost hour can mean the equivalent of a day or two of progress missed. The opportunity cost has multiplied. &lt;strong>The gap between organizations that keep their best programmers programming and those that don’t will widen dramatically.&lt;/strong>&lt;/p>
&lt;p>When your capacity multiplies, entire categories of previously impossible work become viable.&lt;/p>
&lt;h2 id="the-skills-split">The skills split&lt;/h2>
&lt;p>A &lt;a href="https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/">recent study&lt;/a> tested sixteen experienced developers using AI tools on their own repositories (code they knew intimately). On average, they were 19% slower when using AI tools, despite expecting to be 24% faster.&lt;/p>
&lt;p>Developers with roughly fifty or more hours of prior AI-tool use, however, tended to gain productivity. The majority, with less experience, slowed down. There’s a steep learning curve, and few have climbed it.&lt;/p>
&lt;p>A skills split is emerging. Programmers who can use AI effectively are becoming force multipliers; those who can’t, or won’t, are falling behind. The work is shifting from syntax and detail to judgment and architecture: reviewing generated code for subtle flaws, choosing among approaches, directing agents, and maintaining coherence as systems evolve faster than before.&lt;/p>
&lt;p>The best programmers are excelling at this. It plays to their strengths: architectural insight, pattern recognition, and judgment.&lt;/p>
&lt;p>&lt;strong>Good programmers now have superpowers, yet they cost about the same.&lt;/strong> I predict they’ll soon command higher wages, and demand for them will rise.&lt;/p>
&lt;h2 id="the-coordination-problem">The coordination problem&lt;/h2>
&lt;p>The bottleneck has shifted. It’s no longer about individual productivity. It’s about coordination. Our management tools (daily standups, OKRs, sprint planning) were all designed for humans working at human speed, solving problems at a pace where the main constraint was how fast people could think and communicate.&lt;/p>
&lt;p>&lt;strong>These tools are increasingly in the way&lt;/strong>. When a programmer working with an LLM can prototype three different approaches to a problem in a morning, the two-week sprint feels wrong. When they can refactor a complex system in an afternoon, careful estimation of story points loses its meaning. The rhythms don’t match anymore.&lt;/p>
&lt;p>The most interesting innovations in software development over the next few months will be about figuring out how to coordinate work when some people are operating at more than five times the speed of traditional development. &lt;a href="https://www.anthropic.com/news/skills">Claude&amp;rsquo;s Skills&lt;/a> are a very interesting step in that direction.&lt;/p>
&lt;h2 id="the-agency-question">The agency question&lt;/h2>
&lt;p>A common argument against the future of programmers is something along the lines of: you’ll be able to tell an AI, “build me an e-commerce site that sells shoes for clowns, market it, handle the orders, and send the money to this account,” and it will just happen. End to end, without you.&lt;/p>
&lt;p>The technical pieces will probably come together. The &lt;a href="https://modelcontextprotocol.io/introduction">Model Context Protocol&lt;/a> and similar efforts are standardizing how AI systems connect to services and tools. Maybe LLMs will develop something that looks like genuine agency, with their own reward loops and decision-making capabilities.&lt;/p>
&lt;p>But even if all that happens, someone still has to decide to build the clown-shoe site instead of the dog-collar site. The LLM doesn’t have your problems. It doesn’t have your goals. Even if it could execute perfectly on any direction you point it at, you’re still the one doing the pointing. &lt;strong>For as long as we have aligned LLMs and problems to solve we&amp;rsquo;ll need people who can lead the LLMs.&lt;/strong>&lt;/p>
&lt;p>And as the tools get more powerful, the pointing matters more, not less.&lt;/p>
&lt;h2 id="what-this-means">What this means&lt;/h2>
&lt;p>The ability of skilled programmers to create value has multiplied. But the market is splitting. There are programmers who can work effectively with LLMs, and there are those who can’t or won’t. The gap between these two groups is growing.&lt;/p>
&lt;p>If you’re running an engineering organization and thinking, “AI means we can reduce headcount,” you’re looking at this wrong. The opportunity space has expanded dramatically, and you should be revising your ambition and the scope of your plans.&lt;/p>
&lt;p>The constraint isn&amp;rsquo;t how much code you can write anymore: &lt;strong>it&amp;rsquo;s how much good judgment you can apply to problems, and how well your team can coordinate.&lt;/strong> For that, you need programmers who can work at this new speed. And you probably need more of them, not fewer.&lt;/p>
&lt;hr>
&lt;p>&lt;em>I built a tool to address the coordination problem: &lt;a href="https://juanreyero.com/article/ai/beadhub/">BeadHub: Coordination for AI Programming Teams&lt;/a>.&lt;/em>&lt;/p></content:encoded></item><item><title>Data cleaning and anonymizing with GPT-3.5</title><link>https://juanreyero.com/article/ai/data-cleaning-with-gpt-3.5/</link><guid>https://juanreyero.com/article/ai/data-cleaning-with-gpt-3.5/</guid><pubDate>Sun, 06 Aug 2023 00:00:00 +0000</pubDate><description>An early experiment in using language models to clean and anonymize data.</description><content:encoded>&lt;blockquote>
&lt;p>&lt;strong>Note added on 2025-07-28&lt;/strong>: It&amp;rsquo;s been two years of programming with and for LLMs. This article sounds so naïve now.&lt;/p>&lt;/blockquote>
&lt;p>Say you made a website in which customers buy &lt;a href="https://mapaestelar.com">personalized gifts&lt;/a>. Each gift comes with a message, written by the customer in whatever language the customer wants. The use of grammar, punctuation and capitalizations in the messages is often creative.&lt;/p>
&lt;p>You would like to be able to offer reasonably normative messages to your customers. You would also like to store a fully anonymized version of the messages; replace all proper names with a &lt;code>[proper_name]&lt;/code> placeholder, place names with &lt;code>[place_name]&lt;/code>, dates with &lt;code>[date]&lt;/code>, times with &lt;code>[time]&lt;/code>, and geographical coordinates with &lt;code>[coordinates]&lt;/code>.&lt;/p>
&lt;p>Is it possible to use OpenAI&amp;rsquo;s &lt;a href="https://platform.openai.com/docs/models/gpt-3-5">gpt-3.5-turbo&lt;/a> to do this?&lt;/p>
&lt;p>Luckily you happen to have some tens of thousands of messages laying around, so you can actually test whatever solution you come up with.&lt;/p>
&lt;h2 id="the-naïve-approach-just-ask-the-model-to-do-it">The naïve approach: just ask the model to do it&lt;/h2>
&lt;p>The first thing I tried was the straight-forward option: just ask the genie to do it for you, with a system prompt and a user prompt like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">system_prompt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;You are a proof-reader. You will be given &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;a text that may be poorly written, perhaps &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;with bad punctuation and wrong capitalization. &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;Your task is to first correct the grammar, &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;punctuation, and capitalization of the text. &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;Once this is done you should anonymize it by &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;replacing all the person&amp;#39;s proper names in the text &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;with [proper_name], place names with [place_name], &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;dates with [date], times with [time], and &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;geographical coordinates with [coordinates]&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">user_prompt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s1">&amp;#39;Correct and anonymize the following text: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This doesn&amp;rsquo;t work with GPT-3.5. It sometimes produces the desired result, but it often misses the anonymization elements, and generally makes a mess of things.&lt;/p>
&lt;h2 id="function-calling">Function calling&lt;/h2>
&lt;p>&lt;a href="https://platform.openai.com/docs/guides/gpt/function-calling">Function calling&lt;/a> is a wonderful tool that allows you to get structured data from the model. You describe functions and their inputs in your call to the model; if the model decides that it wants to call one of the functions, it will come back with a request to call the function and, crucially, with a dictionary containing the function&amp;rsquo;s arguments.&lt;/p>
&lt;p>And, most interesting for the problem at hand, you can also force the model to call a function. If you do, you will get the structured data you would need to call the function.&lt;/p>
&lt;p>So what we do is ask the model to call a function that needs, as arguments, the corrected text and the anonymization elements. Once we get back the dictionary with the arguments for the function we can anonymize by simply searching and replacing the anonymization elements in the corrected text.&lt;/p>
&lt;p>This actually works. Interestingly, the GPT-3.5 model is not able to replace the anonymization elements in the text by their placeholder, but it can reliably find them.&lt;/p>
&lt;h2 id="sample-code">Sample code&lt;/h2>
&lt;p>This is the function I have been using to play with the OpenAI api:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">json&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">typing&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Dict&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">openai&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Ensure that the openai key is loaded, with something like&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">Api_loaded&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">False&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">ensure_api&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">api_key&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">global&lt;/span> &lt;span class="n">Api_loaded&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">Api_loaded&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">openai&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">api_key&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">api_key&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Api_loaded&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">True&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">chat_completion_request&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">messages&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">Dict&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">api_key&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">functions&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">Dict&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">call_function&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">temperature&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">float&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 0 to 2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model_name&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;gpt-3.5-turbo-0613&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">attempts&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">Dict&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">args&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;model&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">model_name&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;messages&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">messages&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;temperature&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">temperature&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">functions&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">args&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;functions&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">functions&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">call_function&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">functions&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">RuntimeError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s1">&amp;#39;Cannot call function &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">call_function&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s1"> &amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;if no functions are defined&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">found_function&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">fdesk&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">fdesk&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">functions&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">fdesk&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;name&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">call_function&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">found_function&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">RuntimeError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s1">&amp;#39;Cannot call undefined function &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">call_function&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">found_function&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">RuntimeError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s1">&amp;#39;Found more than one definitions of &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">call_function&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">args&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;function_call&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;name&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">call_function&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ensure_api&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">api_key&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">openai&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ChatCompletion&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">**&lt;/span>&lt;span class="n">args&lt;/span>&lt;span class="p">)[&lt;/span>&lt;span class="s2">&amp;#34;choices&amp;#34;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s2">&amp;#34;message&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">function_call&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;function_call&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">function_call&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;call_function&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">function_call&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;name&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;with_arguments&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">loads&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">function_call&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;arguments&amp;#39;&lt;/span>&lt;span class="p">]),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;success&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">True&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">except&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decoder&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">JSONDecodeError&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># The model may have failed to produce correct json&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">attempts&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">chat_completion_request&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">messages&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">messages&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">api_key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">api_key&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">functions&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">functions&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">call_function&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">call_function&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">temperature&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">temperature&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">model_name&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">attempts&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">attempts&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;success&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">False&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;reply&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;content&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;success&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">True&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">except&lt;/span> &lt;span class="n">openai&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">InvalidRequestError&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">exc&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">RuntimeError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;Invalid request error from OpenAI&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="kn">from&lt;/span> &lt;span class="nn">exc&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>We define a &lt;code>store_correct_text&lt;/code> function like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">functions&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;store_correct_text&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Store a corrected version of the input text&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;parameters&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;object&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;properties&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;correct_text&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;string&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;A corrected version the text&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;person_proper_names&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;string&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;A list of the proper names of &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;persons in the text separated &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;by semicolons&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;place_names&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;string&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;A list of the names of places in &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;the text separated by semicolons&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;dates&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;string&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;A list of the dates in the text &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;separated by semicolons&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;geographical_coordinates&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;string&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;A list of the dates in the text &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;separated by semicolons&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;times&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;string&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;A list of the times (hours and minutes) &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;in the text separated by semicolons&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;required&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;correct_text&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;person_proper_names&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;place_names&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;dates&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;geographical_coordinates&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;times&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The system and user prompts are:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">system_prompt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;You are a proof-reader. You will be &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;given a text that can be poorly written, &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;maybe with bad punctuation and wrong &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;capitalization. Your task is to first correct &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;the grammar, punctuation, and capitalization &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;of the text, and once this is done to find all &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;the person&amp;#39;s proper names in the text. &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;Person&amp;#39;s proper names are those that identify &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;people, like Mark or Anne Frank. You should also &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;find all the proper names of places in the text. &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;You should also find the dates. You should also &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;find geographical coordinates (latitude and &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;longitude). You should also find the times &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;mentioned in the text (hour and minute).&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">user_prompt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;Correct the following text, and make it into &amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="sa">f&lt;/span>&lt;span class="s1">&amp;#39;a template:&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>We can now call &lt;code>chat_completion_request&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">chat_completion_request&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">messages&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[{&lt;/span>&lt;span class="s1">&amp;#39;role&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;system&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;content&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">system_prompt&lt;/span>&lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;role&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;user&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;content&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">user_prompt&lt;/span>&lt;span class="p">}],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">api_key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;your api key possibly loaded from .env&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">functions&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">functions&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">call_function&lt;/span>&lt;span class="s1">&amp;#39;store_correct_text&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Finally, if things worked, simply replace the anonymization elements:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;success&amp;#39;&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">final_text&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;with_arguments&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;correct_text&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">argname&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;person_proper_names&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;place_names&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;dates&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;geographical_coordinates&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;times&amp;#39;&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">names&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;with_arguments&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">argname&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">name&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">names&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;;&amp;#39;&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># The placeholder is the argument name&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># minus the final s&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">final_text&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">final_text&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">replace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="sa">f&lt;/span>&lt;span class="s1">&amp;#39;[&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">argname&lt;/span>&lt;span class="p">[:&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s1">]&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></content:encoded></item></channel></rss>