<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>swarnim&apos;s blog</title><description>swarnim&apos;s musings on computers... and maybe other things too.</description><link>https://swarnimwalavalkar.com/</link><item><title>Some thoughts on harnesses and the agents they shape</title><link>https://swarnimwalavalkar.com/posts/some-thoughts-on-harnesses/</link><guid isPermaLink="true">https://swarnimwalavalkar.com/posts/some-thoughts-on-harnesses/</guid><description>Some thoughts on harnesses and the agents they shape</description><pubDate>Sun, 13 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Harnesses today are a snapshot of the constraints and invariants of the current
generation of models. As models improve and what we use them for becomes
increasingly more ambitious, some of those assumptions can become unnecessary
constraints.&lt;/p&gt;
&lt;p&gt;The folks building harnesses do a very good job of making design decisions that
maximize the model&apos;s ability to drive meaningful outcomes, the best harnesses
can also sometimes provide a glimpse into the future by building capabilities
that the model can yet only enable crudely, but even so, if they are useful
enough, (and sufficiently verifiable), the models are post-trained to be more
effective at that capability.&lt;/p&gt;
&lt;p&gt;This is much of what the agent improvement loop looks like, at least for now.&lt;/p&gt;
&lt;p&gt;I want to explore how much of it can become an optimization problem for the
agent itself, shaping its working methods around the task and learning from the
results.&lt;/p&gt;
&lt;p&gt;Now, agents are already quite involved in this process, the people building
harnesses, and training models are all quite ai-pilled and heavily leverage AI
in their work.&lt;/p&gt;
&lt;p&gt;I can&apos;t speak to the research end of that spectrum, but if you&apos;ve spent any
amount of time actually trying to get agents to build harnesses, you would know
that they are not very good at it...&lt;/p&gt;
&lt;p&gt;Models have terrible intuitions for context management, tool design, and being
thoughtful about not busting the prompt cache.&lt;/p&gt;
&lt;p&gt;I can&apos;t be certain as to why that is, maybe it&apos;s because good harness
engineering patterns are out of distribution relative to the model&apos;s training
data because of how novel the category is. Maybe it&apos;s hard to RL on, since the
&quot;reward function&quot; for good harness design is largely confounded and signals are
full of noise, and can only truly be evaluated long-term.&lt;/p&gt;
&lt;p&gt;What is more certain is that models can accomplish great things by composing
simple, strong primitives together, and with iterative improvement over a
measurable goal.&lt;/p&gt;
&lt;p&gt;So then, another way to frame the problem of a recursively self-improving
harness perhaps is figuring out which parts of the harness are immutable aspects
of its runtime, so things like the agent loop, context management primitives,
etc, vs which parts should the agent be able to modify by itself.&lt;/p&gt;
&lt;h2&gt;Harness Design &amp;lt;&amp;gt; Model Intelligence&lt;/h2&gt;
&lt;p&gt;It is hard to forecast exactly how much the future of recursive self-improvement
(RSI) will rely on harness engineering, but it seems unlikely to me that the
near term path to RSI starts as a model directly rewriting its weights.&lt;/p&gt;
&lt;p&gt;I suspect thoughtful harness design will take on more of the responsibility for
making that improvement process possible in the near term.&lt;/p&gt;
&lt;p&gt;This means improving the machinery for getting better answers rather than just
the answer.&lt;/p&gt;
&lt;p&gt;Harness engineering as a discipline will evolve more toward building general
systems for letting the agent improve its own methods, we build general
mechanisms that let it try different approaches, learn from the results, and
change how it works, with fewer heuristic rules prescribing the approach.&lt;/p&gt;
&lt;p&gt;As those systems mature, they can support autoresearch workflows for improving
the models themselves. More capable models may then need less guidance from the
harness, letting us remove some of the complexity that helped earlier
generations work reliably.&lt;/p&gt;
&lt;h2&gt;Harness Design Patterns for Continual Learning&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;quick plug: &lt;a href=&quot;https://github.com/SwarnimWalavalkar/noesis&quot;&gt;Noesis&lt;/a&gt; is my
attempt at reifying some of these ideas into a self-evolving agent that&apos;s
delightful to use.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The &quot;harness&quot; is the runtime the agent operates within. It defines how the model
observes, acts, memorizes, checks itself, and improves.&lt;/p&gt;
&lt;p&gt;The design of this runtime should be deliberately simple and generic to enable
generalization, referencing existing software engineering patterns is also
helpful, because it gives the model something to draw on from pretraining, so it
can spend more effort on the task and less on figuring out how its environment
works.&lt;/p&gt;
&lt;p&gt;I also find operating systems and the UNIX philosophy to be a useful analogy.
Similar to an OS, a harness should encapsulate complexity while keeping the
interface simple.&lt;/p&gt;
&lt;h2&gt;Dynamic Workflows&lt;/h2&gt;
&lt;p&gt;Code is the universal language for defining programs and systems. When several
tool calls contribute to the same task, I think code is the natural place to
express how they fit together.&lt;/p&gt;
&lt;p&gt;The model could fetch data from a few MCP servers, transform the results, and
pass the relevant parts into another operation, all within the abstraction of a
&quot;program&quot;. It can decide which operations run concurrently and how to recover
from failures.&lt;/p&gt;
&lt;p&gt;Doing this through code means the foreground model doesn&apos;t need another
inference round just to move data between tools. Intermediate results can remain
in the execution environment until there is something worth bringing into
context. The tool calls still happen, but the model gets to decide how much of
that machinery it needs to see.&lt;/p&gt;
&lt;p&gt;And whenever a step requires intelligence, the program should be able to invoke
a model. Intelligence becomes a function you can call as part of a larger
computation.&lt;/p&gt;
&lt;p&gt;A program can initially be written as a script for a particular task, and then
if the agent thinks it could be useful again, the agent should be able to give
it an interface, save it, and keep iterating on it as it continues using it
across sessions.&lt;/p&gt;
&lt;p&gt;Longer, more involved workflows may need explicit phases and enough recorded
state to resume after an interruption or retry a failed step. The runtime should
provide those mechanics so the agent can define a workflow without having to
rely on external durable execution mechanisms or worse, unnecessarily reinvent a
bespoke one.&lt;/p&gt;
&lt;p&gt;In Noesis, these are Programs, which can either take the form of scripts or
durable phased workflows. Programs can be bundled alongside a skill for easy
portability, and they can just as well be invoked either by the agent, or by the
human.&lt;/p&gt;
&lt;h2&gt;Context Engineering&lt;/h2&gt;
&lt;p&gt;I think it helps to distinguish between what the agent has access to and what it
is attending to right now.&lt;/p&gt;
&lt;p&gt;A long running session might produce far more material than belongs in any one
model request, but that material can still be useful later. We should be able to
remove it from the immediate context without making it inaccessible.&lt;/p&gt;
&lt;p&gt;Files are a useful primitive here. Large tool outputs and other artifacts
created by the agent can live outside the context window, where the agent can
inspect them programmatically. The agent can then grep, sed, awk its way through
any large corpus of text to get the insight it needs in any subsequent turn.&lt;/p&gt;
&lt;p&gt;The same principle applies to the session transcripts (both current and past).
Noesis for example, makes transcripts from prior sessions accessible through
codemode, so an agent can semantically search relevant chunks from prior
sessions, slice parts of its context window, do transformations on them, use it
as context for a subagent, etc.&lt;/p&gt;
&lt;h2&gt;Compaction&lt;/h2&gt;
&lt;p&gt;Compaction is super important for long running agents, as the agent works on a
long horizon goal and makes its way through various smaller tasks. It
accumulates a lot of context that isn&apos;t necessarily relevant going forward.&lt;/p&gt;
&lt;p&gt;The context window is a scarce resource, you only have so many tokens to play
with until you find yourself contending with the effects of attention
degradation.&lt;/p&gt;
&lt;p&gt;The principal goal of context engineering is to reduce noise, and ensure that
only the tokens most relevant to the task at every point remain in the context
window.&lt;/p&gt;
&lt;p&gt;The way Noesis implements compaction lets it carry notes from one context window
into the next, preserving details it has gathered without repeatedly compressing
those notes into a single summary. Earlier messages and tool outputs remain
searchable, so if something relevant wasn&apos;t captured in the notes, the agent can
go back and find it from the original session transcript.&lt;/p&gt;
&lt;h2&gt;Orchestration&lt;/h2&gt;
&lt;p&gt;A harness should be able to spawn multiple subagents to work in parallel and the
main agent should have the ability to launch, monitor, inspect, steer, and
reintegrate subagent outputs in the main thread.&lt;/p&gt;
&lt;p&gt;This is useful when the main agent needs to test multiple hypotheses, run
experiments concurrently, or delegate isolated subtasks without polluting the
main context.&lt;/p&gt;
&lt;p&gt;Much of this should be expressible through code. The agent can decide how it
wants to compose and orchestrate subagents and define the dependencies between
them.&lt;/p&gt;
&lt;p&gt;For this to work, subagents need stable addressable identities. The main agent
should be able to continue its own work, then come back to a subagent it spawned
earlier with more context or a follow up. Other subagents should also be able to
communicate with one another if they deem it necessary.&lt;/p&gt;
&lt;p&gt;Delegation requires observability to be most effective. A reasonable conclusion
may depend on an assumption that doesn&apos;t make sense in the context of the
broader task. The parent should be able to examine the relevant parts of the
subagent&apos;s trace and artifacts, then follow up with, or steer it. The same
programmatic context management principles apply here too.&lt;/p&gt;
&lt;h2&gt;Closing Thoughts&lt;/h2&gt;
&lt;p&gt;A true fully RSI solution would also improve the model, the compute underneath
it, and the power feeding it all. Perhaps an RSI harness is a step on that path.&lt;/p&gt;
&lt;p&gt;I don&apos;t know how far that goes. But it seems worth building environments where
we can find out through continued use, and where useful discoveries can carry
forward into increasingly ambitious work.&lt;/p&gt;
&lt;p&gt;If you find all of this as interesting as I do, I&apos;d love for you to give
&lt;a href=&quot;https://github.com/SwarnimWalavalkar/noesis&quot;&gt;Noesis&lt;/a&gt; a swing. It&apos;s the
self-evolving agent I&apos;m building to explore these ideas and make a
general-purpose harness I&apos;d enjoy using.&lt;/p&gt;
</content:encoded></item><item><title>Tools and Curiosities</title><link>https://swarnimwalavalkar.com/posts/tools-and-curiosities/</link><guid isPermaLink="true">https://swarnimwalavalkar.com/posts/tools-and-curiosities/</guid><description>Tools and Curiosities</description><pubDate>Sun, 24 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&quot;Don&apos;t Follow Your Dreams, Follow Your Tools&quot;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;The omniscient YouTube algorithm recently resurfaced
&lt;a href=&quot;https://www.youtube.com/watch?v=f_Rqf-vxBM8&quot;&gt;a Hank Green video&lt;/a&gt; on my feed,
with that very title.&amp;lt;/p&amp;gt; And I have been thinking about it.&lt;/p&gt;
&lt;p&gt;I think it is more generous than &quot;follow your dreams,&quot; because dreams are often
just old pictures of yourself. They are formed from the vocabulary you had at
the time. They inherit the prestige objects of the culture around you. They
assume the world will keep offering the same destinations it offered when the
dream first appeared.&lt;/p&gt;
&lt;p&gt;Tools are more honest. They are a current account of what you can do, what you
can see, what you care about, who trusts you, what you have learned, and what
kinds of problems you keep finding yourself most drawn to.&lt;/p&gt;
&lt;p&gt;A toolkit includes the obvious things: technical skills, writing ability, taste
in interfaces, knowledge of a domain, the ability to model complex systems in
your head. But it also includes the less obvious things: relationships,
accumulated scars, values, recurring irritations, the specific kind of friction
you notice before other people do.&lt;/p&gt;
&lt;p&gt;It includes you.&lt;/p&gt;
&lt;p&gt;A tool is not just a thing outside the self. It is any capacity that changes
what you can do next.&lt;/p&gt;
&lt;p&gt;You see this most clearly when you make something.&lt;/p&gt;
&lt;p&gt;Before you know how to build software, many problems remain complaints. A
workflow is slow. Some information lives in the wrong place. A person is copying
data between systems because nobody has given the work a better shape.&lt;/p&gt;
&lt;p&gt;After you know how to build, the same problem looks different. It becomes
material. You can see where a script would help, where an interface is missing,
where a system boundary is wrong. The world did not change. Your handle on it
did.&lt;/p&gt;
&lt;p&gt;Learning a tool changes the board.&lt;/p&gt;
&lt;p&gt;This is why &quot;follow your tools&quot; is better than it first sounds. It is not
saying: only do what you already know how to do. That would be a recipe for
stagnation. It is saying: begin from actual contact with your current
capacities, then use projects to stretch them.&lt;/p&gt;
&lt;p&gt;The usual dream-frame asks: what do I want to become?&lt;/p&gt;
&lt;p&gt;The tool-frame asks: given what I can now see and do, what is the next live
problem?&lt;/p&gt;
&lt;p&gt;That second question is much better.&lt;/p&gt;
&lt;h2&gt;Curiosity is the pointer&lt;/h2&gt;
&lt;p&gt;Tools by themselves are inert. They need a search policy.&lt;/p&gt;
&lt;p&gt;Curiosity is one of the better ones.&lt;/p&gt;
&lt;p&gt;By curiosity I do not mean novelty addiction. I do not mean opening twenty tabs
and calling the feeling of motion research. I mean the thing that keeps snagging
your attention. The broken workflow you keep complaining about. The question you
keep trying to explain to someone else. The topic where the available answers
feel fake. The capability that feels newly possible but not yet well-shaped. The
area where everyone else seems strangely resigned.&lt;/p&gt;
&lt;p&gt;Curiosity usually arrives before a thesis. This is why it is easy to distrust.
It does not yet have the dignity of a plan. It is just a tug.&lt;/p&gt;
&lt;p&gt;But a tug is information.&lt;/p&gt;
&lt;p&gt;A lot of good work starts as an inability to leave something alone. You notice a
gap. You notice that people are using clumsy language for a real thing. You
notice that a system works, but only because some human is absorbing the mess in
their head. You notice that everyone is arguing about the wrong part of the
problem.&lt;/p&gt;
&lt;p&gt;At that stage, the job is not to write the grand plan. It is to build enough
contact with the problem that the next question becomes sharper.&lt;/p&gt;
&lt;p&gt;Curiosity is a pointer. It is not proof. It has to be tethered.&lt;/p&gt;
&lt;p&gt;The tether is a project.&lt;/p&gt;
&lt;h2&gt;Projects are probes&lt;/h2&gt;
&lt;p&gt;A project is curiosity made concrete.&lt;/p&gt;
&lt;p&gt;You do not need the full plan. In fact, if you already know exactly what the
thing will become, the project is probably less interesting. The project is
where the plan earns detail.&lt;/p&gt;
&lt;p&gt;The point of a project is not only to produce the artifact. It is to send a
probe into reality.&lt;/p&gt;
&lt;p&gt;The probe asks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is the problem real?&lt;/li&gt;
&lt;li&gt;Does anyone care?&lt;/li&gt;
&lt;li&gt;Was the hard part technical, social, distributional, aesthetic, or
organizational?&lt;/li&gt;
&lt;li&gt;Does my current toolkit transfer?&lt;/li&gt;
&lt;li&gt;What tool am I missing?&lt;/li&gt;
&lt;li&gt;Do I still care after the first burst of interest?&lt;/li&gt;
&lt;li&gt;Can this become useful to someone besides me?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A serious project should leave behind at least one of three things: value,
taste, or tools.&lt;/p&gt;
&lt;p&gt;Value means the thing helped someone. Taste means your predictive model
improved. You now understand some class of decision better than before. Tools
means you acquired a reusable capacity: a library, a pattern, a contact, a
distribution surface, a sharper concept, a scar.&lt;/p&gt;
&lt;p&gt;This is why failed projects are not always failures. Some projects fail as
products but succeed as probes. They teach you where the hard part really was.
They reveal that the market did not care, or that the interface was wrong, or
that the technical problem was easy and the coordination problem was the whole
game. They show you that your toolkit was missing something.&lt;/p&gt;
&lt;p&gt;Then you learn the missing thing.&lt;/p&gt;
&lt;p&gt;And that new tool changes what projects are available next.&lt;/p&gt;
&lt;p&gt;This loop is much more useful than the dream-frame. The dream-frame treats
deviation as distraction. The tool-frame treats deviation as exploration, as
long as it makes contact with reality.&lt;/p&gt;
&lt;p&gt;That last clause matters.&lt;/p&gt;
&lt;p&gt;It is very easy to fake this loop. You can start projects that never leave your
private world. You can collect beginnings. You can confuse the feeling of
expanded possibility with the reality of expanded capacity. You can stay in the
pleasant phase where the project is still mostly a story about who you might
become.&lt;/p&gt;
&lt;p&gt;Shipping is what closes the loop.&lt;/p&gt;
&lt;p&gt;Not always shipping as in a polished public launch. Sometimes the right unit is
a prototype shown to one user, a script used by a teammate, a memo that changes
a decision, a small tool that saves someone ten minutes every week. But there
has to be some surface where the world can answer back.&lt;/p&gt;
&lt;p&gt;You can improve something bad. You cannot improve nothing.&lt;/p&gt;
&lt;h2&gt;Work with gravity&lt;/h2&gt;
&lt;p&gt;There is a kind of work that feels like falling downhill.&lt;/p&gt;
&lt;p&gt;This is not the same as easy work. It is work where your tools, values,
interests, and energy are already arranged in the direction of the problem.&lt;/p&gt;
&lt;p&gt;Ambitious people are trained to be suspicious of this. If it feels easy, surely
it cannot count. Work is supposed to feel like swimming upstream. The difficulty
becomes part of the proof.&lt;/p&gt;
&lt;p&gt;Sometimes that is right. Some important work is hard because the problem is
hard. Some obligations have to be met whether or not they feel alive. Some
stretches of any real project are just unpleasant.&lt;/p&gt;
&lt;p&gt;But some work is hard because it is badly matched to your tools. Or because it
is mostly prestige. Or because you are trying to become a person you once
imagined instead of looking at the person, toolkit, and world that actually
exist now.&lt;/p&gt;
&lt;p&gt;There is no virtue in that kind of difficulty.&lt;/p&gt;
&lt;p&gt;Working with gravity is what it feels like when your tools, taste, curiosity,
and the problem all point in roughly the same direction. You still work.
Sometimes you work a lot. But the work carries you forward instead of asking you
to constantly manufacture motion.&lt;/p&gt;
&lt;p&gt;The test is whether the downhill path compounds or merely soothes.&lt;/p&gt;
&lt;p&gt;A compounding downhill path leaves you with stronger tools, sharper taste, more
useful artifacts, better relationships, or better problems. A soothing downhill
path leaves you with the same self, just better entertained.&lt;/p&gt;
&lt;p&gt;This is the guardrail. &quot;Do what you want&quot; is not enough. Wants are noisy. Some
wants are signals. Some are avoidance. The difference is contact with reality.&lt;/p&gt;
&lt;p&gt;If the work keeps making the world answer back, trust the pull more.&lt;/p&gt;
&lt;h2&gt;Usefulness disciplines curiosity&lt;/h2&gt;
&lt;p&gt;One of the best ways to keep curiosity honest is to aim it at something useful.&lt;/p&gt;
&lt;p&gt;Useful does not have to mean profitable. It does not have to mean large. It
means there is a counterparty. Someone has a problem. Someone can use the thing,
reject it, misunderstand it, depend on it, ask for it again, or tell you it did
not matter.&lt;/p&gt;
&lt;p&gt;Other people&apos;s problems resist your story about the project.&lt;/p&gt;
&lt;p&gt;This is why tools are such good projects. A tool has to meet another mind at the
interface. It has to be legible enough to use. It has to encode some opinion
about the work. If the opinion is wrong, the user will feel it quickly.&lt;/p&gt;
&lt;p&gt;A useful tool also creates leverage beyond the original act of making it. It
lets someone else move. It removes you from the loop, or at least reduces the
number of times you have to personally carry the same context across the same
gap.&lt;/p&gt;
&lt;p&gt;This is one reason composability matters. A good tool solves a case and creates
an affordance. It becomes part of someone else&apos;s toolkit. They can combine it
with capacities you did not predict, in situations you did not design for.&lt;/p&gt;
&lt;p&gt;Hamming has a line that the essence of science is cumulative. You should do your
work so others can build on top of it. This is true outside science too. A
project becomes more valuable when it is not only an answer, but a surface for
future work.&lt;/p&gt;
&lt;p&gt;Useful tools are a way of making curiosity cumulative.&lt;/p&gt;
&lt;h2&gt;The toolkit compounds&lt;/h2&gt;
&lt;p&gt;The visible output of a project is the artifact. The durable output is often the
toolkit that remains after the artifact succeeds or fails.&lt;/p&gt;
&lt;p&gt;This is why small projects can matter more than they look. They plant acorns.
You learn a domain. You meet a collaborator. You acquire a distribution channel.
You develop a reusable pattern. You get one painful lesson about what users
actually do. You write one script that becomes the seed of a system. You learn
that the elegant part was irrelevant and the boring part was load-bearing.&lt;/p&gt;
&lt;p&gt;Then the next project starts from a different place.&lt;/p&gt;
&lt;p&gt;This is the loop:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Tools let you see or do something.&lt;/li&gt;
&lt;li&gt;Curiosity points you at a live edge.&lt;/li&gt;
&lt;li&gt;A project creates contact with reality.&lt;/li&gt;
&lt;li&gt;Reality contact expands the toolkit.&lt;/li&gt;
&lt;li&gt;The expanded toolkit reveals better curiosities.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This may feel a bit scary. It does not give you the comfort of a fixed
destination. It asks you to keep moving while the map is changing.&lt;/p&gt;
&lt;p&gt;But this is how a lot of real careers seem to work. With the compounding of
tools and judgment across projects.&lt;/p&gt;
&lt;p&gt;The particular thing you do may involve luck. That you keep becoming the kind of
person who can do interesting things is less luck.&lt;/p&gt;
&lt;p&gt;But you still need an arena.&lt;/p&gt;
&lt;p&gt;An arena can be a user, a production system, a deadline, or a peer whose taste
you respect. What matters is that the work has a surface where being wrong costs
something and being right changes what happens next.&lt;/p&gt;
&lt;p&gt;Without that surface, the loop can collapse inward. Curiosity becomes
stimulation. Tools become accumulation. Projects become beginnings.&lt;/p&gt;
&lt;h2&gt;Better maps&lt;/h2&gt;
&lt;p&gt;I do not think the alternative to dreams is cynicism.&lt;/p&gt;
&lt;p&gt;The alternative is attention.&lt;/p&gt;
&lt;p&gt;Pay attention to what you can do. Pay attention to what keeps pulling on you.
Pay attention to the problems that become visible only because of the tools you
already have. Pay attention to where the world pushes back. Build something
small enough to touch reality and serious enough to change your tools.&lt;/p&gt;
&lt;p&gt;Dreams can still be useful. They reveal values. They tell you something about
what you once found beautiful or urgent. But they should not be allowed to
harden into old maps.&lt;/p&gt;
&lt;p&gt;The better aim is to keep producing better maps.&lt;/p&gt;
&lt;p&gt;Follow your tools. Follow your curiosities. Take on projects before you fully
know how they will work. Let them teach you. Let some of them fail. But make
them real enough that the world can answer.&lt;/p&gt;
&lt;p&gt;Don&apos;t follow your dreams into a picture of who you used to want to be.&lt;/p&gt;
&lt;p&gt;Follow your tools and curiosities into an arena where the work can change what
you are capable of seeing next.&lt;/p&gt;
</content:encoded></item><item><title>The Discerning Machine</title><link>https://swarnimwalavalkar.com/posts/the-discerning-machine/</link><guid isPermaLink="true">https://swarnimwalavalkar.com/posts/the-discerning-machine/</guid><description>The Discerning Machine</description><pubDate>Mon, 18 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;aside class=&quot;!my-0 font-serif italic text-base leading-snug text-neutral-500&quot;&amp;gt;
Originally published on &amp;lt;a href=&quot;https://devfolio.co/blog/the-discerning-machine/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; class=&quot;text-neutral-300 underline decoration-neutral-700 underline-offset-[3px] transition-colors duration-200 hover:decoration-neutral-400&quot;&amp;gt;Devfolio&apos;s blog&amp;lt;/a&amp;gt;.
&amp;lt;/aside&amp;gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What we learned from scaling hackathon judging by separating machine thoroughness from human taste.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We recently ran an experiment for the
&lt;a href=&quot;https://x.com/devfolio/status/2052707585208308125&quot;&gt;Push to Prod&lt;/a&gt; hackathon to
see if an AI system could help scale hackathon judging while preserving human
judgment and taste.&lt;/p&gt;
&lt;p&gt;Hackathon judging is usually described as a question of quality: which projects
are best? In practice, it is also a question of attention. By the time
submissions close, a small panel has to read descriptions, watch demos, inspect
repositories, compare projects against a rubric, and decide which teams deserve
glory and prizes. The work is not only subjective, A lot of it is plain
inspection: what was actually built, which claims are supported by the code, and
where the pitch and the artifact come apart.&lt;/p&gt;
&lt;p&gt;That distinction became the design frame for the system. Some parts of judging
are thoroughness-bound: reading code, checking claims, citing evidence, applying
the same rubric across a long queue. Other parts are taste-bound: deciding how
much the evidence matters, whether the hard part was actually solved, and which
project deserves to win. We built for the first part so humans could spend more
of their attention on the second.&lt;/p&gt;
&lt;p&gt;The result is not an AI judge in the usual sense. It is closer to an evidence
layer. An agent reads the team&apos;s submission, walks the repository with tools,
writes a cited audit, and turns that audit into structured scores a human can
inspect, override, or ignore. The decision stays with the human panel. The
machine&apos;s job is to make sure that decision begins closer to the work itself.&lt;/p&gt;
&lt;p&gt;Here are the kinds of audits the system produces:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Credited AI Depth at 9/10. The submission describes the product as a meeting
summarizer. The code implements a more specific workflow:
&lt;code&gt;lib/agents/briefing.ts&lt;/code&gt; generates different artifacts for the chair, the
scribe, and the operations lead; &lt;code&gt;lib/schema/action-items.ts&lt;/code&gt; preserves owner,
deadline, confidence, and source span; &lt;code&gt;app/review/page.tsx&lt;/code&gt; makes those
extracted obligations editable before publish. The implemented system turns
messy discussion into accountable work rather than stopping at generic
summarization.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It also catches gaps hidden deep in the codebase:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Reduced Technical Execution from 8 → 5. The submission claims &quot;multi-tenant
isolation with row-level security,&quot; but &lt;code&gt;db/policies.sql&lt;/code&gt; only checks that a
user is authenticated, and &lt;code&gt;lib/db/server.ts&lt;/code&gt; performs writes through a
service-role client that bypasses those policies. The app may still work as a
demo, but the claimed isolation is not implemented.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;These examples are composites from a few real samples, but they show the shape
of the assessment, the system reads the pitch against the code and leaves
behind an audit a human can check. The system uses a human-written rubric to
localize the judge&apos;s attention; the decision about who deserves to win stays
with the human panel.&lt;/p&gt;
&lt;p&gt;We built a system that produces audits like this for every published project in
a hackathon. An agent runs over the repository with the team&apos;s submission text
alongside it. It uses &lt;code&gt;read&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;, and &lt;code&gt;ls&lt;/code&gt; to walk the codebase claim by
claim and check what the code supports. The output is a markdown report. A
cheaper model turns the report into structured scores. The aggregate score is
computed deterministically in code. And in the end, a human reads what matters
and decides.&lt;/p&gt;
&lt;p&gt;The first production version ran on &lt;em&gt;Push to Prod&lt;/em&gt; submissions. It was useful
enough to keep building: it surfaced implementation details and claim
mismatches that would have been easy to miss in a high-volume manual review,
and it produced audits that a human could inspect rather than opaque scores
they had to accept or reject wholesale.&lt;/p&gt;
&lt;p&gt;This is what we learned from treating judging as an attention-allocation
problem with a constrained human compute budget.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Thoroughness and taste are different jobs&lt;/h2&gt;
&lt;p&gt;Some parts of judging are thoroughness-bound. Other parts are taste-bound.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Thoroughness&lt;/th&gt;
&lt;th&gt;Taste&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Core question&lt;/td&gt;
&lt;td&gt;What is actually present in the artifact?&lt;/td&gt;
&lt;td&gt;How much does it matter?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unit of work&lt;/td&gt;
&lt;td&gt;Inspect files, verify claims, cite evidence&lt;/td&gt;
&lt;td&gt;Compare tradeoffs, infer depth, judge core value proposition&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Main constraint&lt;/td&gt;
&lt;td&gt;Coverage under limited attention&lt;/td&gt;
&lt;td&gt;Domain priors built from experience&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best delegated to&lt;/td&gt;
&lt;td&gt;Systems that can apply the same policy repeatedly&lt;/td&gt;
&lt;td&gt;Humans who understand context, ambition, and what the rubric misses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Useful output&lt;/td&gt;
&lt;td&gt;An audit: claims, mismatches, citations&lt;/td&gt;
&lt;td&gt;A decision: ranking, override, or prize call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical failure mode&lt;/td&gt;
&lt;td&gt;Search error: the system looked in the wrong place&lt;/td&gt;
&lt;td&gt;Rubric overreach: the score hides a judgment call&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A pipeline that routes each step to the resource with the better cost and error
profile is resource allocation across humans and machines. The design follows
from there.&lt;/p&gt;
&lt;p&gt;Taste is the judgment you build after seeing many projects succeed, fail, and
evolve. A strong judge is not only asking whether a submission satisfies the
rubric. They are also asking: &lt;em&gt;does this implementation have depth? Is the hard
part actually solved? If this team kept going for another month, would the
project compound or collapse?&lt;/em&gt; Those calls come from experience with similar
artifacts. A rubric can describe some of that judgment. A model can approximate
some of it. Neither carries the full set of priors a strong human judge brings
to the artifact.&lt;/p&gt;
&lt;p&gt;So yes, the machine is discerning in a narrow sense. It is good at checking
evidence before it is good at judging quality. It can notice that a team
claimed a custom model and shipped a wrapper. It can notice that a README
describes a backend the repo does not contain. It can notice that a criterion
has no cited evidence. That narrower form of discernment is valuable precisely
because it leaves taste to the human layer.&lt;/p&gt;
&lt;h2&gt;What the machine can discern&lt;/h2&gt;
&lt;p&gt;The usual &quot;LLM as a judge&quot; setup asks the model: &lt;em&gt;given this artifact, what is
its quality?&lt;/em&gt; That framing invites a familiar set of problems. The model may
reward confident prose. It may prefer its own style. It may be swayed by order,
verbosity, or polish. It is being asked to compress a complex artifact into a
judgment it cannot reliably ground.&lt;/p&gt;
&lt;p&gt;We ended up asking a different question.&lt;/p&gt;
&lt;p&gt;The agent reads the team&apos;s pitch: name, tagline, description, tracks, demo URL,
submission answers. Then it enters the repository with tools. Its job is to
walk the codebase and check, claim by claim, what is and is not supported. The
output is a report whose spine is &lt;code&gt;claims_mismatches&lt;/code&gt;: places where what the
team said and what the code does come apart, with &lt;code&gt;file:line&lt;/code&gt; citations.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The hierarchy matters. The repository is the evidence. The markdown audit is
the agent&apos;s reading of that evidence. The structured JSON is an extraction from
the audit. The aggregate score is deterministic compression: score × weight,
computed in code, not by the model. The human decision sits on top. We trust
each layer less as it gets farther from the code, so the lower layers stay
inspectable.&lt;/p&gt;
&lt;p&gt;Under this frame, a polished README becomes a longer list of claims to check. A
blank README has less to disprove. Bias has not disappeared; the risk has
moved. The main failure modes shift from presentation bias toward search error,
incomplete exploration, and bad evidence retrieval. Those are still serious
failure modes, but they are easier to inspect and easier to repair.&lt;/p&gt;
&lt;p&gt;One kind of reward-hacking also gets harder: winning on confident prose alone.
A judge that estimates quality can be coaxed toward a high score by an artifact
that sounds complete. An auditor has a fixed reference to return to. If the
pitch is inflated, the repository can push back. The hard cases remain hard:
impressive-looking but trivial code, copied work, generated filler, hidden
dependencies, or a demo path that does not match the repo. The auditor reduces
the part of the scoring surface where prose alone can dominate.&lt;/p&gt;
&lt;p&gt;The output tends toward binary questions. &lt;em&gt;Is this claim supported? Is this
file present? Does this implementation match the described architecture?&lt;/em&gt; That
is a better primitive than &lt;em&gt;is this a 7 or an 8?&lt;/em&gt; We still produce 0–10 scores
per criterion because hackathon rubrics expect them, but the useful object
underneath is the cited claim check. Nobody really knows what separates a 3
from a 4 in the abstract. A cited mismatch is easier to argue with.&lt;/p&gt;
&lt;p&gt;That is why the transcript matters. When the model returns only a number, the
human has nothing to react to. Accepting or rejecting the score becomes
ceremony. When the model returns &lt;em&gt;&quot;docked Originality from 7→4 because
&lt;code&gt;src/model.ts:42&lt;/code&gt; shows the &apos;custom architecture&apos; is
&lt;code&gt;transformers.AutoModel.from_pretrained(&apos;bert-base-uncased&apos;)&lt;/code&gt;&quot;&lt;/em&gt;, the human can
verify or override in thirty seconds with the primary source in front of them.
The audit gives the human a concrete object to appeal against: a claim, a
citation, and a local reason for the score change.&lt;/p&gt;
&lt;p&gt;This hierarchy explains the two-phase pipeline too. The expensive agent does
the open-ended work: clone the repo, explore, read, reason, and write the
audit. A cheaper extraction model turns that markdown into schema-shaped JSON.
The extractor is not allowed to invent claim mismatches, omit criteria,
duplicate criteria, change max scores, or return an overall score. Validation
catches those failures, canonicalizes criterion names back to the rubric,
retries parse-level errors with a retry note, and leaves the aggregate score to
code.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The model does the open-ended reading; deterministic code handles schema
validation, canonicalization, weighting, and aggregation.&lt;/p&gt;
&lt;h2&gt;Floor quality over peak accuracy&lt;/h2&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Is the AI actually as good as a human judge? Probably not. That comparison uses
the wrong baseline.&lt;/p&gt;
&lt;p&gt;The easy benchmark compares the model against a careful, well-rested expert
with unlimited time. That person is not the system we are replacing. The real
comparison is the human process under workload: a small panel, hundreds of
submissions, uneven energy, uneven context.&lt;/p&gt;
&lt;p&gt;The important question has two parts: &lt;em&gt;how good can the best review be?&lt;/em&gt; and
&lt;em&gt;how many projects get a real review at all?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;One way to think about this is the difference between peak quality and floor
quality. A panel of humans has a high ceiling. On a project that catches the
right judge at the right moment, the review can be excellent. The floor drops
as the queue grows. The system becomes uneven. Some projects get deep
attention. Others get triage.&lt;/p&gt;
&lt;p&gt;The auditor has a lower ceiling than a great human judge and a more consistent
floor. It does not get curious or develop taste in the way a human expert does.
Its advantage is invariance under queue position: later projects receive the
same exploration policy as earlier ones, subject to the same budget and harness
constraints.&lt;/p&gt;
&lt;p&gt;That trade off can be worth making even if the model is worse than an expert on
any single project. The practical baseline is variance in review depth across
the queue. At the prize-money end of a hackathon, that variance matters.&lt;/p&gt;
&lt;h2&gt;Agentic evaluators are a different category&lt;/h2&gt;
&lt;p&gt;Once the artifact is an audit rather than a score, the engineering problem
changes. The evaluator is no longer a prompt that maps input to verdict. It is
a search system over an evidence base: submission text, repository files, demo
metadata, rubric criteria, tool traces, and the intermediate claims the agent
writes down along the way.&lt;/p&gt;
&lt;p&gt;That makes the harness the main object. The harness decides what evidence the
agent can reach, which tools it can call, how much exploration budget it gets,
what counts as a citation, how failures are retried, and which parts of the
output are allowed to influence the final score. The model is one component
inside that system. The evaluator is the whole loop.&lt;/p&gt;
&lt;p&gt;Rubrics matter a lot. A vague rubric gives the agent too much freedom to
substitute its own notion of quality. A good rubric is closer to a
specification: criteria, weights, examples, disallowed assumptions, evidence
requirements, and the boundary between claim verification and human judgment.
If the rubric says &quot;technical execution,&quot; the agent has to know whether that
means code completeness, architectural depth, deployed functionality,
reliability, or some weighted combination of those. Otherwise the audit
becomes fluent but under-specified.&lt;/p&gt;
&lt;p&gt;Profiles are how the same evaluator adapts inside production. A catalog pass
can prioritize coverage: inspect every project enough to surface obvious claim
mismatches and route human attention. A sponsor-track profile can spend more
budget on the files and flows relevant to that track&apos;s stated criteria. A
finalist profile can rerun the same project with deeper repository traversal,
stricter citation requirements, and a stronger model. An appeal profile can
focus only on disputed criteria and force the agent to re-check the evidence
behind a specific score change. These are operating points on the same
evaluation system, not environment switches.&lt;/p&gt;
&lt;p&gt;This changes the cost model. With a single model call, the main knobs are
model choice and context size. With an agentic evaluator, the knobs include
tool-call budget, repository traversal policy, timeout, model choice,
extraction strictness, rubric specificity, and retry strategy. You can spend
more compute where the decision is high-stakes or where the first pass found
uncertainty. You can also cap exploration when the audit only needs to route
attention.&lt;/p&gt;
&lt;p&gt;The failure mode changes too. A truncated prompt cannot see what was cut. An
under-explored agent saw what it chose to look at, and the transcript tells you
where it looked. That does not make the system automatically reliable. It
makes the unreliability more diagnosable: search error, missing context, weak
rubric, bad extraction, schema drift, timeout, or an unsupported inference
from evidence.&lt;/p&gt;
&lt;p&gt;The output shape also becomes part of the protocol. An agent in a sandbox can
decide, mid-run, to write its report to a file instead of returning it inline.
Or write half inline and half to disk. Or crash after streaming 90% of a
useful report. A normal model call either returns the requested object or
fails. An agent leaves traces, so the system has to recover from traces:
streamed events as the source of truth, filesystem fallback, a targeted
re-prompt for inline output, partial-text recovery on late-session crash.&lt;/p&gt;
&lt;p&gt;This is the surface area you inherit the moment the model becomes a process
instead of a function call. &quot;Agentic&quot; is mostly a marketing word, but in this
system it has a concrete meaning: evaluation quality depends on the harness,
the rubric, the exploration policy, and the recovery path, not only on the
base model.&lt;/p&gt;
&lt;p&gt;The same is true for observability. We ended up reading the agent&apos;s own JSONL
session logs from inside the sandbox when the vendor SDK did not surface token
usage consistently. The system also persists phase latencies as it moves
through fetching context, sandbox acquisition, cloning, review, extraction,
and persistence. This is boring accounting. It is also how you notice that an
evaluator is getting slower, more expensive, or less complete before the
scores start feeling wrong. The alternative is paying for runs you cannot
attribute and trusting evaluations you cannot inspect.&lt;/p&gt;
&lt;h2&gt;Disagreement is the product boundary&lt;/h2&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The disagreement between an automated judge and an expert is often treated as
noise to eliminate. Some of it is. If the system misses a file, misreads a
claim, or invents a mismatch, that is a bug.&lt;/p&gt;
&lt;p&gt;The final band of disagreement is where the expert&apos;s knowledge lives.&lt;/p&gt;
&lt;p&gt;In the auditor frame, that is exactly where the human should spend time. The
pipeline&apos;s job is not to make the model and the human agree on everything. It
is to make sure they agree on what is present, what is missing, and what has
evidence. Then the human can spend attention on what it means.&lt;/p&gt;
&lt;p&gt;That reverses the usual alignment target. If the system and the human disagree
on whether a claimed feature exists, the system needs work. If they disagree
on whether the implementation is prize-worthy, that may be the product working
as intended. High agreement on thoroughness is good. High agreement on taste
is suspicious if it means the rubric has crowded out judgment or the human has
stopped looking.&lt;/p&gt;
&lt;p&gt;A healthy pipeline converges on evidence and leaves room for human
disagreement over significance.&lt;/p&gt;
&lt;h2&gt;Looking ahead&lt;/h2&gt;
&lt;p&gt;The &lt;em&gt;Push to Prod&lt;/em&gt; experiment gave us a glimpse into what an agentic evaluator
could look like. The next step is turning that experiment into a measurable,
repeatable part of Devfolio&apos;s broader judging product stack.&lt;/p&gt;
&lt;p&gt;The audit should live where judging already happens: attached to the project,
broken down by rubric criterion, visible beside the judge&apos;s scoring/prize
assignment flow, and backed by citations into the submission and repository. A
judge should be able to inspect the evidence, accept or override the AI&apos;s
assessment, and continue with the normal judging flow. For organizers and
sponsors, this enables configuring when audits run, which profiles apply to
which tracks or prizes, and how much of the audit is shown to judges. We treat
human overrides and disagreements as first-class product data.&lt;/p&gt;
&lt;p&gt;The evaluator itself can change shape. We have run the single-judge version. A
small panel of cheaper models may beat a single expensive one, especially on
prize-deciding runs. Whether you want one general agent or several specialized
ones is also open. We do not have enough runs to take a side yet.&lt;/p&gt;
&lt;p&gt;Hackathon judging is the clearest version of the problem, and the same
constraint appears elsewhere in Devfolio&apos;s product surface. Devfolio sits
between builders and scarce attention. Hackathons have many teams, a short
window, a small judging panel, and real consequences for who gets noticed. The
same pattern shows up elsewhere in our world: curators deciding which projects
to feature, ecosystem teams looking for promising builders, sponsors trying to
understand what actually came out of a track, internal teams comparing many
artifacts without reducing them to who wrote the best pitch.&lt;/p&gt;
&lt;p&gt;These workflows differ from judging in their risk profile. A talent-search
workflow has different failure modes. A showcase page is not a prize decision.
A sponsor report is not an evaluation rubric. They share one operational
constraint: expert attention runs out before the artifacts do.&lt;/p&gt;
&lt;p&gt;The useful system is one that splits thoroughness from taste, routes each
operation to the resource with the right cost and error profile, and makes the
boundary between machine audit and human authority explicit.&lt;/p&gt;
&lt;p&gt;That is the sense in which the machine can be discerning. Not because it has
taste. Because it can learn to tell the difference between a claim and
evidence for that claim; between a working implementation and a well-written
description of one; between a score that should move automatically and a
judgment call that belongs with a person.&lt;/p&gt;
&lt;p&gt;Every serious submission still needs a human decision. The point of the system
is to make sure that decision begins from contact with the artifact: the repo,
the demo, the cited source, the thing the team actually built. A discerning
machine does not replace the judge. It helps ensure the judge is looking at
the work itself.&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://eugeneyan.com/writing/llm-evaluators/&quot;&gt;Eugene Yan - &lt;em&gt;Evaluating the Effectiveness of LLM Evaluators.&lt;/em&gt; calibration
against human–human agreement&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://softwaredoug.com/blog/2025/11/02/llm-judges-arent-the-shortcut-you-think&quot;&gt;Doug Turnbull - &lt;em&gt;LLM Judges Aren&apos;t the Shortcut You Think.&lt;/em&gt; The value of
expert disagreement&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://x.com/synthesis_md/status/2037531446139814263/&quot;&gt;Judging at the Synthesis hackathon&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vitalik.eth.limo/general/2025/02/28/aihumans.html&quot;&gt;Vitalik Buterin - &lt;em&gt;Distilled human judgment&lt;/em&gt; as a reference frame for
scalable evaluation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.benkuhn.net/impact/&quot;&gt;Ben Kuhn - &lt;em&gt;Impact, Agency, and Taste.&lt;/em&gt; Taste as predictive models and
search heuristics&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Optimizing Information Retrieval for RAG Systems</title><link>https://swarnimwalavalkar.com/posts/information-retrieval-rag/</link><guid isPermaLink="true">https://swarnimwalavalkar.com/posts/information-retrieval-rag/</guid><description>Optimizing Information Retrieval for RAG Systems</description><pubDate>Sat, 04 Jan 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The following are notes from some of my learnings from studying and building
retrieval systems for RAG applications.&lt;/p&gt;
&lt;h2&gt;Full-Text Search vs Vector Search&lt;/h2&gt;
&lt;p&gt;Vector search excels at capturing semantic similarity, making it great for
understanding the general meaning and context of queries. However, it has
limitations, particularly when dealing with specific keyword-based queries or
named entities.&lt;/p&gt;
&lt;p&gt;For instance, when users search for names acronyms, or IDs (e.g.,
&lt;code&gt;claude-3.5-sonnet&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;This is where a hybrid approach shines;&lt;/p&gt;
&lt;p&gt;You can create a more robust and accurate retrieval system by combining:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Traditional full-text search for precise keyword matching&lt;/li&gt;
&lt;li&gt;Vector search for semantic understanding&lt;/li&gt;
&lt;li&gt;Metadata filtering to scope the search space&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;Hybrid Search&lt;/h2&gt;
&lt;p&gt;The decision to use hybrid search depends on your use case; For technical
documentation where users need to find specific API endpoints or error codes,
keyword search excels at exact matches.&lt;/p&gt;
&lt;p&gt;For a research paper database where users explore related concepts and
methodologies, semantic search might better capture topical relevance.&lt;/p&gt;
&lt;p&gt;For a knowledge base where users might search for specific terms but also need
contextually related information, a hybrid approach combines precise matching
with semantic understanding.&lt;/p&gt;
&lt;h3&gt;Combining Search Techniques&lt;/h3&gt;
&lt;p&gt;One straightforward approach to implementing hybrid search is to combine
traditional keyword matching with semantic search through score fusion.&lt;/p&gt;
&lt;p&gt;In this method, we first run both searches in parallel: a keyword search for
exact matches and a vector search for semantic similarity. Each returns a scored
list of results. These scores are then normalized and combined using a weighted
sum:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;final_score = α * keyword_score + (1 - α) * semantic_score
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Where &lt;code&gt;α&lt;/code&gt; is a tunable parameter which prioritizes certain documents based on
factors like their relevance to the search query, their ranking in the
individual lists, or other criteria.&lt;/p&gt;
&lt;p&gt;The result is a final list that integrates the strengths of both keyword and
semantic search methods.&lt;/p&gt;
&lt;h3&gt;Reciprocal Rank Fusion (RRF)&lt;/h3&gt;
&lt;p&gt;Another common approach to combine results is Reciprocal Rank Fusion (RRF). RRF
assigns higher weights to items that appear near the top of multiple result
lists.&lt;/p&gt;
&lt;p&gt;For each document d, the RRF score is calculated as:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;RRF(d) = Σ(r ∈ R) 1 / (k + r(d))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;d&lt;/code&gt; is a document&lt;/li&gt;
&lt;li&gt;&lt;code&gt;R&lt;/code&gt; is the set of rankers (retrievers)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;k&lt;/code&gt; is a smoothing constant that prevents disproportionate influence of
top-ranked items &lt;em&gt;(typically 60)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;r(d)&lt;/code&gt; is the rank of document &lt;code&gt;d&lt;/code&gt; in ranker &lt;code&gt;r&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, if a document ranks &lt;strong&gt;3rd&lt;/strong&gt; in keyword search and &lt;strong&gt;9th&lt;/strong&gt; in
semantic search with &lt;em&gt;&lt;code&gt;k=60&lt;/code&gt;&lt;/em&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;RRF = 1/(60 + 3) + 1/(60 + 9) = 0.0317
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Documents appearing in only one list get zero contribution from the other list.
The final results are sorted by descending RRF score.&lt;/p&gt;
&lt;p&gt;This method effectively balances results that perform well across multiple
search strategies while dampening the impact of outlier rankings.&lt;/p&gt;
&lt;p&gt;Reference implementation in Typescript:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function reciprocalRankFusion(
  allResults: Document[][],
  options: RRFOptions = {}
): DocumentWithRanks[] {
  const { k = 60, maxResults = 10, scoreThreshold = 0 } = options;

  const rrfScores = new Map&amp;lt;string, number&amp;gt;();
  const docDetails = new Map&amp;lt;
    string,
    Document &amp;amp; { ranks: Map&amp;lt;number, number&amp;gt; }
  &amp;gt;();

  // Process each result list
  allResults.forEach((resultList, retrieverId) =&amp;gt; {
    resultList.forEach((doc, rank) =&amp;gt; {
      const rrf = 1 / (k + (rank + 1));
      const currentScore = rrfScores.get(doc.id) || 0;
      rrfScores.set(doc.id, currentScore + rrf);

      // Store document details from first occurrence
      if (!docDetails.has(doc.id)) {
        docDetails.set(doc.id, {
          ...doc,
          ranks: new Map(),
        });
      }

      // Track rank in each retriever
      docDetails.get(doc.id)?.ranks.set(retrieverId, rank + 1);
    });
  });

  // Build final results
  const fusedResults: DocumentWithRanks[] = Array.from(rrfScores.entries())
    .filter(([_, score]) =&amp;gt; score &amp;gt;= scoreThreshold)
    .map(([id, score]) =&amp;gt; {
      const document = docDetails.get(id)!;

      return {
        ...document,
        rrf_score: score,
        ranks: Object.fromEntries(document.ranks) as {
          [retrieverId: number]: number;
        },
      };
    })
    .sort((a, b) =&amp;gt; (b.rrf_score ?? 0) - (a.rrf_score ?? 0))
    .slice(0, maxResults);


&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;Query Reformulation&lt;/h2&gt;
&lt;p&gt;Raw user queries often lack context or contain ambiguous references. Rather than
taking these queries at face value, query reformulation acts as a preprocessing
step that transforms them into more complete, self-contained expressions.&lt;/p&gt;
&lt;p&gt;The goal is to add implicit context that users typically omit, resolve ambiguous
references, and expand queries with relevant terms.&lt;/p&gt;
&lt;p&gt;For instance, a query like &lt;em&gt;&quot;How did we do this quarter?&quot;&lt;/em&gt; might be reformulated
to &lt;em&gt;&quot;What is the revenue for Q1 2025?&quot;&lt;/em&gt; - adding both the specific metric
(&lt;code&gt;revenue&lt;/code&gt;) and temporal context (&lt;code&gt;Q1 2025&lt;/code&gt;) that was implicit in the original
query.&lt;/p&gt;
&lt;p&gt;One way to implement this is to maintain a context window containing recent
conversation history, currently visible information, and relevant system state.&lt;/p&gt;
&lt;p&gt;An LLM can then be used to reformulate queries by identifying contextual
references, resolving pronouns, and expanding abbreviated expressions. For
example, &lt;em&gt;&quot;Find similar docs&quot;&lt;/em&gt; might become &lt;em&gt;&quot;Find documentation similar to the
current deployment guide&quot;&lt;/em&gt; when reformulated with appropriate context.&lt;/p&gt;
&lt;p&gt;The key is ensuring that reformulated queries are self-contained while
preserving the original intent. This makes them more effective for downstream
search operations, whether using keyword, semantic, or hybrid approaches.&lt;/p&gt;
&lt;h2&gt;Feature and Entity Extraction&lt;/h2&gt;
&lt;p&gt;Many search queries contain specific attributes that are better handled through
structured queries. By extracting these features first, we can leverage
traditional search infrastructure more effectively.&lt;/p&gt;
&lt;p&gt;We can use LLMs to extract various features from the reformulated query. Each
feature extractor can run in parallel and should focus on specific attributes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Temporal expressions (&quot;last week&quot;, &quot;Q1&quot;, &quot;2024&quot;)&lt;/li&gt;
&lt;li&gt;Named entities (people, organizations, products)&lt;/li&gt;
&lt;li&gt;Numerical ranges (&quot;over 500&quot;, &quot;between 10-20&quot;)&lt;/li&gt;
&lt;li&gt;Status indicators (&quot;completed&quot;, &quot;pending&quot;, &quot;failed&quot;)&lt;/li&gt;
&lt;li&gt;Technical identifiers (API endpoints, error codes)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, given the query &lt;em&gt;&quot;Show me failed deployments from last week for the
auth service&quot;&lt;/em&gt;, feature extraction might yield:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;deployed_at&quot;: {
    &quot;range&quot;: &quot;2024-12-28/2025-01-03&quot;,
    &quot;confidence&quot;: 0.95
  },
  &quot;status&quot;: {
    &quot;value&quot;: &quot;failed&quot;,
    &quot;confidence&quot;: 0.98
  },
  &quot;service&quot;: {
    &quot;value&quot;: &quot;auth&quot;,
    &quot;confidence&quot;: 0.99
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Re-ranking&lt;/h2&gt;
&lt;p&gt;Effective re-ranking strategies are helpful for surfacing the most relevant
documents. Here are two approaches,&lt;/p&gt;
&lt;p&gt;These strategies are helpful independently but most powerful when combined. The
result should be a more robust ordering that considers both semantic relevance
and metadata compatibility.&lt;/p&gt;
&lt;h3&gt;Heuristic Re-ranking&lt;/h3&gt;
&lt;p&gt;Heuristic re-ranking employs efficient algorithms that leverage readily
available signals. With metadata signals through simple, fast heuristics, we can
quickly improve ranking quality:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Recency Bias&lt;/strong&gt;: For queries requiring current information (&lt;em&gt;&quot;current
status&quot;&lt;/em&gt;, &lt;em&gt;&quot;ongoing issues&quot;&lt;/em&gt;), apply time-decay functions to favor newer
documents.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Entity Matching&lt;/strong&gt;: Boost documents that reference entities (people,
organizations, locations) mentioned in the query. If someone searches for
&quot;budget proposals from marketing team&quot;, documents containing marketing team
members get prioritized.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Category Alignment&lt;/strong&gt;: Leverage document categories or tags when queries
suggest specific content types (&lt;em&gt;&quot;technical documentation&quot;&lt;/em&gt;, &lt;em&gt;&quot;financial
reports&quot;&lt;/em&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This heuristic re-ranking is fast, but can sometimes miss subtle nuances.&lt;/p&gt;
&lt;h3&gt;Re-ranking with Cross-Encoders&lt;/h3&gt;
&lt;p&gt;Cross-encoders look at queries and documents together, unlike traditional
embedding models that process them separately. This joint analysis leads to more
nuanced relevance judgments — they can better understand context, catch subtle
relationships, and make more accurate relevance decisions.&lt;/p&gt;
&lt;p&gt;For model selection, a general-purpose models like
&lt;a href=&quot;https://huggingface.co/cross-encoder/ms-marco-MiniLM-L-12-v2&quot;&gt;ms-marco-MiniLM&lt;/a&gt;
will be good enough in most cases. But consider fine-tuning if your use-case
truly warrants it.&lt;/p&gt;
&lt;h2&gt;Closing Thoughts&lt;/h2&gt;
&lt;p&gt;The most robust retrieval solutions often combine multiple approaches. The goal
is to build systems that leverage both the semantic understanding of embeddings
and the precision of traditional search methods.&lt;/p&gt;
&lt;p&gt;The key is choosing the right combination of techniques based on your specific
use case, and gradually add complexity only where it demonstrably improves
results.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;https://supabase.com/docs/guides/ai/hybrid-search&lt;/li&gt;
&lt;li&gt;https://learn.microsoft.com/en-us/azure/search/hybrid-search-ranking#how-rrf-ranking-works&lt;/li&gt;
&lt;li&gt;https://en.wikipedia.org/wiki/Query_understanding&lt;/li&gt;
&lt;li&gt;https://jxnl.co/writing/2023/09/17/rag-is-more-than-embeddings/#improving-the-rag-model-with-query-understanding&lt;/li&gt;
&lt;li&gt;https://haystack.deepset.ai/blog/query-expansion&lt;/li&gt;
&lt;li&gt;https://www.sbert.net/examples/applications/cross-encoder/README.html&lt;/li&gt;
&lt;li&gt;https://www.sbert.net/examples/applications/retrieve_rerank/README.html&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>The Socratic Method</title><link>https://swarnimwalavalkar.com/posts/socratic-method/</link><guid isPermaLink="true">https://swarnimwalavalkar.com/posts/socratic-method/</guid><description>The Socratic Method</description><pubDate>Sat, 10 Sep 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;To put it into action, follow this general structure:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Start with open-ended questions.&lt;/li&gt;
&lt;li&gt;Propose ideas based on these questions.&lt;/li&gt;
&lt;li&gt;Probe these ideas with progressive questioning.&lt;/li&gt;
&lt;li&gt;Repeat 2/3 until the best ideas are developed.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here&apos;s a process of how you might apply Socratic Questioning:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Start asking questions: What&apos;s the problem you are trying to solve? We often
waste time and energy trying to solve the &quot;wrong&quot; problem. Identify the
“right” problem before you try to solve it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Propose your current thinking on the problem: What is your hypothesis? What
are the origins of that thinking?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Open the floor for targeted questioning: Why do you think this? Is the
thinking too vague? What is it based upon?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Challenge the assumptions underlying the original thinking: Why do you believe
this to be true? How do you know it’s true? How would you know if you were
wrong? Identify the source of beliefs on a problem. Be ruthless in evaluating
their integrity and validity.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Evaluate the evidence used to support the thinking: What concrete evidence do
I have? How credible is it? What “hidden evidence” may exist?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Understand the consequences of being wrong: Can an error be quickly fixed? How
costly is this mistake? Always understand the stakes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Evaluate potential alternatives: What alternative beliefs or viewpoints might
exist? Why might they be superior? Why do others believe them to be true? What
do they know that I don’t? Evaluate them on their merits and ask these same
fundamental questions about them.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After zooming in, zoom out: What was my original thinking? Was it correct? If
not, where did I err? What conclusions can I draw from the process about
systemic errors in my thinking?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;https://www.sahilbloom.com/newsletter/superhuman-effort-socratic-questioning-more&lt;/p&gt;
</content:encoded></item><item><title>Monads in Functional Programming</title><link>https://swarnimwalavalkar.com/posts/haskell-monads/</link><guid isPermaLink="true">https://swarnimwalavalkar.com/posts/haskell-monads/</guid><description>Monads in Functional Programming</description><pubDate>Sat, 25 Dec 2021 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Monads in Haskell&lt;/h1&gt;
&lt;p&gt;In functional programming, Monads are an abstraction used to structure programs&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Help reduce complicated sequences of functions into “a pipeline” of actions&lt;/li&gt;
&lt;li&gt;Abstract away control flow&lt;/li&gt;
&lt;li&gt;Facilitate side-effects&lt;/li&gt;
&lt;li&gt;Manage external data interactions&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;class Monad m where
  return :: a					-&amp;gt; m a
  (&amp;gt;&amp;gt;=)  :: m a -&amp;gt; (a -&amp;gt; m b) 	-&amp;gt; m b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Monads are abstraction used to help structure programs and help easily achieve
some functionality which would be difficult to achieve otherwise.For example,
they help achieve side-effects which would be required in the real world.&lt;/p&gt;
&lt;p&gt;Monads in Haskell are defined as a Typeclass.&lt;/p&gt;
&lt;p&gt;We make things “monadic” by making them an instance of this typeclass. 2 main
operations defined by the typeclass:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lifting: take a non-monadic value and turn it into a monadic value&lt;/li&gt;
&lt;li&gt;Binding: monadic value and function that return a monadic value
&lt;ul&gt;
&lt;li&gt;The bind operator can have different semantics for different monads&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Functors and Aplicatives&lt;/h3&gt;
&lt;p&gt;Functors are things that can be mapped over&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fmap::(a -&amp;gt; b) -&amp;gt; f a -&amp;gt; f b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Applicatives are functors that can be applied&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pure  :: a -&amp;gt; f a
(&amp;lt;*&amp;gt;) :: f(a -&amp;gt; b) -&amp;gt; f a -&amp;gt; f b
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;p&gt;A monad on category C consists of an endofunctor (a functor mapping a category
to itself), T: C -&amp;gt; C along with two natural transformations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;1_C -&amp;gt; T where 1C denotes the identity functor on C, and&lt;/li&gt;
&lt;li&gt;T^2 -&amp;gt; T where T^2 is the functor T to T from C to C&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These are required to fulfill coherence conditions&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Monad m where
	return :: a					-&amp;gt; m a
	(&amp;gt;&amp;gt;=) :: m a -&amp;gt; (a-&amp;gt;m b)	-&amp;gt; m b
	(&amp;gt;&amp;gt;) :: m a -&amp;gt; m b			-&amp;gt; m b
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Coherence Conditions&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Left identity&lt;/strong&gt;: The first monad law states that if we take a value, put it in
a default context with return and then feed it to a function by using &amp;gt;&amp;gt;=, it’s
the same as just taking the value and applying the function to it.
&lt;code&gt;return a &amp;gt;&amp;gt;= f ≡ f a&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Right identity&lt;/strong&gt;: The second law states that if we have a monadic value and we
use &amp;gt;&amp;gt;= to feed it to return, the result is our original monadic value.
&lt;code&gt;m &amp;gt;&amp;gt;= return ≡ m&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Associativity:&lt;/strong&gt; The final monad law says that when we have a chain of monadic
function applications with &lt;code&gt;&amp;gt;&amp;gt;=&lt;/code&gt;, it shouldn’t matter how they’re nested.
&lt;code&gt;(m &amp;gt;&amp;gt;= f) &amp;gt;&amp;gt;= g ≡ m &amp;gt;&amp;gt;= (\x -&amp;gt; f x &amp;gt;&amp;gt;= g)&lt;/code&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Monads for Side-Effects&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Eg. IO&lt;/strong&gt; Monads in Haskell can function as &quot;containers&quot; that carry &quot;extra
information&quot; apart from the value inside that functions need not worry about.
Here, the &quot;information&quot; can be used as the action that performs IO&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;instance Monad IO where
	return :: a -&amp;gt; IO a
	(&amp;gt;&amp;gt;=) :: IO a -&amp;gt; a (a -&amp;gt; IO b) -&amp;gt; IO b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Example as a REPL reading/writing to a terminal&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;flushStr :: String -&amp;gt; IO ()
readPrompt :: String -&amp;gt; IO String
evalString :: String -&amp;gt; IO String
until_ :: Monad m =&amp;gt; (a -&amp;gt; Bool) -&amp;gt; m a -&amp;gt; (a -&amp;gt; m ()) -&amp;gt; m ()
runRepl :: IO ()
main :: IO ()
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Monads for Control Flow&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Eg. Error Handling&lt;/strong&gt; We define all types of errors we want to catch and throw
as &lt;code&gt;MonadicError&lt;/code&gt; We define a type for functions that may throw a &lt;code&gt;MonadicError&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type ThrowsError = Either MondaicError
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Either&lt;/code&gt; is another instance of a monad, The &quot;extra information&quot; in this case is
whether the error occurred.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;instance (Error e) =&amp;gt; Monad (Either e) where
	return x = Right x
	Right x &amp;gt;&amp;gt; f = f x
	Left err &amp;gt;&amp;gt;= f = Left err
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If &lt;code&gt;(&amp;gt;==)&lt;/code&gt; sees an error it simply passes that error through without subsequent
computations, else passes the value along&lt;/p&gt;
&lt;h2&gt;Monad Transformers&lt;/h2&gt;
&lt;p&gt;Take our 2 Error Handling and IO Monads for example, say we need to use their
behavior functionality simultaneously. We use monad transformers to combine
functionality of multiple monads We use ExceptT, a monad transformer that adds
exceptions to other monads&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;newtype ExceptT e m a :: * -&amp;gt; (* -&amp;gt; *) -&amp;gt; * -&amp;gt; *
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The combined Monad would then be:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type IOThrowsError = ExceptT MonadicError IO
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Monads for Environment Management&lt;/h2&gt;
&lt;p&gt;Haskell has no notion of mutable state. Each function has an environment storing
values for each of its args and vars.&lt;/p&gt;
&lt;p&gt;We use a feature called IORef that helps us hold the environment state within
the IO monad We then simply access this environment mutating its state as
required, and keep passing it around on each evaluation cycle.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Env = IORef[(String, IORef SomeVal)]

eval :: Env -&amp;gt; SomeVal -&amp;gt; IOThrowsError SomeVal
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>The Essence of Computer Science</title><link>https://swarnimwalavalkar.com/posts/sicp/</link><guid isPermaLink="true">https://swarnimwalavalkar.com/posts/sicp/</guid><description>The Essence of Computer Science</description><pubDate>Wed, 09 Jun 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;From -&amp;gt; https://youtu.be/-J_xL4IGhJA?si=NHglUsKKpbT_8jLY&lt;/p&gt;
&lt;p&gt;“I think that it’s extraordinarily important that we in computer science keep
fun in computing. When it started out, it was an awful lot of fun.&lt;/p&gt;
&lt;p&gt;Of course, the paying customers got shafted every now and then, and after a
while we began to take their complaints seriously. We began to feel as if we
really were responsible for the successful, error-free perfect use of these
machines. I don’t think we are. I think we’re responsible for stretching them,
setting them off in new directions, and keeping fun in the house.&lt;/p&gt;
&lt;p&gt;I hope the field of computer science never loses its sense of fun. Above all, I
hope we don’t become missionaries. Don’t feel as if you’re Bible salesmen. The
world has too many of those already. What you know about computing other people
will learn. Don’t feel as if the key to successful computing is only in your
hands. What’s in your hands, I think and hope, is intelligence: the ability to
see the machine as more than when you were first led up to it, that you can make
it more.”&lt;/p&gt;
&lt;p&gt;—Alan J. Perlis (April 1, 1922 – February 7, 1990)&lt;/p&gt;
&lt;h2&gt;Computer Science is a terrible name&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;First, Its not a science, And its also not about computers&lt;/li&gt;
&lt;li&gt;Computer Science has a lot in common with magic than it does with science&lt;/li&gt;
&lt;li&gt;Computer Science is no more about computers than Physics is about particle
accelerators and Geometry about surveying instruments&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When a field is in its infancy and you don&apos;t really understand it really well,
its really easy to confuse the essence of what you&apos;re doing with the tools that
you use.&lt;/p&gt;
&lt;h2&gt;The Essence of Computer Science&lt;/h2&gt;
&lt;p&gt;Its really about formalizing an intuition about process; about developing a way
to talk precisely about how to do things&lt;/p&gt;
&lt;h2&gt;Declarative Knowledge vs Imperative Knowledge&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Declarative Knowledge&lt;/strong&gt; is knowledge that talks about what is true. It makes
statements of fact that one can use to try to reason about things.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Imperative Knowledge&lt;/strong&gt; talks about &quot;how to&quot; knowledge. It tends to describe a
specific sequence of steps that characterize the evolution of a process by which
one can deduce information, transforming one set of facts into a new set.&lt;/p&gt;
</content:encoded></item><item><title>Distributed Systems</title><link>https://swarnimwalavalkar.com/posts/distributed-systems/</link><guid isPermaLink="true">https://swarnimwalavalkar.com/posts/distributed-systems/</guid><description>Distributed Systems</description><pubDate>Mon, 24 May 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A distributed system is a collection of autonomous computing elements that
appears to its users as a single coherent system.&lt;/p&gt;
&lt;h2&gt;Features of distributed systems:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A collection of computing elements (nodes) each able to behave differently&lt;/li&gt;
&lt;li&gt;Clients believe they&apos;re dealing with a single system. The Independent nodes
have to collaborate&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Autonomous Compute Units&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Fundamentally, nodes act Independently from each other&lt;/li&gt;
&lt;li&gt;Nodes communicate by exchanging messages (cf. event driven systems)&lt;/li&gt;
&lt;li&gt;Nodes have their own notion of time, ie. No global clock&lt;/li&gt;
&lt;li&gt;Relationship between nodes in a collection need to be managed (register which
nodes do or do not belong in the system)
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;open group:&lt;/strong&gt; any node can join the system, it can communicate with any
other node&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;closed group:&lt;/strong&gt; only members of a group can communicate with each other,
separate mechanism is needed for a node to leave or join a group&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Distributed systems are often organized as an &lt;em&gt;overlay network&lt;/em&gt;, where a node is
a process with a list of other nodes it can directly send messages to. There are
roughly two typed of overlay networks&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Structured Overlay:&lt;/strong&gt; Each node has a well-defined set of neighbors with whom
it can communicate. The nodes are organized in a tree or logical ring.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Unstructured Overlay:&lt;/strong&gt; Each node has a number of references to randomly
selected other nodes.&lt;/p&gt;
&lt;p&gt;An overlay network should, in principle, always be connected, meaning that
between any two nodes there is always a communication path allowing those nodes
to route messages from one to the other.&lt;/p&gt;
&lt;p&gt;cf: Peer-To-Peer (P2P) networks.&lt;/p&gt;
&lt;h3&gt;Single Coherent System&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;A distributed system should appear as a single coherent system.&lt;/li&gt;
&lt;li&gt;A distributed system is coherent if it behaves according to the expectations
of its users.&lt;/li&gt;
&lt;li&gt;In a single coherent system the collection of nodes as a whole operates the
same, no matter where, when, and how interaction between a user and the system
takes place.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;Design Goals&lt;/h2&gt;
&lt;h3&gt;Performance&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Distributing computation
&lt;ul&gt;
&lt;li&gt;Cons: network and latency bottlenecks - Tricks that help: caching, async
programming&lt;/li&gt;
&lt;li&gt;Pros: parallelism, client can pick geographically proximate server
&lt;ul&gt;
&lt;li&gt;Scalability:
&lt;ul&gt;
&lt;li&gt;ideally, performance would linearly increase with the addition of new
nodes &lt;code&gt;N x nodes -&amp;gt; N x throughput&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Need to balance based on some factor N
&lt;ul&gt;
&lt;li&gt;divide the state by N (In the example of a file system)
&lt;ul&gt;
&lt;li&gt;split by user&lt;/li&gt;
&lt;li&gt;split by file name&lt;/li&gt;
&lt;li&gt;Sharding or Partitioning&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Wont always work -&amp;gt; can only scale so far (potential drawbacks)
&lt;ul&gt;
&lt;li&gt;Global operations, eg search&lt;/li&gt;
&lt;li&gt;Load Imbalance
&lt;ul&gt;
&lt;li&gt;One very active user&lt;/li&gt;
&lt;li&gt;One very popular file
&lt;ul&gt;
&lt;li&gt;-&amp;gt; one particular server takes all the load, other remain idle&lt;/li&gt;
&lt;li&gt;= &lt;code&gt;N x nodes -&amp;gt; 1 x throughput&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Fault Tolerance&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Availability The system keeps on serving as it normally would under certain
kinds of failures
&lt;ul&gt;
&lt;li&gt;fail-over
&lt;ul&gt;
&lt;li&gt;active-passive
&lt;ul&gt;
&lt;li&gt;heartbeats are sent between 2 servers (active and passive)&lt;/li&gt;
&lt;li&gt;If the heartbeat is interrupted, passive server takes over the active
one&lt;/li&gt;
&lt;li&gt;downtime length can vary depending of whether the passive service was in
&quot;hot&quot; standby or has to do a &quot;cold&quot; startup&lt;/li&gt;
&lt;li&gt;Only the active server ever handles traffic&lt;/li&gt;
&lt;li&gt;Also refereed to as master-slave failover.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;replication
&lt;ul&gt;
&lt;li&gt;Master-Slave Replication
&lt;ul&gt;
&lt;li&gt;The master serves reads and writes, replicating writes to one or more
slaves, which serve only reads.&lt;/li&gt;
&lt;li&gt;Slaves can also replicate to additional slaves in a tree-like fashion.&lt;/li&gt;
&lt;li&gt;If the master goes offline, the system can continue to operate in
read-only mode until a slave is promoted to a master or a new master is
provisioned.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Master-Master Replication
&lt;ul&gt;
&lt;li&gt;Both masters serve reads and writes and coordinate with each other on
writes&lt;/li&gt;
&lt;li&gt;If either master goes down, the system can continue to operate with both
reads and writes&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Recoverability
&lt;ul&gt;
&lt;li&gt;The system gracefully recovers from failures and continues working correctly
&lt;ul&gt;
&lt;li&gt;store state on disk&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Consistency&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;CAP Theorem
&lt;ul&gt;
&lt;li&gt;Consistency - Every read receives the most recent write or an error&lt;/li&gt;
&lt;li&gt;Availability - Every request receives a response, without guarantee that it
contains the most recent version of the information&lt;/li&gt;
&lt;li&gt;Partition Tolerance - The system continues to operate despite arbitrary
partitioning due to network failures&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Networks aren&apos;t reliable, so you&apos;ll need to support partition tolerance. You&apos;ll
need to make a software tradeoff between consistency and availability.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;CP - consistency and partition tolerance&lt;/strong&gt; Waiting for a response from the
partitioned node might result in a timeout error. CP is a good choice if your
business needs require atomic reads and writes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;AP - availability and partition tolerance&lt;/strong&gt; Responses return the most
readily available version of the data available on any node, which might not
be the latest. Writes might take some time to propagate when the partition is
resolved.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AP is a good choice if the business needs allow for eventual consistency or when
the system needs to continue working despite external errors.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Topics&lt;/h2&gt;
&lt;h3&gt;Networking&lt;/h3&gt;
&lt;h3&gt;CDNs&lt;/h3&gt;
&lt;h3&gt;Caching&lt;/h3&gt;
&lt;h3&gt;Communication Protocols&lt;/h3&gt;
</content:encoded></item></channel></rss>