<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rijul Rajesh</title>
    <description>The latest articles on DEV Community by Rijul Rajesh (@rijultp).</description>
    <link>https://dev.to/rijultp</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1207862%2F60f14114-548d-4857-87c3-87cd2e09375d.png</url>
      <title>DEV Community: Rijul Rajesh</title>
      <link>https://dev.to/rijultp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rijultp"/>
    <language>en</language>
    <item>
      <title>Stopping a Linux Service Isn't Always Enough. systemd Masking Explained</title>
      <dc:creator>Rijul Rajesh</dc:creator>
      <pubDate>Fri, 04 Sep 2026 19:51:50 +0000</pubDate>
      <link>https://dev.to/rijultp/stopping-a-linux-service-isnt-always-enough-systemd-masking-explained-550h</link>
      <guid>https://dev.to/rijultp/stopping-a-linux-service-isnt-always-enough-systemd-masking-explained-550h</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Rijul, and I'm building LiveReview — a blast-radius aware AI code review built for your business-critical systems. &lt;a href="https://github.com/HexmosTech/LiveReview/" rel="noopener noreferrer"&gt;Star us&lt;/a&gt; to help devs discover the project, give it a try, and share your feedback to help improve the product.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this article, we explore a specific feature of systemd, which is called &lt;strong&gt;masking&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you haven't heard about systemd, it's basically a system and service manager in Linux.&lt;/p&gt;

&lt;p&gt;It is responsible for doing things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Starting services when you turn on the system&lt;/li&gt;
&lt;li&gt;Stopping services&lt;/li&gt;
&lt;li&gt;Restarting services, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And &lt;code&gt;systemctl&lt;/code&gt; is the command you use to interact with systemd.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mask in systemd
&lt;/h3&gt;

&lt;p&gt;For more context, we start a service via:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl start service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl mask service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if we try to start this particular service, systemd will refuse.&lt;/p&gt;

&lt;p&gt;It can give errors like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Failed to start nginx.service:
Unit nginx.service is masked.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Where mask is useful
&lt;/h3&gt;

&lt;p&gt;Now, on immediately seeing the &lt;code&gt;mask&lt;/code&gt; command, it may not be immediately clear what its use is.&lt;/p&gt;

&lt;p&gt;Let me explain one situation.&lt;/p&gt;

&lt;p&gt;Suppose you have a server where you absolutely don't want Nginx to be running.&lt;/p&gt;

&lt;p&gt;In this case, you can try stopping it via:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl stop nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But some other script or process somehow starts it again.&lt;/p&gt;

&lt;p&gt;This is a problem.&lt;/p&gt;

&lt;p&gt;So you want to prevent it from ever being started.&lt;/p&gt;

&lt;p&gt;In such cases, &lt;code&gt;mask&lt;/code&gt; becomes useful.&lt;/p&gt;

&lt;p&gt;All you have to do is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl mask nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What happens when it's masked?
&lt;/h3&gt;

&lt;p&gt;When you mask a service, this is what happens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl mask nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;systemd makes a symlink for Nginx. Think of it as a link:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/etc/systemd/system/nginx.service
        ↓
     /dev/null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So systemd looks for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nginx.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and finds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/etc/systemd/system/nginx.service -&amp;gt; /dev/null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;systemd interprets that as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This unit is masked. Don't start it.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Wrapping up
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;mask&lt;/code&gt; is just one of many other commands we use.&lt;/p&gt;

&lt;p&gt;Here is an illustration of where &lt;code&gt;mask&lt;/code&gt; and &lt;code&gt;unmask&lt;/code&gt; fit within the broader range:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc9gvm7tjrwq9h3aimbf3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc9gvm7tjrwq9h3aimbf3.png" alt=" " width="799" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So that's about it for this article. See you in the next one.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;br&gt;
Your team's attention is limited, and the deluge of AI-generated code is making it harder to keep production stable while also shipping at high velocity.&lt;/em&gt;&lt;/p&gt;
&lt;em&gt;

&lt;p&gt;I'm building &lt;strong&gt;LiveReview&lt;/strong&gt;, a blast-radius aware AI code review built for your business-critical systems.&lt;/p&gt;

&lt;p&gt;Instead of presenting every diff with equal emphasis, &lt;strong&gt;LiveReview scores each change by blast radius — how far its impact reaches through your call graph — so you can focus attention where it actually matters.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Spend code review effort where business risk is highest — not spread evenly across every diff.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Try LiveReview on your codebase:&lt;/b&gt;&lt;/p&gt;

&lt;/em&gt;&lt;p&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hexmos.com/livereview" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvls0pq7nymbrll98je6s.png" alt="LiveReview Banner" width="800" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>linux</category>
    </item>
    <item>
      <title>How Does AI Know What's Inside an Image? Meet Vision Language Models</title>
      <dc:creator>Rijul Rajesh</dc:creator>
      <pubDate>Wed, 02 Sep 2026 19:29:03 +0000</pubDate>
      <link>https://dev.to/rijultp/how-does-ai-know-whats-inside-an-image-meet-vision-language-models-2m8o</link>
      <guid>https://dev.to/rijultp/how-does-ai-know-whats-inside-an-image-meet-vision-language-models-2m8o</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Rijul, and I'm building LiveReview — a blast-radius aware AI code review built for your business-critical systems. &lt;a href="https://github.com/HexmosTech/LiveReview/" rel="noopener noreferrer"&gt;Star us&lt;/a&gt; to help devs discover the project, give it a try, and share your feedback to help improve the product.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Do you interact with AI models where you put in an image and then it processes it?&lt;/p&gt;

&lt;p&gt;Do you wonder what these models are and what is happening behind the scenes?&lt;/p&gt;

&lt;p&gt;This is called a &lt;strong&gt;VLM&lt;/strong&gt;, or &lt;strong&gt;Vision-Language Model&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A VLM combines vision and language capabilities so that it can process visual information along with text.&lt;/p&gt;

&lt;p&gt;A simple way to think about it is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LLM → Works primarily with text&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VLM → Works with images and text&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is a simplified mental model, since VLM architectures can vary. Under the hood, a VLM often combines a &lt;strong&gt;vision encoder&lt;/strong&gt;, a &lt;strong&gt;connector or projector&lt;/strong&gt;, and a &lt;strong&gt;language model&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So, how does a VLM actually "see" an image?&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does a VLM Actually See?
&lt;/h2&gt;

&lt;p&gt;An LLM works with tokens.&lt;/p&gt;

&lt;p&gt;But an image is not naturally made up of language tokens.&lt;/p&gt;

&lt;p&gt;So we need a way to convert the visual information in an image into something the language model can work with.&lt;/p&gt;

&lt;p&gt;A simplified view looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Image
  ↓
Vision Encoder
  ↓
Visual Representations
  ↓
Vision-Language Connector
  ↓
Language Model
  ↓
Text Response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break this down.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vision Encoder
&lt;/h2&gt;

&lt;p&gt;The first important component is the &lt;strong&gt;Vision Encoder&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Its job is to process the image and turn the visual information into numerical representations that the rest of the model can work with.&lt;/p&gt;

&lt;p&gt;Depending on the vision architecture, the image may be divided into smaller regions or &lt;strong&gt;patches&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6xscriz1uxxt5b94426d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6xscriz1uxxt5b94426d.png" alt=" " width="648" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each part is processed by the vision encoder, which produces &lt;strong&gt;visual representations&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;These representations don't simply mean "this patch is a dog" or "this patch is blue."&lt;/p&gt;

&lt;p&gt;The vision encoder builds representations that capture visual patterns and context, which can help the model understand things such as shapes, objects, colors, text, spatial relationships, and other visual information.&lt;/p&gt;

&lt;p&gt;The exact way this happens depends on the vision encoder architecture. Patch-based processing is common, but it is not universal to every vision system.&lt;/p&gt;

&lt;p&gt;The result is essentially a representation of the image that can be passed toward the language model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Perception and Grounding
&lt;/h2&gt;

&lt;p&gt;Now that we have visual representations, we can talk about two important capabilities: &lt;strong&gt;perception&lt;/strong&gt; and &lt;strong&gt;grounding&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Perception
&lt;/h3&gt;

&lt;p&gt;Perception is about understanding the visual content.&lt;/p&gt;

&lt;p&gt;It is not just:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What objects are in this image?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It can also involve understanding relationships between objects, actions, scenes, and the overall visual context.&lt;/p&gt;

&lt;p&gt;For example, given an image of a person riding a bicycle, the model may understand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Person
  ↓
riding
  ↓
Bicycle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So perception is about building an understanding of what is happening in the image.&lt;/p&gt;

&lt;h3&gt;
  
  
  Grounding
&lt;/h3&gt;

&lt;p&gt;Grounding is about connecting language to specific parts of the visual input.&lt;/p&gt;

&lt;p&gt;For example, if we ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Where is the dog?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F22jy25e6zu2mbicabo1h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F22jy25e6zu2mbicabo1h.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The model could associate the word &lt;strong&gt;dog&lt;/strong&gt; with a particular region of the image.&lt;/p&gt;

&lt;p&gt;A simplified representation could be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"center of the image"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In more technical systems, grounding can involve associating language with &lt;strong&gt;regions, objects, points, or other parts of an image&lt;/strong&gt;. Bounding boxes are one common way of representing this, but they are not the only form of grounding.&lt;/p&gt;

&lt;p&gt;This becomes especially useful when we want an AI system to not only identify something, but also connect that understanding to &lt;strong&gt;where or what it refers to in the image&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  VLM vs Multimodal LLM
&lt;/h2&gt;

&lt;p&gt;You may also hear another term:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multimodal LLM&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So what is the difference?&lt;/p&gt;

&lt;p&gt;The terminology isn't perfectly standardized, but a useful way to think about it is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VLM&lt;/strong&gt; usually emphasizes models that connect &lt;strong&gt;vision and language&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Examples include models such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Qwen-VL&lt;/li&gt;
&lt;li&gt;Qwen2.5-VL&lt;/li&gt;
&lt;li&gt;Llama Vision&lt;/li&gt;
&lt;li&gt;Pixtral&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Multimodal LLM&lt;/strong&gt; is a broader term often used for language models that can work with multiple types of inputs or outputs, such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Text
Images
Audio
Video
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, conceptually, you can think of VLMs as one part of the broader multimodal AI space.&lt;/p&gt;

&lt;p&gt;The exact terminology can vary depending on the model and how its creators describe it, so these categories should be treated as a useful mental model rather than strict technical boundaries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;So, the basic idea behind a VLM is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Image
  ↓
Vision Encoder
  ↓
Visual Representations
  ↓
Connector / Projector
  ↓
Language Model
  ↓
Response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The vision side processes the image and produces visual representations.&lt;/p&gt;

&lt;p&gt;The connector helps make those representations usable by the language model.&lt;/p&gt;

&lt;p&gt;The language model then uses those visual representations together with the text input to generate a response.&lt;/p&gt;

&lt;p&gt;VLMs become especially useful when text alone isn't enough to express what we want an AI system to understand.&lt;/p&gt;

&lt;p&gt;For example, instead of describing a UI design, diagram, screenshot, chart, or photograph entirely through text, we can simply give the model the image.&lt;/p&gt;

&lt;p&gt;In that sense, VLMs give AI systems a way to work with visual information alongside language, making it possible to interact with information that previously had to be described using words.&lt;/p&gt;

&lt;p&gt;So that's it about this article, see you on the next one!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;&lt;br&gt;
Your team's attention is limited, and the deluge of AI-generated code is making it harder to keep production stable while also shipping at high velocity.&lt;/em&gt;&lt;/p&gt;
&lt;em&gt;

&lt;p&gt;I'm building &lt;strong&gt;LiveReview&lt;/strong&gt;, a blast-radius aware AI code review built for your business-critical systems.&lt;/p&gt;

&lt;p&gt;Instead of presenting every diff with equal emphasis, &lt;strong&gt;LiveReview scores each change by blast radius — how far its impact reaches through your call graph — so you can focus attention where it actually matters.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Spend code review effort where business risk is highest — not spread evenly across every diff.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Try LiveReview on your codebase:&lt;/b&gt;&lt;/p&gt;

&lt;/em&gt;&lt;p&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hexmos.com/livereview" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvls0pq7nymbrll98je6s.png" alt="LiveReview Banner" width="800" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>vlm</category>
      <category>llm</category>
    </item>
    <item>
      <title>How AI Stores Millions of Vectors Without Using Tons of Memory</title>
      <dc:creator>Rijul Rajesh</dc:creator>
      <pubDate>Sat, 29 Aug 2026 19:55:59 +0000</pubDate>
      <link>https://dev.to/rijultp/ever-wondered-how-ai-stores-millions-of-embeddings-47ek</link>
      <guid>https://dev.to/rijultp/ever-wondered-how-ai-stores-millions-of-embeddings-47ek</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Rijul, and I'm building LiveReview — a blast-radius aware AI code review built for your business-critical systems. &lt;a href="https://github.com/HexmosTech/LiveReview/" rel="noopener noreferrer"&gt;Star us&lt;/a&gt; to help devs discover the project, give it a try, and share your feedback to help improve the product.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In any sort of AI application, we have the concept of &lt;strong&gt;vectors&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Vectors come in different shapes and sizes.&lt;/p&gt;

&lt;p&gt;Especially when they are large, we need a good way to manage them.&lt;/p&gt;

&lt;p&gt;One way to solve this is by &lt;strong&gt;compressing these large vectors&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is especially relevant to &lt;strong&gt;FAISS&lt;/strong&gt;, which I explained in &lt;a href="https://dev.to/rijultp/how-does-an-ai-find-the-most-similar-information-faiss-explained-1lhh"&gt;another article of mine&lt;/a&gt;, where it is a library for efficient similarity search over large collections of vectors. &lt;strong&gt;Product Quantization is one of the techniques FAISS supports for vector compression and efficient search.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's visualize this with a problem.&lt;/p&gt;




&lt;h4&gt;
  
  
  The Problem
&lt;/h4&gt;

&lt;p&gt;Suppose you have a customer support RAG app&lt;/p&gt;

&lt;p&gt;And for that, you have 10 million embeddings containing chunks from product documentation, FAQs, and support articles.&lt;/p&gt;

&lt;p&gt;Each of these embeddings has 768 dimensions. Each of those 768 dimensions is used to store a numerical representation of the meaning of that text.&lt;/p&gt;

&lt;p&gt;Now, each dimension is a &lt;code&gt;float&lt;/code&gt;, so we can think of it as a &lt;strong&gt;32-bit float&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;32 bits means 4 bytes.&lt;/p&gt;

&lt;p&gt;So:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;768 × 4 = 3072 bytes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's roughly &lt;strong&gt;3 KB per 768-dimensional vector&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now let's scale this to 10 million embeddings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10,000,000 × 3 KB = 30 GB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So this 3 KB per vector becomes &lt;strong&gt;30 GB&lt;/strong&gt; when scaled to 10 million embeddings.&lt;/p&gt;

&lt;p&gt;30 GB is roughly the size of a decent-sized game or several high-quality movies.&lt;/p&gt;

&lt;p&gt;So imagine searching among this much vector data. It can get expensive.&lt;/p&gt;

&lt;p&gt;Let's look at the numbers again.&lt;/p&gt;

&lt;p&gt;We have &lt;strong&gt;10 million embeddings&lt;/strong&gt;. We can't change that.&lt;/p&gt;

&lt;p&gt;But we have &lt;strong&gt;3 KB per vector&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;What if we could compress that 3 KB further, so that when we scale it to millions of embeddings, we get a much lower storage requirement?&lt;/p&gt;

&lt;p&gt;The technique used to do this is called &lt;strong&gt;Product Quantization&lt;/strong&gt;, or &lt;strong&gt;PQ&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let's look at the basic idea behind PQ.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Basic Idea
&lt;/h3&gt;

&lt;p&gt;Imagine I have this vector:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[0.21, 0.73, -0.15, 0.91, 0.34, -0.52, 0.18, 0.66]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of storing all these floating-point numbers, PQ:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Splits the vector into smaller pieces&lt;/li&gt;
&lt;li&gt;Learns representative patterns for each piece&lt;/li&gt;
&lt;li&gt;Replaces each piece with the ID of its closest codeword&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see an example.&lt;/p&gt;

&lt;p&gt;Suppose we split this 8-dimensional vector into 4 pieces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[0.21, 0.73] [-0.15, 0.91] [0.34, -0.52] [0.18, 0.66]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, based on these subvectors, we have a &lt;strong&gt;separate codebook for each subvector position&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For the first position, let's assume this is the codebook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Codebook 1

ID 0 → [0.10, 0.70]
ID 1 → [0.20, 0.75]
ID 2 → [0.80, 0.10]
ID 3 → [-0.20, 0.90]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's match the first subvector to its closest vector in the codebook.&lt;/p&gt;

&lt;p&gt;Our first subvector is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[0.21, 0.73]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks pretty close to &lt;strong&gt;ID 1&lt;/strong&gt;, which is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[0.20, 0.75]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So instead of storing the entire subvector, we store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly, we do the same thing for the other subvectors.&lt;/p&gt;

&lt;p&gt;For:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[-0.15, 0.91]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we have another codebook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Codebook 2

ID 0 → [-0.30, 0.80]
ID 1 → [0.10, 0.40]
ID 2 → [-0.20, 0.90]
ID 3 → [0.70, 0.20]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The closest one is &lt;strong&gt;ID 2&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And we repeat this process for the remaining subvectors.&lt;/p&gt;

&lt;p&gt;So the original vector:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[0.21, 0.73] [-0.15, 0.91] [0.34, -0.52] [0.18, 0.66]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can be represented as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[1, 2, 3, 0]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each number is an index into a different codebook.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    Original vector
                          │
          ┌───────────────┼───────────────┐
          ↓               ↓               ↓
      Subvector 1     Subvector 2     Subvector 3 ...
          │               │               │
          ↓               ↓               ↓
     Codebook 1       Codebook 2       Codebook 3
          │               │               │
          ↓               ↓               ↓
        ID 17           ID 42           ID 8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Compression
&lt;/h3&gt;

&lt;p&gt;So now we have the vector in this form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[1, 2, 3, 0]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each ID can be stored using just a few bits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For this example, let's assume each ID is stored using 1 byte.&lt;/strong&gt;&lt;br&gt;
(With only 4 possible IDs, 2 bits would technically be enough, but we'll use 1 byte here to keep the example simple.)&lt;/p&gt;

&lt;p&gt;We have 4 subvectors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;4 × 1 byte = 4 bytes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Originally, we had 8 floating-point numbers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8 × 4 bytes = 32 bytes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the size went down from &lt;strong&gt;32 bytes to 4 bytes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And remember, this is just an 8-dimensional vector.&lt;/p&gt;

&lt;p&gt;Real embeddings are often hundreds or thousands of dimensions.&lt;/p&gt;

&lt;p&gt;For example, a 768-dimensional embedding stored as 32-bit floats requires:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;768 × 4 = 3072 bytes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With PQ, if we split it into 96 subvectors and store one 8-bit code for each subvector:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;96 × 1 byte = 96 bytes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's &lt;strong&gt;32× less storage for the vector representations&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When you're dealing with millions or billions of vectors, that difference becomes enormous.&lt;/p&gt;

&lt;p&gt;And that's the real reason Product Quantization is so useful for large-scale vector search.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrapping It Up
&lt;/h3&gt;

&lt;p&gt;At its core, Product Quantization is a clever way of saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Instead of storing every number in a vector, split the vector into smaller pieces and represent each piece by the ID of its closest learned codeword.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You lose some precision, but in return, you get dramatically smaller vectors and &lt;strong&gt;more efficient approximate distance calculations&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So that's about this article.&lt;/p&gt;

&lt;p&gt;See you in the next one!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;&lt;br&gt;
Your team's attention is limited, and the deluge of AI-generated code is making it harder to keep production stable while also shipping at high velocity.&lt;/em&gt;&lt;/p&gt;
&lt;em&gt;

&lt;p&gt;I'm building &lt;strong&gt;LiveReview&lt;/strong&gt;, a blast-radius aware AI code review built for your business-critical systems.&lt;/p&gt;

&lt;p&gt;Instead of presenting every diff with equal emphasis, &lt;strong&gt;LiveReview scores each change by blast radius — how far its impact reaches through your call graph — so you can focus attention where it actually matters.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Spend code review effort where business risk is highest — not spread evenly across every diff.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Try LiveReview on your codebase:&lt;/b&gt;&lt;/p&gt;

&lt;/em&gt;&lt;p&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hexmos.com/livereview" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvls0pq7nymbrll98je6s.png" alt="LiveReview Banner" width="800" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>llm</category>
    </item>
    <item>
      <title>Turn Your Obsidian Vault Into an AI-Powered Second Brain</title>
      <dc:creator>Rijul Rajesh</dc:creator>
      <pubDate>Thu, 27 Aug 2026 20:26:30 +0000</pubDate>
      <link>https://dev.to/rijultp/turn-your-obsidian-vault-into-an-ai-powered-second-brain-559</link>
      <guid>https://dev.to/rijultp/turn-your-obsidian-vault-into-an-ai-powered-second-brain-559</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Rijul. I'm building git-lrc, a micro AI code reviewer that runs on every commit. It's free and source-available on GitHub. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help more developers discover the project. Do give it a try and share your feedback&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Are you someone who uses Obsidian day-to-day?&lt;/p&gt;

&lt;p&gt;Suppose someone asks you about some work you did a few months ago. Or maybe you want to refer back to how you solved a particular problem.&lt;/p&gt;

&lt;p&gt;But obviously, you won't remember all the details.&lt;/p&gt;

&lt;p&gt;You may need to go through your Obsidian notes just to figure out what you did.&lt;/p&gt;

&lt;p&gt;That sounds pretty cumbersome.&lt;/p&gt;

&lt;p&gt;When I already had agents doing lower-level work for me, I started thinking, why not get an agent to handle this task as well?&lt;/p&gt;

&lt;p&gt;So here I'll show you how I did it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Introducing the Copilot Plugin for Obsidian
&lt;/h3&gt;

&lt;p&gt;This is a plugin I recently stumbled across.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv30rbglculqp84704reb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv30rbglculqp84704reb.png" alt=" " width="800" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just go to &lt;strong&gt;Settings → Community Plugins&lt;/strong&gt; and search for &lt;strong&gt;Copilot&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You should find the Copilot plugin.&lt;/p&gt;

&lt;p&gt;Just install it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fitc1odkc8hj3d5b3905b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fitc1odkc8hj3d5b3905b.png" alt=" " width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once installed, you can connect it to an AI provider. In my case, I connected it to OpenCode.&lt;/p&gt;




&lt;h3&gt;
  
  
  Now Comes the Fun Part
&lt;/h3&gt;

&lt;p&gt;In the Obsidian sidebar, you'll see a button for Copilot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7hrp2i0frqbsfrf8a6u1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7hrp2i0frqbsfrf8a6u1.png" alt=" " width="367" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click it, and you now have an AI agent that can work with your Obsidian vault.&lt;/p&gt;

&lt;p&gt;So let me demonstrate the problem I had.&lt;/p&gt;

&lt;p&gt;I did a &lt;strong&gt;Teams integration&lt;/strong&gt; for an app recently, but I needed to know the specifics of how and when I did it.&lt;/p&gt;

&lt;p&gt;Instead of manually searching through my notes and wasting time, I simply asked Copilot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;When did I do stuff related to Teams integration?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see the output here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmn1rrc4qvl39oozer0j5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmn1rrc4qvl39oozer0j5.png" alt=" " width="608" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now I can see the relevant documents, and I can continue asking questions about them.&lt;/p&gt;

&lt;p&gt;For example, I can dig deeper into what I did, when I did it, or how I implemented something.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrapping Up
&lt;/h3&gt;

&lt;p&gt;So this is another way you can make your existing workflow a little faster.&lt;/p&gt;

&lt;p&gt;It's basically another agent working with your notes, acting more like a second brain that can dig through your old information and bring it back when you need it.&lt;/p&gt;

&lt;p&gt;Kind of like a librarian for your brain.&lt;/p&gt;

&lt;p&gt;See you in the next article.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c6mz17iiajj885fmxgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c6mz17iiajj885fmxgb.png" alt=" " width="360" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;git-lrc&lt;/a&gt; fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.&lt;/p&gt;

&lt;p&gt;Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.&lt;/p&gt;

&lt;p&gt;Give it a ⭐ &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;star on Github&lt;/a&gt;&lt;/p&gt;

</description>
      <category>obsidian</category>
      <category>ai</category>
    </item>
    <item>
      <title>How Does an Email Reach Your Inbox? SMTP Explained with Mailtrap</title>
      <dc:creator>Rijul Rajesh</dc:creator>
      <pubDate>Tue, 25 Aug 2026 20:22:35 +0000</pubDate>
      <link>https://dev.to/rijultp/how-does-an-email-reach-your-inbox-smtp-explained-with-mailtrap-3c2b</link>
      <guid>https://dev.to/rijultp/how-does-an-email-reach-your-inbox-smtp-explained-with-mailtrap-3c2b</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Rijul. I'm building git-lrc, a micro AI code reviewer that runs on every commit. It's free and source-available on GitHub. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help more developers discover the project. Do give it a try and share your feedback&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Suppose you hit &lt;strong&gt;Forgot Password&lt;/strong&gt; on one of your apps while trying to log in.&lt;/p&gt;

&lt;p&gt;A few seconds later, bam, an email appears in your inbox.&lt;/p&gt;

&lt;p&gt;Sounds simple, right?&lt;/p&gt;

&lt;p&gt;But have you ever thought about what actually happens behind the scenes?&lt;/p&gt;

&lt;p&gt;In this article, we'll look at how this works and how you can simulate the whole process for free using Mailtrap.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happens When You Send an Email?
&lt;/h2&gt;

&lt;p&gt;The flow we mentioned earlier looks roughly like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your Application
       |
       | SMTP
       ↓
Mail Submission / SMTP Server
       |
       | SMTP
       ↓
Recipient's Mail Server
       |
       ↓
Recipient's Mailbox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what exactly are a &lt;strong&gt;mail server&lt;/strong&gt; and a &lt;strong&gt;recipient's mail server&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;Usually, you might think: I clicked Forgot Password, some magic happened, and the email reached my inbox.&lt;/p&gt;

&lt;p&gt;That "magic" is handled by several components, including the sending mail server and the recipient's mail server.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is a Mail Server?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;mail server&lt;/strong&gt; is a system responsible for handling email.&lt;/p&gt;

&lt;p&gt;It can receive, store, process, and forward emails depending on its role.&lt;/p&gt;

&lt;p&gt;For example, when your application needs to send a password reset email, it can hand that email off to a mail server.&lt;/p&gt;

&lt;p&gt;The mail server then takes care of sending it toward the recipient.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is the Recipient's Mail Server?
&lt;/h2&gt;

&lt;p&gt;The recipient also has a mail server responsible for receiving their email.&lt;/p&gt;

&lt;p&gt;For example, if you send an email to someone with a Gmail address, Google's mail infrastructure receives the message and eventually makes it available in the user's inbox.&lt;/p&gt;

&lt;p&gt;So the basic idea is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your Application
       ↓
Your Mail Server
       ↓
Recipient's Mail Server
       ↓
Recipient's Inbox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Where Does SMTP Come In?
&lt;/h2&gt;

&lt;p&gt;You may also see the term &lt;strong&gt;SMTP&lt;/strong&gt; being thrown around.&lt;/p&gt;

&lt;p&gt;SMTP stands for &lt;strong&gt;Simple Mail Transfer Protocol&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is the protocol used for sending and relaying email.&lt;/p&gt;

&lt;p&gt;Just like we use a language and set of rules to communicate with each other, applications and mail servers use SMTP to communicate when sending email.&lt;/p&gt;

&lt;p&gt;So the application doesn't need to figure out all the details of how the email should be delivered.&lt;/p&gt;

&lt;p&gt;It can communicate with an SMTP server and hand the message over to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is an SMTP Server?
&lt;/h2&gt;

&lt;p&gt;An SMTP server is a server that communicates using SMTP. Depending on its role, it can accept submitted mail, relay mail to another server, or receive mail for its own domain.&lt;/p&gt;

&lt;p&gt;An application typically needs configuration like this to connect to one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SMTP Host: smtp.example.com
SMTP Port: 587
Username: abc123
Password: xyz456
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact values depend on the SMTP provider you're using.&lt;/p&gt;




&lt;h1&gt;
  
  
  Test It Yourself: Trying Out Mailtrap
&lt;/h1&gt;

&lt;p&gt;Suppose you want to try this out yourself.&lt;/p&gt;

&lt;p&gt;Normally, you might have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your App
   ↓
SMTP Server
   ↓
Real User's Inbox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But during development, you probably don't want your test emails going to real users.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;Mailtrap&lt;/strong&gt; can be useful.&lt;/p&gt;

&lt;p&gt;With Mailtrap's email sandbox, you can have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your App
   ↓
Mailtrap SMTP
   ↓
Mailtrap Inbox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mailtrap captures the emails inside the sandbox instead of delivering them to the actual recipient.&lt;/p&gt;

&lt;p&gt;That's extremely useful when you're developing and testing email workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Mailtrap to demo SMTP
&lt;/h2&gt;

&lt;p&gt;To get started, go to &lt;a href="https://mailtrap.io/" rel="noopener noreferrer"&gt;Mailtrap&lt;/a&gt; and create an account.&lt;/p&gt;

&lt;p&gt;Then go to the &lt;strong&gt;Sandboxes&lt;/strong&gt; section:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mailtrap.io/sandboxes/projects" rel="noopener noreferrer"&gt;Mailtrap Sandboxes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;My Sandbox&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fblumljebg6uv4kvekbfi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fblumljebg6uv4kvekbfi.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should see the SMTP credentials required to connect your application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzqosgto0vxw4uourtnll.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzqosgto0vxw4uourtnll.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Keep these credentials handy. We'll use them for the demo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sending a Test Email Using SMTP Credentials
&lt;/h2&gt;

&lt;p&gt;You can clone the demo project here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/RijulTP/smtp-demo" rel="noopener noreferrer"&gt;SMTP Demo GitHub Repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The project contains a &lt;code&gt;.env.example&lt;/code&gt; file with the configuration you need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SMTP_HOST=
SMTP_PORT=
SMTP_USERNAME=
SMTP_PASSWORD=
FROM_EMAIL=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SMTP_HOST&lt;/strong&gt;: The hostname of the SMTP server&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SMTP_PORT&lt;/strong&gt;: The port used by the SMTP server&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SMTP_USERNAME&lt;/strong&gt;: Your SMTP username&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SMTP_PASSWORD&lt;/strong&gt;: Your SMTP password&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FROM_EMAIL&lt;/strong&gt;: The email address the message is sent from&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fill these values using the credentials provided by your Mailtrap sandbox.&lt;/p&gt;

&lt;p&gt;Then run the demo application and trigger the email.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the email appear inside your Mailtrap inbox instead of being delivered to a real recipient.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjzm00k1263g1kwqzl24u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjzm00k1263g1kwqzl24u.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;The next time you click &lt;strong&gt;Forgot Password&lt;/strong&gt; and an email appears a few seconds later, there's quite a bit happening behind the scenes.&lt;/p&gt;

&lt;p&gt;Your application hands the email to an SMTP server, which can then relay it through the mail system until it reaches the recipient's mail infrastructure.&lt;/p&gt;

&lt;p&gt;Whether you're implementing a feature that involves email or simply trying to understand how these seemingly simple things work, SMTP is an important piece of the puzzle.&lt;/p&gt;

&lt;p&gt;That's it for this article. See you in the next one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c6mz17iiajj885fmxgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c6mz17iiajj885fmxgb.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;git-lrc&lt;/a&gt; fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.&lt;/p&gt;

&lt;p&gt;Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.&lt;/p&gt;

&lt;p&gt;Give it a ⭐ &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;star on Github&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mail</category>
      <category>smtp</category>
    </item>
    <item>
      <title>How Does an AI Find the Most Similar Information? FAISS Explained</title>
      <dc:creator>Rijul Rajesh</dc:creator>
      <pubDate>Mon, 24 Aug 2026 20:08:55 +0000</pubDate>
      <link>https://dev.to/rijultp/how-does-an-ai-find-the-most-similar-information-faiss-explained-1lhh</link>
      <guid>https://dev.to/rijultp/how-does-an-ai-find-the-most-similar-information-faiss-explained-1lhh</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Rijul. I'm building git-lrc, a micro AI code reviewer that runs on every commit. It's free and source-available on GitHub. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help more developers discover the project. Do give it a try and share your feedback&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Imagine you have &lt;strong&gt;100,000 notes&lt;/strong&gt; and you want to find the one most relevant to a question.&lt;/p&gt;

&lt;p&gt;Reading every note one by one works, but it is obviously not efficient.&lt;/p&gt;

&lt;p&gt;This is one of the problems FAISS helps solve.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem: Finding Similar Information
&lt;/h2&gt;

&lt;p&gt;Imagine you have a huge pile of notes.&lt;/p&gt;

&lt;p&gt;100,000 of them.&lt;/p&gt;

&lt;p&gt;Some say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Python is a programming language.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Others:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Docker packages applications into containers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And others:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;PostgreSQL is a relational database.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now you ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What can I use to run applications in isolated environments?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You want to find the note about Docker.&lt;/p&gt;

&lt;p&gt;One simple approach would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Question
   ↓
Read note 1
Read note 2
Read note 3
...
Read note 100,000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this is not efficient.&lt;/p&gt;

&lt;p&gt;There is another problem with ordinary keyword search.&lt;/p&gt;

&lt;p&gt;Your question says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"run applications in isolated environments"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But the document says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Docker packages applications into containers"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There may not be many exact words in common.&lt;/p&gt;

&lt;p&gt;Yet the &lt;strong&gt;meaning is related&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is where semantics come into the picture.&lt;/p&gt;

&lt;p&gt;And to work with semantic similarity, we use &lt;strong&gt;embeddings&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Turning Notes Into Numbers
&lt;/h2&gt;

&lt;p&gt;An embedding model can turn text into a vector.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Docker packages applications into containers"
                    ↓
             Embedding model
                    ↓
       [0.21, -0.73, 0.44, ...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another document:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Kubernetes manages containers"
                    ↓
       [0.19, -0.70, 0.48, ...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And another:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Chocolate cake recipe"
                    ↓
       [-0.81, 0.12, -0.34, ...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important idea is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Similar meanings tend to produce similar vectors.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So if we imagine these vectors in a vector space, documents related to Docker and Kubernetes may be closer together, while something about chocolate cake would be much farther away.&lt;/p&gt;

&lt;p&gt;So the basic solution is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Find the vectors closest to the query vector.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But then scale becomes a problem.&lt;/p&gt;

&lt;p&gt;What happens when we go from:&lt;/p&gt;

&lt;p&gt;10,000 documents → 100,000 → 1 million → 10 million?&lt;/p&gt;

&lt;p&gt;You could calculate the distance between your question and all 10 million vectors.&lt;/p&gt;

&lt;p&gt;That's possible, but it can become expensive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is the problem FAISS helps solve.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  FAISS: Finding Similar Things Fast
&lt;/h2&gt;

&lt;p&gt;FAISS stands for &lt;strong&gt;Facebook AI Similarity Search&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is a library developed by Meta for &lt;strong&gt;efficient similarity search over vectors&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You give FAISS thousands or millions of vectors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Vector 1
Vector 2
Vector 3
...
Vector 1,000,000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you give it a query vector:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Query vector
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Give me the 5 vectors most similar to this one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;FAISS can return something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Closest:

Vector 83721
Vector 192837
Vector 92837
Vector 1827
Vector 72819
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important thing to notice is what FAISS is actually searching.&lt;/p&gt;

&lt;p&gt;It is searching &lt;strong&gt;vectors&lt;/strong&gt;, not text.&lt;/p&gt;




&lt;h2&gt;
  
  
  But How Does That Find the Actual Document?
&lt;/h2&gt;

&lt;p&gt;FAISS doesn't necessarily need to store your documents.&lt;/p&gt;

&lt;p&gt;Your application might maintain a mapping like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ID 0 → "Python is a programming language"
ID 1 → "Docker packages applications into containers"
ID 2 → "PostgreSQL is a database"
ID 3 → "Kubernetes manages containers"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And FAISS stores the corresponding vectors.&lt;/p&gt;

&lt;p&gt;So when you ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What runs applications in isolated environments?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The query is converted into a vector and searched against the vectors in FAISS.&lt;/p&gt;

&lt;p&gt;It might return:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Closest vector IDs:

1
3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your application can then map those IDs back to the original documents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1 → Docker packages applications into containers

3 → Kubernetes manages containers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So FAISS helps you efficiently find &lt;strong&gt;which vectors are closest&lt;/strong&gt;, while your application handles the connection between those vectors and the original data.&lt;/p&gt;




&lt;h2&gt;
  
  
  What FAISS Actually Does
&lt;/h2&gt;

&lt;p&gt;You can notice the wording in its name:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Similarity Search&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;FAISS is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not a text search engine&lt;/li&gt;
&lt;li&gt;Not an AI model&lt;/li&gt;
&lt;li&gt;Not an embedding model&lt;/li&gt;
&lt;li&gt;Not something that understands English&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;FAISS doesn't know what Docker is.&lt;/p&gt;

&lt;p&gt;It doesn't know what Kubernetes is.&lt;/p&gt;

&lt;p&gt;It sees numbers and efficiently searches for vectors that are similar according to the chosen similarity or distance measure.&lt;/p&gt;

&lt;p&gt;The embedding model gives the text its numerical representation.&lt;/p&gt;

&lt;p&gt;FAISS helps you search those representations efficiently.&lt;/p&gt;




&lt;h2&gt;
  
  
  FAISS in RAG
&lt;/h2&gt;

&lt;p&gt;If you've read about &lt;strong&gt;RAG&lt;/strong&gt;, you may already know that retrieval is an important part of the process.&lt;/p&gt;

&lt;p&gt;A simplified RAG pipeline looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Documents
    ↓
Embeddings
    ↓
Vector index
    ↓
User question
    ↓
Query embedding
    ↓
Similarity search
    ↓
Relevant documents
    ↓
LLM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;FAISS can be used in that retrieval step.&lt;/p&gt;

&lt;p&gt;Especially when you have a large number of vectors and need to efficiently find the ones most relevant to a query.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;FAISS is basically a &lt;strong&gt;helper for finding similar vectors efficiently&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;With a small number of vectors, you may not need anything particularly sophisticated.&lt;/p&gt;

&lt;p&gt;But as the number of vectors grows into hundreds of thousands or millions, the way you perform similarity search starts to matter.&lt;/p&gt;

&lt;p&gt;That's where technologies like FAISS become useful.&lt;/p&gt;

&lt;p&gt;It takes a seemingly simple problem, &lt;strong&gt;"find the vectors closest to this one"&lt;/strong&gt;, and provides efficient ways to do it at scale.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c6mz17iiajj885fmxgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c6mz17iiajj885fmxgb.png" alt=" " width="360" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;git-lrc&lt;/a&gt; fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.&lt;/p&gt;

&lt;p&gt;Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.&lt;/p&gt;

&lt;p&gt;Give it a ⭐ &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;star on Github&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>ONNX Explained: The Standard Format for Machine Learning Models</title>
      <dc:creator>Rijul Rajesh</dc:creator>
      <pubDate>Sat, 22 Aug 2026 19:23:43 +0000</pubDate>
      <link>https://dev.to/rijultp/onnx-explained-the-standard-format-for-machine-learning-models-2ik4</link>
      <guid>https://dev.to/rijultp/onnx-explained-the-standard-format-for-machine-learning-models-2ik4</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Rijul. I'm building git-lrc, a micro AI code reviewer that runs on every commit. It's free and source-available on GitHub. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help more developers discover the project. Do give it a try and share your feedback&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Did you know there is an open standard for representing machine learning models in a common format?&lt;/p&gt;

&lt;p&gt;This is called &lt;strong&gt;ONNX&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It provides a standard way to represent machine learning models so they can be used across different runtimes and environments.&lt;/p&gt;

&lt;p&gt;Let's see what problem ONNX solves.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Suppose you built a machine learning model using PyTorch.&lt;/p&gt;

&lt;p&gt;You ran it locally and everything works.&lt;/p&gt;

&lt;p&gt;Now you need to deploy it.&lt;/p&gt;

&lt;p&gt;The environment where you deploy the model doesn't necessarily have PyTorch installed. You may also need to run the model on different hardware, such as a CPU, GPU, or mobile device.&lt;/p&gt;

&lt;p&gt;In the past, this could mean making environment-specific changes or creating custom implementations.&lt;/p&gt;

&lt;p&gt;ONNX provides a common representation for the model, making it easier to deploy the model across different runtimes and environments.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is ONNX?
&lt;/h2&gt;

&lt;p&gt;ONNX stands for &lt;strong&gt;Open Neural Network Exchange&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It defines a standard way of representing machine learning models.&lt;/p&gt;

&lt;p&gt;For example, imagine your model performs these operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input&lt;/li&gt;
&lt;li&gt;Matrix multiplication&lt;/li&gt;
&lt;li&gt;Add bias&lt;/li&gt;
&lt;li&gt;ReLU&lt;/li&gt;
&lt;li&gt;Output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ONNX can represent this as a computational graph:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input
  │
  ▼
MatMul
  │
  ▼
 Add
  │
  ▼
 Relu
  │
  ▼
Output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The graph is made up of standardized ONNX operators that describe what the model does.&lt;/p&gt;

&lt;p&gt;The resulting model can be serialized as a file such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model.onnx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, at its simplest, &lt;strong&gt;ONNX is a standard format for representing machine learning models&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But the ONNX file itself doesn't execute the model.&lt;/p&gt;

&lt;p&gt;That's where ONNX Runtime comes in.&lt;/p&gt;




&lt;h2&gt;
  
  
  ONNX Runtime
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;ONNX Runtime&lt;/strong&gt; can load an ONNX model and execute it.&lt;/p&gt;

&lt;p&gt;It supports running models across different environments and hardware through its execution providers, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU&lt;/li&gt;
&lt;li&gt;GPU&lt;/li&gt;
&lt;li&gt;Mobile&lt;/li&gt;
&lt;li&gt;Other supported hardware accelerators&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the basic flow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PyTorch Model
     │
     ▼
Export to ONNX
     │
     ▼
 model.onnx
     │
     ▼
ONNX Runtime
     │
     ▼
Run the model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, ONNX doesn't automatically make every model runnable on every piece of hardware. The model's operators and the capabilities of the target runtime still need to be supported.&lt;/p&gt;

&lt;p&gt;You can check out &lt;a href="https://colab.research.google.com/drive/1ADv_xQhoUtrmqWp3ZQXURRKBKofwu6qI?usp=sharing" rel="noopener noreferrer"&gt;this Colab notebook&lt;/a&gt;, where we create an ONNX model from PyTorch and then use ONNX Runtime to run it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;So that's the basic idea behind &lt;strong&gt;ONNX and ONNX Runtime&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ONNX&lt;/strong&gt; provides a common format for representing machine learning models, while &lt;strong&gt;ONNX Runtime&lt;/strong&gt; provides a way to execute those models.&lt;/p&gt;

&lt;p&gt;Together, they make it easier to take a model built in one environment and deploy it across different runtimes and supported hardware.&lt;/p&gt;

&lt;p&gt;See you in the next article.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c6mz17iiajj885fmxgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c6mz17iiajj885fmxgb.png" alt=" " width="360" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;git-lrc&lt;/a&gt; fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.&lt;/p&gt;

&lt;p&gt;Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.&lt;/p&gt;

&lt;p&gt;Give it a ⭐ &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;star on Github&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>What Is mDNS? Access Devices on Your Local Network by Name</title>
      <dc:creator>Rijul Rajesh</dc:creator>
      <pubDate>Fri, 21 Aug 2026 20:06:22 +0000</pubDate>
      <link>https://dev.to/rijultp/what-is-mdns-access-devices-on-your-local-network-by-name-dej</link>
      <guid>https://dev.to/rijultp/what-is-mdns-access-devices-on-your-local-network-by-name-dej</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Rijul. I'm building git-lrc, a micro AI code reviewer that runs on every commit. It's free and source-available on GitHub. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help more developers discover the project. Do give it a try and share your feedback&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Have you ever seen devices on a local network being accessed using a name instead of an IP address?&lt;/p&gt;

&lt;p&gt;When I first came across this, I found it pretty interesting.&lt;/p&gt;

&lt;p&gt;That technology is called &lt;strong&gt;mDNS&lt;/strong&gt;, or &lt;strong&gt;Multicast DNS&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It allows devices on the same local network to discover and communicate with each other using names instead of IP addresses, without requiring a traditional DNS server.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Simple Example
&lt;/h2&gt;

&lt;p&gt;Suppose your PC has this IP address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.1.20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And its hostname is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-pc.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your phone is connected to the same network and has:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.1.30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Normally, if you want to access a web application running on port 3000 on your PC, you might use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://192.168.1.20:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With mDNS, you can instead use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://my-pc.local:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You don't need to remember the IP address.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.local&lt;/code&gt; hostname is resolved to the correct device on the local network.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does Normal DNS Work?
&lt;/h2&gt;

&lt;p&gt;With traditional DNS, the process looks roughly like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You
 ↓
DNS Server
 ↓
"What IP address belongs to example.com?"
 ↓
DNS Server looks up the address
 ↓
IP address returned
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The DNS server maintains or retrieves the mapping between a hostname and an IP address.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example.com → 93.184.216.34
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But mDNS works differently.&lt;/p&gt;

&lt;p&gt;There isn't a central DNS server that needs to know the address of every device on your local network.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does mDNS Work?
&lt;/h2&gt;

&lt;p&gt;Let's say your phone wants to find:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-pc.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It can send a multicast query asking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Who has my-pc.local?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The request is sent to the local network.&lt;/p&gt;

&lt;p&gt;The PC that owns that hostname responds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"That's me. I'm 192.168.1.20."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The basic flow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Phone
  ↓
"Who has my-pc.local?"
  ↓
Local network
  ↓
PC
  ↓
"That's me. I'm 192.168.1.20"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The phone can then connect to the PC using the returned IP address.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Does Multicast Come In?
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;M&lt;/strong&gt; in mDNS stands for &lt;strong&gt;Multicast&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For IPv4, mDNS uses the multicast address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;224.0.0.251
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can think of this address as a specific multicast group on the local network.&lt;/p&gt;

&lt;p&gt;The devices communicate through this group:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 Wi-Fi / LAN
                     |
          ┌──────────┼──────────┐
          ↓          ↓          ↓
         PC        Phone      Laptop
          |          |          |
          └──── 224.0.0.251 ───┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a device sends an mDNS query to &lt;code&gt;224.0.0.251&lt;/code&gt;, devices listening to that multicast group can receive it.&lt;/p&gt;

&lt;p&gt;So if your phone asks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Who has my-pc.local?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the PC can hear the request and respond because it owns that hostname.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Is This Useful?
&lt;/h2&gt;

&lt;p&gt;mDNS is particularly useful on local networks where devices need to discover each other without requiring you to manually configure DNS.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://my-pc.local:3000
ssh my-pc.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is useful for things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accessing development servers&lt;/li&gt;
&lt;li&gt;Connecting to computers on your home network&lt;/li&gt;
&lt;li&gt;Device discovery&lt;/li&gt;
&lt;li&gt;Printers and other network devices&lt;/li&gt;
&lt;li&gt;Local development and testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don't have to keep track of an IP address that might change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;mDNS is essentially &lt;strong&gt;DNS for your local network, without requiring a traditional DNS server&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of asking a central DNS server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"What IP belongs to this hostname?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;a device can ask the local network:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Who has this hostname?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The device that owns the name responds with its IP address.&lt;/p&gt;

&lt;p&gt;And that's the basic idea behind mDNS.&lt;/p&gt;

&lt;p&gt;See you in another article.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c6mz17iiajj885fmxgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c6mz17iiajj885fmxgb.png" alt=" " width="360" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;git-lrc&lt;/a&gt; fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.&lt;/p&gt;

&lt;p&gt;Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.&lt;/p&gt;

&lt;p&gt;Give it a ⭐ &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;star on Github&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dns</category>
      <category>network</category>
    </item>
    <item>
      <title>Stop Treating Your Vector Database Like a Black Box: Visualize ChromaDB</title>
      <dc:creator>Rijul Rajesh</dc:creator>
      <pubDate>Mon, 17 Aug 2026 20:07:10 +0000</pubDate>
      <link>https://dev.to/rijultp/stop-treating-your-vector-database-like-a-black-box-visualize-chromadb-1kfa</link>
      <guid>https://dev.to/rijultp/stop-treating-your-vector-database-like-a-black-box-visualize-chromadb-1kfa</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Rijul. I'm building git-lrc, a micro AI code reviewer that runs on every commit. It's free and source-available on GitHub. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help more developers discover the project. Do give it a try and share your feedback&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Have you built your first &lt;strong&gt;RAG&lt;/strong&gt; system and set up ChromaDB?&lt;/p&gt;

&lt;p&gt;If so, you might have started thinking of ChromaDB as a bit of a black box.&lt;/p&gt;

&lt;p&gt;You put documents into it, embeddings come out, searches happen, and relevant chunks are returned.&lt;/p&gt;

&lt;p&gt;But what is actually happening inside?&lt;/p&gt;

&lt;p&gt;We can make that easier to understand by visualizing the embeddings stored in ChromaDB.&lt;/p&gt;

&lt;p&gt;You can get something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsqvr2u3jindkprvg768q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsqvr2u3jindkprvg768q.png" alt=" " width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's see how we can build it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Before We Start
&lt;/h2&gt;

&lt;p&gt;If you haven't built a RAG system yet, I recommend checking out &lt;a href="https://dev.to/rijultp/youve-heard-of-rag-but-what-does-it-actually-do-5e57"&gt;my RAG article&lt;/a&gt; and &lt;a href="https://dev.to/rijultp/keep-up-with-ai-by-building-your-first-vector-database-with-chromadb-2f6b"&gt;ChromaDB Article&lt;/a&gt; first.&lt;/p&gt;

&lt;p&gt;It will give you an idea of how ChromaDB and vector databases work.&lt;/p&gt;

&lt;p&gt;Once you're familiar with that, you can come back here and visualize what's happening inside the vector database.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Does the Visualization Work?
&lt;/h2&gt;

&lt;p&gt;The basic idea is quite simple.&lt;/p&gt;

&lt;p&gt;Every chunk in our vector store is represented as a &lt;strong&gt;3072-dimensional vector&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In simple terms, that's a list of 3072 numbers that captures the semantic meaning of that chunk.&lt;/p&gt;

&lt;p&gt;The problem is that we can't visualize 3072 dimensions directly.&lt;/p&gt;

&lt;p&gt;So we need to reduce those 3072 dimensions down to just 3.&lt;/p&gt;

&lt;p&gt;That's where &lt;strong&gt;PCA&lt;/strong&gt;, or &lt;strong&gt;Principal Component Analysis&lt;/strong&gt;, comes in.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Is PCA?
&lt;/h3&gt;

&lt;p&gt;PCA is a technique used to reduce a high-dimensional vector to a smaller number of dimensions while preserving as much information as possible.&lt;/p&gt;

&lt;p&gt;Instead of simply removing random numbers, PCA finds the most important patterns across the dimensions and represents those patterns using fewer dimensions.&lt;/p&gt;

&lt;p&gt;In our case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;3072 dimensions
       ↓
      PCA
       ↓
  3 dimensions
       ↓
  3D scatter plot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can then represent every chunk as a single point in a 3D space.&lt;/p&gt;

&lt;p&gt;Chunks with similar embeddings may end up closer together, allowing clusters to appear naturally.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Five Steps
&lt;/h2&gt;

&lt;p&gt;The visualization script essentially performs five steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Connect to the Vector Store
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;open_store()&lt;/code&gt; function opens the local ChromaDB database and gets the &lt;code&gt;rag_demo&lt;/code&gt; collection.&lt;/p&gt;

&lt;p&gt;I created this RAG demo in &lt;a href="https://dev.to/rijultp/youve-heard-of-rag-but-what-does-it-actually-do-5e57"&gt;my RAG article&lt;/a&gt;, so you can check that out if you want to see how the data was created.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Pull Out the Records
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;collect_entries()&lt;/code&gt; function fetches everything we need from the collection:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Embedding vectors&lt;/li&gt;
&lt;li&gt;Chunk IDs&lt;/li&gt;
&lt;li&gt;Source documents&lt;/li&gt;
&lt;li&gt;Chunk text&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will also use the source document information to group the points in the visualization.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Compress 3072 Dimensions Into 3
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;compress_to_3d()&lt;/code&gt; function uses PCA to reduce each 3072-dimensional embedding down to 3 dimensions.&lt;/p&gt;

&lt;p&gt;These three values become the X, Y, and Z coordinates of our visualization.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Build the Tooltips
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;build_hover_labels()&lt;/code&gt; function creates the information that appears when you hover over a point.&lt;/p&gt;

&lt;p&gt;This lets us see things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chunk ID&lt;/li&gt;
&lt;li&gt;Source document&lt;/li&gt;
&lt;li&gt;Part of the chunk text&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Draw the Scene
&lt;/h3&gt;

&lt;p&gt;Finally, &lt;code&gt;render_scene()&lt;/code&gt; creates the interactive 3D visualization using Plotly.&lt;/p&gt;

&lt;p&gt;Each point represents a chunk from our vector database.&lt;/p&gt;

&lt;p&gt;We also create a separate trace for each source document, which allows us to distinguish where the chunks came from.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Code
&lt;/h2&gt;

&lt;p&gt;Here is the complete visualization script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;chromadb&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;plotly.graph_objects&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;go&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sklearn.decomposition&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PCA&lt;/span&gt;

&lt;span class="n"&gt;COLLECTION_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rag_demo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;DB_PATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;chroma_db&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;TARGET_AXES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;open_store&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;chromadb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Return a handle to the local vector collection.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chromadb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;PersistentClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DB_PATH&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;COLLECTION_NAME&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;collect_entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;chromadb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Pull every stored record out of the collection.

    Returns (vectors, ids, source_tags, chunk_texts) in lock-step order.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;records&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;embeddings&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;documents&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;metadatas&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;vectors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;records&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;embeddings&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;records&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ids&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;source_tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unknown&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;records&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;metadatas&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;chunk_texts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;records&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;documents&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;vectors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source_tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk_texts&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compress_to_3d&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vectors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Fit a PCA model on the vectors and return (model, projected_points).&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PCA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_components&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;TARGET_AXES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;projected_points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fit_transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vectors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;projected_points&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_hover_labels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source_tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk_texts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Compose the rich tooltip shown when hovering over a point.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;rid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;br&amp;gt;source: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;br&amp;gt;chunk: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;rid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source_tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk_texts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render_scene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;projected_points&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;source_tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;hover_labels&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;variance_explained&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Build the interactive 3D figure and open it in the browser.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;figure&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;go&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Figure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update_layout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;COLLECTION_NAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; embeddings projected into 3D &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(explained variance &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;variance_explained&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;scene&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xaxis_title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PCA Axis 1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;yaxis_title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PCA Axis 2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;zaxis_title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PCA Axis 3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# One trace per source document so each cluster can be toggled in the legend.
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source_tags&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
        &lt;span class="n"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;source_tags&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_trace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;go&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Scatter3d&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;projected_points&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;projected_points&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;projected_points&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;markers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;customdata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                    &lt;span class="n"&gt;hover_labels&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="n"&gt;hovertemplate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%{customdata}&amp;lt;extra&amp;gt;&amp;lt;/extra&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open_store&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;vectors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source_tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk_texts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;collect_entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vectors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No embeddings found. Run `python ingest.py` first.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;projected_points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;compress_to_3d&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vectors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;hover_labels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;build_hover_labels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source_tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk_texts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;variance_explained&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;explained_variance_ratio_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nf"&gt;render_scene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;projected_points&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;source_tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;hover_labels&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;variance_explained&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Plotted &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vectors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; chunks in 3D &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;variance_explained&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; of variance preserved).&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;Now that you have an idea of how the visualization works, you can try it yourself using &lt;a href="https://github.com/RijulTP/rag-demo" rel="noopener noreferrer"&gt;my demo repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Clone the repository and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python ingest.py
python visualize.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ingest.py&lt;/code&gt; loads the data into ChromaDB if it hasn't already been added.&lt;/p&gt;

&lt;p&gt;Then &lt;code&gt;visualize.py&lt;/code&gt; reads the stored embeddings and launches the 3D visualization.&lt;/p&gt;

&lt;p&gt;You should get something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv2boczktx1kgmn6nrv0i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv2boczktx1kgmn6nrv0i.png" alt=" " width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each dot represents a different chunk in the vector database.&lt;/p&gt;

&lt;p&gt;The color represents the source document.&lt;/p&gt;

&lt;p&gt;For example, all the red points might represent chunks that came from &lt;code&gt;policies.md&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This gives us a much more intuitive way to look at what's happening inside our vector database.&lt;/p&gt;

&lt;p&gt;Instead of just seeing a collection of embeddings, we can actually see how the chunks are distributed in the embedding space.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;When learning something new, it is easy to stay at the theoretical level.&lt;/p&gt;

&lt;p&gt;We can read about embeddings, vector databases, similarity search, and RAG without ever really developing an intuition for what is happening underneath.&lt;/p&gt;

&lt;p&gt;Visualization can help bridge that gap.&lt;/p&gt;

&lt;p&gt;By reducing our high-dimensional embeddings to three dimensions, we can actually see the data and start developing an intuition for how similar chunks are positioned relative to one another.&lt;/p&gt;

&lt;p&gt;It won't show us everything happening inside ChromaDB, but it gives us a useful way to look inside what can otherwise feel like a black box.&lt;/p&gt;

&lt;p&gt;See you in another article.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c6mz17iiajj885fmxgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c6mz17iiajj885fmxgb.png" alt=" " width="360" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;git-lrc&lt;/a&gt; fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.&lt;/p&gt;

&lt;p&gt;Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.&lt;/p&gt;

&lt;p&gt;Give it a ⭐ &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;star on Github&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>db</category>
      <category>rag</category>
    </item>
    <item>
      <title>Keep Up With AI by Building Your First Vector Database with ChromaDB</title>
      <dc:creator>Rijul Rajesh</dc:creator>
      <pubDate>Wed, 12 Aug 2026 19:59:39 +0000</pubDate>
      <link>https://dev.to/rijultp/keep-up-with-ai-by-building-your-first-vector-database-with-chromadb-2f6b</link>
      <guid>https://dev.to/rijultp/keep-up-with-ai-by-building-your-first-vector-database-with-chromadb-2f6b</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Rijul. I'm building git-lrc, a micro AI code reviewer that runs on every commit. It's free and source-available on GitHub. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help more developers discover the project. Do give it a try and share your feedback&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ChromaDB&lt;/strong&gt; is a term you might have heard being mentioned quite often when working with AI applications.&lt;/p&gt;

&lt;p&gt;ChromaDB is a &lt;strong&gt;vector database&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is the kind of database you will often see being used in AI applications such as chatbots, RAG systems, and other applications that need to search for information based on semantic meaning.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a Vector Database?
&lt;/h2&gt;

&lt;p&gt;Let's say we have two sentences:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;How can I get my money back?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What is your refund policy?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The words are different, but the meaning is similar.&lt;/p&gt;

&lt;p&gt;To allow a computer to work with this kind of semantic similarity, we can convert text into numbers called &lt;strong&gt;embeddings&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;An embedding is a numerical representation of the meaning of a piece of text.&lt;/p&gt;

&lt;p&gt;A vector database allows us to store these embeddings and later search for information based on their semantic similarity.&lt;/p&gt;

&lt;p&gt;ChromaDB is one such vector database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing ChromaDB
&lt;/h2&gt;

&lt;p&gt;Let's start by installing ChromaDB:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;chromadb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once installed, we can import it and create a client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;chromadb&lt;/span&gt;

&lt;span class="n"&gt;chroma_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chromadb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can create a collection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;collection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chroma_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my_collection&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can think of a collection as a place where we store related pieces of data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Documents
&lt;/h2&gt;

&lt;p&gt;Now let's add some documents to our collection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;This is a document about pineapple&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;This is a document about oranges&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use &lt;code&gt;collection.add()&lt;/code&gt; to add the text to the database.&lt;/p&gt;

&lt;p&gt;One useful thing here is that we don't have to manually generate the embeddings ourselves for this basic example.&lt;/p&gt;

&lt;p&gt;ChromaDB can generate embeddings for the documents for us.&lt;/p&gt;

&lt;p&gt;When you run this for the first time, ChromaDB will download the embedding model it uses to generate these embeddings.&lt;/p&gt;

&lt;p&gt;Once the documents and their embeddings are stored, we can search the collection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Querying the Database
&lt;/h2&gt;

&lt;p&gt;Let's query the database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;query_texts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;This is a query document about hawaii&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;n_results&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;query_texts&lt;/code&gt; contains the text we want to search for.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;n_results&lt;/code&gt; specifies how many results we want to retrieve.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ChromaDB will generate an embedding for the query and compare it with the embeddings stored in the collection.&lt;/p&gt;

&lt;p&gt;It then returns the most relevant results.&lt;/p&gt;

&lt;p&gt;The output might look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    'ids': [['id1', 'id2']],
    'embeddings': None,
    'documents': [
        [
            'This is a document about pineapple',
            'This is a document about oranges'
        ]
    ],
    'uris': None,
    'included': ['metadatas', 'documents', 'distances'],
    'data': None,
    'metadatas': [[None, None]],
    'distances': [[1.0404, 1.2431]]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the &lt;code&gt;distances&lt;/code&gt; field.&lt;/p&gt;

&lt;p&gt;These values represent how far the results are from the query in the embedding space. The exact interpretation depends on the distance function being used.&lt;/p&gt;

&lt;p&gt;In this example, the pineapple document has a smaller distance than the oranges document, meaning ChromaDB considers it more similar to the query.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting the Embeddings
&lt;/h2&gt;

&lt;p&gt;By default, the embeddings aren't included in the query result.&lt;/p&gt;

&lt;p&gt;If we want to see them, we can explicitly request them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;query_texts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;This is a query document about hawaii&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;n_results&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;distances&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;metadatas&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;embeddings&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;documents&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the output will include the actual embedding vectors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    'ids': [['id1', 'id2']],
    'embeddings': [
        array([
            [-0.0071,  0.0655, -0.0116, ...,  0.0897,  0.0134],
            [-0.0265,  0.0688, -0.0377, ...,  0.0654,  0.0778]
        ])
    ],
    'documents': [
        [
            'This is a document about pineapple',
            'This is a document about oranges'
        ]
    ],
    'uris': None,
    'included': [
        'distances',
        'metadatas',
        'embeddings',
        'documents'
    ],
    'data': None,
    'metadatas': [[None, None]],
    'distances': [[1.0404, 1.2431]]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The actual embedding contains many numbers, so I've shortened the output with &lt;code&gt;...&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The important thing to understand is the flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Document
    ↓
Embedding
    ↓
Stored in ChromaDB
    ↓
Query
    ↓
Query embedding
    ↓
Similarity search
    ↓
Relevant documents
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's the basic idea behind using ChromaDB as a vector database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;In this article, we looked at the basics of &lt;strong&gt;ChromaDB&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;This is only the basic usage.&lt;/p&gt;

&lt;p&gt;The more interesting part is seeing how we can use ChromaDB in a real application, such as a &lt;strong&gt;RAG system&lt;/strong&gt;, where we can store documents, search for relevant information, and provide those results to an LLM.&lt;/p&gt;

&lt;p&gt;We can explore that in another article.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c6mz17iiajj885fmxgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c6mz17iiajj885fmxgb.png" alt=" " width="360" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;git-lrc&lt;/a&gt; fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.&lt;/p&gt;

&lt;p&gt;Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.&lt;/p&gt;

&lt;p&gt;Give it a ⭐ &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;star on Github&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
    </item>
    <item>
      <title>You've Heard of RAG. But What Does It Actually Do?</title>
      <dc:creator>Rijul Rajesh</dc:creator>
      <pubDate>Mon, 10 Aug 2026 19:56:22 +0000</pubDate>
      <link>https://dev.to/rijultp/youve-heard-of-rag-but-what-does-it-actually-do-5e57</link>
      <guid>https://dev.to/rijultp/youve-heard-of-rag-but-what-does-it-actually-do-5e57</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Rijul. I'm building git-lrc, a micro AI code reviewer that runs on every commit. It's free and source-available on GitHub. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help more developers discover the project. Do give it a try and share your feedback&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Have you been scrolling through AI content and constantly seeing the term &lt;strong&gt;RAG&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;Maybe it sounds like some complicated, high-level AI concept that is difficult to understand.&lt;/p&gt;

&lt;p&gt;But RAG is actually fairly simple.&lt;/p&gt;

&lt;p&gt;And if you're trying to build AI systems, it is a concept worth understanding.&lt;/p&gt;

&lt;p&gt;Let's look at some of the different types of AI systems we see today and understand where RAG fits in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types of AI Systems We See Today
&lt;/h2&gt;

&lt;p&gt;There are many different ways of building AI systems today, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generative AI&lt;/li&gt;
&lt;li&gt;RAG systems&lt;/li&gt;
&lt;li&gt;Agentic systems&lt;/li&gt;
&lt;li&gt;Multi-agent systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article, we'll focus on &lt;strong&gt;RAG&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is RAG?
&lt;/h2&gt;

&lt;p&gt;RAG stands for &lt;strong&gt;Retrieval-Augmented Generation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The basic idea is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Instead of asking an LLM to answer a question using only what it already knows, we retrieve relevant information and give it to the LLM along with the question.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To understand how this works, we need to look at the main components of a RAG pipeline.&lt;/p&gt;

&lt;h1&gt;
  
  
  Understanding the RAG Pipeline
&lt;/h1&gt;

&lt;p&gt;A basic RAG pipeline looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Documents
    ↓
Chunking
    ↓
Embeddings
    ↓
Vector database
    ↓
User question
    ↓
Question embedding
    ↓
Similarity search
    ↓
Relevant chunks
    ↓
Prompt + retrieved chunks
    ↓
LLM
    ↓
Answer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break down each part.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Chunking?
&lt;/h2&gt;

&lt;p&gt;Suppose I have a file called &lt;code&gt;policies.md&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It contains 1,000 lines of information.&lt;/p&gt;

&lt;p&gt;I don't want to send the entire document to the LLM every time a user asks a question.&lt;/p&gt;

&lt;p&gt;Instead, we break the document into smaller pieces.&lt;/p&gt;

&lt;p&gt;This process is called &lt;strong&gt;chunking&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Chunking = breaking documents into smaller pieces that can be independently retrieved.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;policies.md
    ↓
Chunk 1
Chunk 2
Chunk 3
...
Chunk 50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, instead of searching through or sending the entire document, we can retrieve only the chunks that are relevant to the user's question.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Embeddings?
&lt;/h2&gt;

&lt;p&gt;An &lt;strong&gt;embedding&lt;/strong&gt; represents the semantic meaning of text as numbers.&lt;/p&gt;

&lt;p&gt;For example, this sentence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"What is your refund policy?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can be converted into an embedding such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[0.021, -0.183, 0.442, ...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The actual embedding contains many more numbers, but the important idea is that text is converted into a numerical representation.&lt;/p&gt;

&lt;p&gt;This is useful because we can compare these numerical representations to determine how semantically similar two pieces of text are.&lt;/p&gt;

&lt;p&gt;For example, these two questions use different words:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"How can I get my money back?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"What is your refund policy?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But they have a similar meaning.&lt;/p&gt;

&lt;p&gt;Their embeddings should therefore be relatively close to each other.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Vector Database
&lt;/h2&gt;

&lt;p&gt;We can store the chunks and their embeddings in a &lt;strong&gt;vector database&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We also keep information about where the chunk came from.&lt;/p&gt;

&lt;p&gt;Something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Customers can request a refund within 30 days..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"embedding"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"policies.md"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the vector database gives us a way to store our knowledge and later search for information based on semantic similarity.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Does Retrieval Mean?
&lt;/h2&gt;

&lt;p&gt;Now let's see how retrieval actually works.&lt;/p&gt;

&lt;p&gt;Suppose the user asks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What is the refund policy?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, we convert the question into an embedding.&lt;/p&gt;

&lt;p&gt;Then we search the vector database using that embedding.&lt;/p&gt;

&lt;p&gt;The database might return something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. policies.md
   "Customers can request a refund within 30 days..."

2. policies.md
   "Subscriptions can be cancelled at any time..."

3. pricing.md
   "The Pro plan costs $29/month..."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first result is highly relevant to the question.&lt;/p&gt;

&lt;p&gt;Finding these relevant pieces of information is called &lt;strong&gt;retrieval&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How RAG Changes the Prompt
&lt;/h2&gt;

&lt;p&gt;Now we have the relevant information.&lt;/p&gt;

&lt;p&gt;We can add it to the prompt that we send to the LLM.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User: What is the refund policy?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model has to answer using only the information it already has.&lt;/p&gt;

&lt;h3&gt;
  
  
  After
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;System:
Answer using the provided context.

Context:
Customers can request a refund within 30 days...

Question:
What is the refund policy?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the LLM has the relevant information available in its context.&lt;/p&gt;

&lt;p&gt;It can generate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customers can request a refund within 30 days.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's essentially what &lt;strong&gt;Retrieval-Augmented Generation&lt;/strong&gt; means.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrieval
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Find relevant information.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Augmentation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Put that information into the prompt.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Generation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ask the LLM to generate an answer using that information.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's RAG.&lt;/p&gt;

&lt;h1&gt;
  
  
  Building Your Own RAG: A Simple Example
&lt;/h1&gt;

&lt;p&gt;Now let's take a simple use case and see this in action.&lt;/p&gt;

&lt;p&gt;I have a &lt;a href="https://github.com/RijulTP/rag-demo" rel="noopener noreferrer"&gt;small repository that you can clone and try yourself&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Suppose I have a chatbot that is supposed to answer questions about a company.&lt;/p&gt;

&lt;p&gt;The project contains a &lt;code&gt;documents&lt;/code&gt; folder with four files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Company&lt;/li&gt;
&lt;li&gt;Policies&lt;/li&gt;
&lt;li&gt;Pricing&lt;/li&gt;
&lt;li&gt;Products&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The chatbot uses Gemini as the underlying LLM.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, Let's See the Problem Without RAG
&lt;/h2&gt;

&lt;p&gt;First, activate the virtual environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run the chatbot without RAG:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python chat.py &lt;span class="nt"&gt;--no-rag&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I'll ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What is the company's refund policy?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwftqrkai0xf581hx1arf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwftqrkai0xf581hx1arf.png" alt=" " width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the response is generic.&lt;/p&gt;

&lt;p&gt;The chatbot doesn't have access to the company's actual information.&lt;/p&gt;

&lt;p&gt;Let's try another question:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Who is the CEO?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F527ed5swun2zytoghpf2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F527ed5swun2zytoghpf2.png" alt=" " width="798" height="136"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Again, we get a generic response.&lt;/p&gt;

&lt;p&gt;The problem is that the LLM doesn't have our company's documents in its context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Now Let's Run the RAG Version
&lt;/h2&gt;

&lt;p&gt;Now let's run the RAG version of the chatbot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python chat.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll ask the same question:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What is the company's refund policy?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxjc9u0gjlpoo7u2iuq26.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxjc9u0gjlpoo7u2iuq26.png" alt=" " width="800" height="668"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This time, you can see the retrieved chunks.&lt;/p&gt;

&lt;p&gt;The system first searches the documents and finds the pieces of information that are relevant to the question.&lt;/p&gt;

&lt;p&gt;It then provides those chunks to the LLM so it can generate an answer based on the company's actual information.&lt;/p&gt;

&lt;p&gt;Now let's ask something that isn't present in the knowledge base:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Who is the CEO?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwk815sfcgaf9v36c12wd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwk815sfcgaf9v36c12wd.png" alt=" " width="800" height="593"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This time, the chatbot can recognize that the information isn't available in the knowledge base instead of simply making up an answer.&lt;/p&gt;

&lt;p&gt;That's one of the useful properties of RAG.&lt;/p&gt;

&lt;h1&gt;
  
  
  Wrapping Up
&lt;/h1&gt;

&lt;p&gt;We have built and demonstrated a basic RAG system.&lt;/p&gt;

&lt;p&gt;Along the way, we got familiar with concepts such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chunking&lt;/li&gt;
&lt;li&gt;Embeddings&lt;/li&gt;
&lt;li&gt;Vector databases&lt;/li&gt;
&lt;li&gt;Retrieval&lt;/li&gt;
&lt;li&gt;Knowledge bases&lt;/li&gt;
&lt;li&gt;Retrieval-Augmented Generation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once we break the process down, these concepts are much simpler than they might initially seem.&lt;/p&gt;

&lt;p&gt;Of course, this is only a basic example of RAG.&lt;/p&gt;

&lt;p&gt;There are many deeper topics to explore, such as different chunking strategies, embedding models, retrieval methods, reranking, hybrid search, and evaluation.&lt;/p&gt;

&lt;p&gt;But for now, you have a basic understanding of what RAG actually does and how the pieces fit together.&lt;/p&gt;

&lt;p&gt;See you in the next article.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c6mz17iiajj885fmxgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c6mz17iiajj885fmxgb.png" alt=" " width="360" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;git-lrc&lt;/a&gt; fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.&lt;/p&gt;

&lt;p&gt;Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.&lt;/p&gt;

&lt;p&gt;Give it a ⭐ &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;star on Github&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
    </item>
    <item>
      <title>Stop Making Your AI Agent Rediscover Your Codebase</title>
      <dc:creator>Rijul Rajesh</dc:creator>
      <pubDate>Sun, 09 Aug 2026 19:49:12 +0000</pubDate>
      <link>https://dev.to/rijultp/stop-making-your-ai-agent-rediscover-your-codebase-l05</link>
      <guid>https://dev.to/rijultp/stop-making-your-ai-agent-rediscover-your-codebase-l05</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Rijul. I'm building git-lrc, a micro AI code reviewer that runs on every commit. It's free and source-available on GitHub. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help more developers discover the project. Do give it a try and share your feedback&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As I use AI coding agents to work on my repositories, I often find myself opening new sessions for different tasks.&lt;/p&gt;

&lt;p&gt;The problem is that every new session starts with the same challenge.&lt;/p&gt;

&lt;p&gt;The agent may have to rediscover the codebase.&lt;/p&gt;

&lt;p&gt;It may search for files, follow imports, look through related code, and try to understand the project structure all over again.&lt;/p&gt;

&lt;p&gt;This gets annoying pretty quickly.&lt;/p&gt;

&lt;p&gt;It also means spending additional &lt;strong&gt;time, tokens, and context&lt;/strong&gt; on work that has already been done in previous sessions.&lt;/p&gt;

&lt;p&gt;So I started looking for a way to solve this problem, since I imagine many people using coding agents run into the same issue.&lt;/p&gt;

&lt;p&gt;That's when I came across &lt;strong&gt;codebase-memory-mcp&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is codebase-memory-mcp?
&lt;/h2&gt;

&lt;p&gt;You can find the repository here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/DeusData/codebase-memory-mcp" rel="noopener noreferrer"&gt;https://github.com/DeusData/codebase-memory-mcp&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The basic idea is to create a &lt;strong&gt;persistent knowledge graph of your codebase&lt;/strong&gt; that an AI agent can query.&lt;/p&gt;

&lt;p&gt;Think about a textbook.&lt;/p&gt;

&lt;p&gt;A textbook usually has an index that tells you where to find specific topics instead of requiring you to read the entire book to locate something.&lt;/p&gt;

&lt;p&gt;codebase-memory-mcp applies a similar idea to your codebase.&lt;/p&gt;

&lt;p&gt;Instead of making the agent repeatedly explore files and related code to figure out where something is, it can query the indexed representation of the codebase and use that information to find the relevant parts.&lt;/p&gt;

&lt;p&gt;This gives the agent a better starting point when working on a repository.&lt;/p&gt;

&lt;p&gt;Rather than repeatedly asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Where is this functionality implemented?&lt;/p&gt;

&lt;p&gt;Which files are connected to this component?&lt;/p&gt;

&lt;p&gt;Where is this function used?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agent can use the codebase index to navigate the repository more efficiently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing codebase-memory-mcp
&lt;/h2&gt;

&lt;p&gt;You can follow the installation instructions in the repository's README.&lt;/p&gt;

&lt;p&gt;For Linux, you can install it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/DeusData/codebase-memory-mcp/main/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the installation is complete, you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;codebase-memory-mcp &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configures the MCP server for a number of supported AI coding agents, including OpenCode and Claude Code.&lt;/p&gt;

&lt;p&gt;After that, you need to index your project before the agent can query the indexed codebase. The project's README recommends restarting your coding agent and asking it to &lt;strong&gt;"Index this project"&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;When we start using AI agents for software development, there are new limitations that we don't encounter in the same way with traditional development.&lt;/p&gt;

&lt;p&gt;One of them is the amount of time and context an agent can spend &lt;strong&gt;rediscovering a codebase&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Tools like codebase-memory-mcp are interesting because they try to solve that problem by giving agents a persistent representation of the codebase that they can query instead of starting from scratch every time.&lt;/p&gt;

&lt;p&gt;As we adapt to agent-based development, understanding these limitations and finding ways to work around them can make the overall development process much smoother.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c6mz17iiajj885fmxgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c6mz17iiajj885fmxgb.png" alt=" " width="360" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;git-lrc&lt;/a&gt; fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.&lt;/p&gt;

&lt;p&gt;Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.&lt;/p&gt;

&lt;p&gt;Give it a ⭐ &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;star on Github&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
    </item>
  </channel>
</rss>
