DEV Community

Aditya Agrawal
Aditya Agrawal

Posted on

I Stopped Treating AI as a Black Box and Started Building a Semantic Caching System from Scratch

Most AI projects today look something like this:

response = llm.invoke(prompt)
Enter fullscreen mode Exit fullscreen mode

It works.

It's powerful.

But one question kept bothering me:

Do I actually understand what's happening behind the scenes?

That's what led me to start building a Semantic Caching System from scratch.

Not by copying an existing GitHub repository.

Not by wrapping an LLM in another API.

But by implementing every component myself and understanding why it exists.


Why Semantic Caching?

Imagine you're building an AI chatbot.

A user asks:

"What is Semantic Caching?"

A few seconds later another user asks:

"Can you explain semantic caching?"

The wording is different.

But the intent is almost identical.

Traditional caching won't help because the strings aren't exactly the same.

Semantic caching solves this problem by understanding that two different sentences can have the same meaning.

Instead of recomputing the answer every time, we can reuse a previous response when two queries are semantically similar.

That means:

  • Faster responses
  • Lower compute costs
  • Better scalability
  • Reduced load on AI models

My Goal

Instead of building another AI application, I wanted to understand how one of its important building blocks actually works.

So I decided to build everything myself.

My learning rule is simple:

If I can't explain why a class exists, I shouldn't use it.


What I've Built So Far

The project is divided into independent modules instead of one large codebase.

Current components include:

  • Query preprocessing
  • Text normalization
  • Tokenization
  • Embedding generation
  • Cosine similarity engine
  • Semantic cache manager
  • Cache hit and miss detection
  • Cache eviction strategies
  • Logging
  • Performance metrics
  • FastAPI endpoints

Each module has a single responsibility, making the architecture easier to understand and extend.


The Development Process

Rather than writing thousands of lines of code at once, I'm building one class at a time.

For every class, I follow the same workflow:

  1. Understand the problem it solves
  2. Design the class
  3. Implement it
  4. Explain every line of code
  5. Test it
  6. Improve it
  7. Move to the next component

This approach is slower than following a tutorial, but I've learned far more from it.


What I'm Learning

Working on this project has already helped me understand concepts that are often hidden behind libraries:

Semantic Search

How can two different sentences be recognized as having similar meanings?

Embeddings

How can text be represented as mathematical vectors?

Cosine Similarity

How do we measure the similarity between two vectors?

Cache Management

How do we decide whether to reuse an existing response or compute a new one?

Cache Eviction

When memory becomes full, which cached items should be removed first?


Why I'm Avoiding the "Magic"

Modern AI libraries are incredible.

But they also make it very easy to skip understanding the fundamentals.

I wanted to know:

  • How embeddings work
  • Why cosine similarity works
  • Why semantic search works
  • Why caching improves performance
  • How these components communicate inside a real system

Building everything myself has answered many of those questions.


What's Next?

This project is still evolving.

The next steps include exploring how to make the architecture more production-oriented by integrating technologies such as:

  • Redis
  • Vector databases
  • Distributed caching
  • Kubernetes
  • Monitoring and metrics
  • Horizontal scaling

The idea isn't to build the biggest project.

It's to build one that teaches me something new every day.


Final Thoughts

One thing I've realized is that it's easy to build software that works.

It's much harder—and far more rewarding—to build software that you truly understand.

This project has reminded me that the best way to learn isn't by collecting frameworks.

It's by asking:

"Could I build this myself?"

That's the question I'm trying to answer, one class at a time.


If you're working on Backend Engineering, AI Infrastructure, or Distributed Systems, I'd love to hear how you approach learning complex systems from first principles.

Top comments (0)