<?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: Ramya Perumal</title>
    <description>The latest articles on DEV Community by Ramya Perumal (@ramya_perumal).</description>
    <link>https://dev.to/ramya_perumal</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%2F3900955%2F3e2feb4c-f889-4df6-b8ef-5b1a1ac619ca.png</url>
      <title>DEV Community: Ramya Perumal</title>
      <link>https://dev.to/ramya_perumal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ramya_perumal"/>
    <language>en</language>
    <item>
      <title>AI Agents - Introduction to LLM and AI Terminologies</title>
      <dc:creator>Ramya Perumal</dc:creator>
      <pubDate>Tue, 01 Sep 2026 18:38:49 +0000</pubDate>
      <link>https://dev.to/ramya_perumal/ai-agents-introduction-to-llm-and-ai-terminologies-1pmi</link>
      <guid>https://dev.to/ramya_perumal/ai-agents-introduction-to-llm-and-ai-terminologies-1pmi</guid>
      <description>&lt;h2&gt;
  
  
  LLM
&lt;/h2&gt;

&lt;p&gt;LLM is a model, which means an equation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;y = mx + c

y = m1x^3 + m2x^2 + m3x + m4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A model is actually made up of &lt;strong&gt;weights&lt;/strong&gt;. In any model, e.g., ChatGPT model or Gemini model, they would have used a large amount of input to train the model.&lt;/p&gt;

&lt;p&gt;Input means a large amount of text/image data that is available on the internet. The input would have been fed into the &lt;strong&gt;Transformer architecture&lt;/strong&gt; to get the output, which is the model.&lt;/p&gt;

&lt;p&gt;Weights are floating-point numbers that represent the model's learned parameters. A &lt;strong&gt;10B or 100B parameter model&lt;/strong&gt; means how many parameters (weights) are present inside the model.&lt;/p&gt;

&lt;p&gt;We cannot store a large-parameter model on our computer due to inadequate storage and computational power. Storage and CPU/GPU power decide what size of model can be run on a computer.&lt;/p&gt;

&lt;p&gt;To run a model locally, we can use one of the following tools:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Llama.cpp&lt;/li&gt;
&lt;li&gt;Ollama&lt;/li&gt;
&lt;li&gt;LM Studio&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Open Weight Model vs Open Source Model
&lt;/h2&gt;

&lt;p&gt;An &lt;strong&gt;open-weight model&lt;/strong&gt; shares its model weights. So, we can run them, fine-tune them, and host them on a local system.&lt;/p&gt;

&lt;p&gt;Here, the training code, data, and full methodology are not shared.&lt;/p&gt;

&lt;p&gt;Whereas, in an &lt;strong&gt;open-source model&lt;/strong&gt;, the weights, training code, data, and sometimes the dataset are shared.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Do We Need to Use LLMs?
&lt;/h2&gt;

&lt;p&gt;LLM is a &lt;strong&gt;next-word predictor&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Suppose we ask:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Hi, how..."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The answer can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How are you?&lt;/li&gt;
&lt;li&gt;How do you do?&lt;/li&gt;
&lt;li&gt;How is your life?&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are possibilities.&lt;/p&gt;

&lt;p&gt;Here, most of the time, the answer will be &lt;strong&gt;"How are you?"&lt;/strong&gt; because if a word has more presence, it has a higher possibility of occurring.&lt;/p&gt;

&lt;p&gt;Each possibility will have a score between &lt;strong&gt;0 and 1&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We have &lt;strong&gt;3 controlling parameters&lt;/strong&gt; to control the output generated by the LLM.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Temperature
&lt;/h3&gt;

&lt;p&gt;Usually set from &lt;strong&gt;0–1&lt;/strong&gt;. It controls the randomness of the model.&lt;/p&gt;

&lt;p&gt;If the value is &lt;strong&gt;0–0.3&lt;/strong&gt;, which is low, it means generating the most likely words, i.e., facts or commonly occurring words.&lt;/p&gt;

&lt;p&gt;If the value is high, the model will choose less likely words.&lt;/p&gt;

&lt;p&gt;We use this high value in &lt;strong&gt;storytelling and creative writing&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Top K
&lt;/h3&gt;

&lt;p&gt;Controls the number of possibilities.&lt;/p&gt;

&lt;p&gt;For example, &lt;strong&gt;K = 3&lt;/strong&gt; means choosing only the 3 most likely possibilities.&lt;/p&gt;

&lt;p&gt;Top K will be used along with Temperature.&lt;/p&gt;

&lt;p&gt;For example, if we set &lt;strong&gt;Top K = 5&lt;/strong&gt; and &lt;strong&gt;Temperature = 0.5&lt;/strong&gt;, the LLM will take possibilities from the selected Top K values based on the temperature.&lt;/p&gt;

&lt;p&gt;Top K is used to limit the number of possibilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Top P
&lt;/h3&gt;

&lt;p&gt;It is also called a &lt;strong&gt;sampling method&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The possibility scores are added up until they reach the defined value in Top P.&lt;/p&gt;

&lt;p&gt;Top P is also used along with &lt;strong&gt;Temperature&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Tokens
&lt;/h1&gt;

&lt;p&gt;Tokens are the process of splitting words into small pieces. A small piece may not be complete.&lt;/p&gt;

&lt;p&gt;For example, a token can be split into &lt;strong&gt;"to"&lt;/strong&gt; and &lt;strong&gt;"kens"&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;These are called &lt;strong&gt;tokens&lt;/strong&gt;, and the process is called &lt;strong&gt;tokenization&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A tokenizer, such as those used by &lt;strong&gt;OpenAI and GPT&lt;/strong&gt;, can be used.&lt;/p&gt;

&lt;p&gt;We can specify the size of the token that we want to split.&lt;/p&gt;

&lt;p&gt;Each token will be represented by a number, which in turn is converted into an embedding.&lt;/p&gt;

&lt;h1&gt;
  
  
  Context Window
&lt;/h1&gt;

&lt;p&gt;It is a &lt;strong&gt;short-term memory&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The context window is the maximum number of tokens that a model can see at a given time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Short context window&lt;/strong&gt; and &lt;strong&gt;long context window&lt;/strong&gt; are the types.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>llm</category>
    </item>
    <item>
      <title>AI Agents - Data Structures in Python</title>
      <dc:creator>Ramya Perumal</dc:creator>
      <pubDate>Sun, 30 Aug 2026 22:07:35 +0000</pubDate>
      <link>https://dev.to/ramya_perumal/ai-agents-data-structures-in-python-4152</link>
      <guid>https://dev.to/ramya_perumal/ai-agents-data-structures-in-python-4152</guid>
      <description>&lt;p&gt;Data Structure means data stored in some structured format. How will we store strings, integers, and booleans in a data structure? Here we will see List, Dictionary, Tuple, and Set data structures in details.&lt;/p&gt;

&lt;p&gt;Data structures can be treated as containers.&lt;/p&gt;

&lt;h3&gt;
  
  
  List
&lt;/h3&gt;

&lt;p&gt;It is a dynamic array. An array is a collection of data that is stored consecutively. In Java or other languages, for a normal array, we have to specify the size to refer to the data. Every array has an index that points to the value of the array. The index starts from 0.&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%2Ff1y9jtum9tksnqkh37fn.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%2Ff1y9jtum9tksnqkh37fn.png" alt=" " width="733" height="361"&gt;&lt;/a&gt;&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;num&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="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;num&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="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An array will maintain the data insertion order.&lt;/p&gt;

&lt;p&gt;Dynamic array means allocating more space at runtime.&lt;/p&gt;

&lt;p&gt;We can store heterogeneous data in the list, which means storing different data types or structures inside a single sequential collection.&lt;/p&gt;

&lt;p&gt;E.g.&lt;br&gt;
nums = [2, 3, 6, 8, 0, 1]&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;nums&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="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;access&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="mi"&gt;0&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;nums&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;find&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;
&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;access&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;

&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;empty&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;
&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;occurrences&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;particular&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;
&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;entire&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;
&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;sort&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;
&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&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="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;insert&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are the functions that can be used with a list.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dictionary
&lt;/h3&gt;

&lt;p&gt;Dictionary means a key-value pair.&lt;/p&gt;

&lt;p&gt;Syntax:&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;dict_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;student1&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;name&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;some name&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;age&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the key is immutable. The key can be either a string, boolean, integer, or tuple.&lt;/p&gt;

&lt;p&gt;Generally, to search for a particular value, we need to search all the values one by one. But in a dictionary, by using the key, fetching time will be faster compared to other data structures. We can retrieve the value in O(1) time.&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="nb"&gt;dict&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="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;
&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;dictionary&lt;/span&gt;
&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;dictionary&lt;/span&gt;
&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;dictionary&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are the functions associated with a dictionary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tuple
&lt;/h3&gt;

&lt;p&gt;An analogy for a tuple is taking a screenshot. Once we take the screenshot, we cannot change anything inside it. The same is applicable to a tuple. Once a tuple is created, we cannot change its values. We can delete the tuple by using the &lt;code&gt;del&lt;/code&gt; keyword.&lt;/p&gt;

&lt;p&gt;Syntax:&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;tuple_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A tuple is created mainly to preserve values as original and to maintain their integrity. So, it is immutable. Lists and dictionaries are mutable, where we can change the values in them.&lt;/p&gt;

&lt;p&gt;Functions can always return a tuple.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set
&lt;/h2&gt;

&lt;p&gt;Set is a collection of unique elements. Here, duplication of elements is not allowed. To implement this, hashing methodology is implemented internally. It is the same as set operations in mathematics.&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%2F2t82rsowc21fw4jr5geu.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%2F2t82rsowc21fw4jr5geu.png" alt=" " width="505" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Syntax:&lt;/p&gt;

&lt;p&gt;set_name = {element1, element2, element3}&lt;/p&gt;

&lt;p&gt;Set does not maintain the user-specified order. Even if we try to add duplicates, it will not allow them.&lt;/p&gt;

&lt;p&gt;Set will add the new element at any index. That is why it does not have an index. &lt;/p&gt;

&lt;p&gt;Some of the methods in Set:&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;set_name1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;union&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;set_name2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;union&lt;/span&gt; &lt;span class="n"&gt;between&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt; &lt;span class="n"&gt;sets&lt;/span&gt;  
&lt;span class="n"&gt;set_name1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;intersection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;set_name2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;common&lt;/span&gt; &lt;span class="n"&gt;elements&lt;/span&gt; &lt;span class="n"&gt;between&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt; &lt;span class="n"&gt;sets&lt;/span&gt; 
&lt;span class="n"&gt;set_name1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;issubset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;set_name2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;check&lt;/span&gt; &lt;span class="n"&gt;set1&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;subset&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;set2&lt;/span&gt; 
&lt;span class="n"&gt;set_name1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;issuperset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;set_name2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;check&lt;/span&gt; &lt;span class="n"&gt;set1&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;superset&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;set2&lt;/span&gt;
&lt;span class="n"&gt;set_name1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;remove&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;
&lt;span class="n"&gt;set_name1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;remove&lt;/span&gt; &lt;span class="n"&gt;specified&lt;/span&gt; &lt;span class="n"&gt;elements&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>ai</category>
      <category>python</category>
      <category>agents</category>
    </item>
    <item>
      <title>AI Agents - Python basics</title>
      <dc:creator>Ramya Perumal</dc:creator>
      <pubDate>Tue, 25 Aug 2026 22:03:25 +0000</pubDate>
      <link>https://dev.to/ramya_perumal/ai-agents-python-basics-52ff</link>
      <guid>https://dev.to/ramya_perumal/ai-agents-python-basics-52ff</guid>
      <description>&lt;p&gt;AI Agents - Python Basics&lt;/p&gt;

&lt;p&gt;Why do we need to use Python to create AI agents?&lt;br&gt;
Because the number of users in the community is bigger, and the number of libraries is more compared to other languages.&lt;br&gt;
Why not use popular languages like Java or Go? Because every language is used for different purposes.&lt;/p&gt;

&lt;p&gt;Python is called an interpreted language, which means it executes the code line by line and does not compile it first. Other languages like Java and C++ compile the code (i.e., convert it into binaries, 0s and 1s) and execute it from the compiled file.&lt;/p&gt;

&lt;p&gt;Print Function&lt;/p&gt;

&lt;p&gt;Prints the content in the console that is inside the function.&lt;/p&gt;

&lt;p&gt;A function is simply a plan to do a task repeatedly. Here, we create a function when we do not want to repeatedly do the same work again and again.&lt;/p&gt;

&lt;p&gt;Syntax:&lt;/p&gt;

&lt;p&gt;def function_name(parameter_list):&lt;br&gt;
    return&lt;/p&gt;

&lt;p&gt;E.g.&lt;/p&gt;

&lt;p&gt;print("Hello World")&lt;/p&gt;

&lt;p&gt;print - is the function_name, and "Hello World" is printed in the console.&lt;/p&gt;

&lt;p&gt;print("Hello World", "Hi")&lt;/p&gt;

&lt;p&gt;Identifier&lt;/p&gt;

&lt;p&gt;name = "some name"&lt;/p&gt;

&lt;p&gt;The value will be stored in RAM.&lt;/p&gt;

&lt;p&gt;There are two types of memory in a computer.&lt;/p&gt;

&lt;p&gt;RAM - Random Access Memory - Temporary memory used to access data faster for computational purposes.&lt;/p&gt;

&lt;p&gt;ROM - Read Only Memory - Hard drive.&lt;/p&gt;

&lt;p&gt;Initially, the OS will be stored in the ROM or hard drive. The OS will not run directly from the ROM. When the computer starts, the OS files will be moved to RAM because fetching data from RAM will be much faster. Since RAM is costly, we cannot store all the data in it.&lt;/p&gt;

&lt;p&gt;"some name" will be stored somewhere in RAM. We cannot remember the memory address for the process all the time, so we assign a label called "name". In Python, there is no concept called a "Variable". The same label can be replaced with a different memory address. So, the "name" identifier will point to the address where the value is stored.&lt;/p&gt;

&lt;p&gt;E.g.&lt;/p&gt;

&lt;p&gt;age = 30&lt;br&gt;
Flag = True&lt;br&gt;
name = "Peter"&lt;/p&gt;

&lt;p&gt;These are string/boolean/integer/None types of values that can be stored in the identifier.&lt;/p&gt;

&lt;p&gt;In Python, everything will be treated as an object. Each object has attributes and functions. Each object may or may not have attributes and functions. To know whether a particular object has attributes and functions, use the method called 'dir'.&lt;/p&gt;

&lt;p&gt;dir(age)&lt;/p&gt;

&lt;p&gt;It will list down the attributes and functions associated with the object.&lt;/p&gt;

&lt;h3&gt;
  
  
  Acknowledgment
&lt;/h3&gt;

&lt;p&gt;A special thanks to my mentor &lt;strong&gt;Syed Jafer&lt;/strong&gt; for the continuous guidance and support throughout these sessions. I truly appreciate the effort taken to explain each concept clearly and make the learning process easier.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>agents</category>
    </item>
    <item>
      <title>RAG - Hallucination Detection</title>
      <dc:creator>Ramya Perumal</dc:creator>
      <pubDate>Fri, 21 Aug 2026 00:54:08 +0000</pubDate>
      <link>https://dev.to/ramya_perumal/rag-hallucination-detection-2k60</link>
      <guid>https://dev.to/ramya_perumal/rag-hallucination-detection-2k60</guid>
      <description>&lt;h1&gt;
  
  
  Hallucination
&lt;/h1&gt;

&lt;p&gt;Hallucination means making an assumption or making up something when the LLM does not know the answer.&lt;/p&gt;

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

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;Suppose we have a PDF file that contains information about Python, but it does not have any details about &lt;strong&gt;Decorators&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here, the document is split into chunks, and the chunks are stored in the vector database.&lt;/p&gt;

&lt;p&gt;Suppose we ask the query:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"What is a decorator?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The LLM should not give any response because the information about decorators is not available in the database.&lt;/p&gt;

&lt;p&gt;But the LLM may give a response from its own knowledge, which may be correct, but it is &lt;strong&gt;not from the database&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is called &lt;strong&gt;hallucination&lt;/strong&gt; in RAG.&lt;/p&gt;

&lt;h2&gt;
  
  
  Methods to Measure Hallucination
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Knowledge Groundedness
&lt;/h3&gt;

&lt;p&gt;The response given by the LLM should be supported by the information given in the context.&lt;/p&gt;

&lt;p&gt;If the response is not supported by the context, it is considered hallucinated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ways to Detect Hallucination
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Embedding
&lt;/h3&gt;

&lt;p&gt;Compare the embedding of the context with the embedding of the LLM response to check how closely they are related.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. LettuceDetect
&lt;/h3&gt;

&lt;p&gt;LettuceDetect is a BERT-based model used to find where hallucinations could occur at the character level.&lt;/p&gt;

&lt;p&gt;It checks the response word by word to identify possible hallucinations.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. LLM as a Judge
&lt;/h3&gt;

&lt;p&gt;Give the response to another LLM and ask it to detect hallucinations.&lt;/p&gt;

&lt;p&gt;The drawback here is that the LLM may hallucinate again, and it can also be expensive unless we use a local model.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. RAGAS Framework
&lt;/h3&gt;

&lt;p&gt;RAGAS is also called an &lt;strong&gt;evaluation framework&lt;/strong&gt;. It provides different metrics that can be used to evaluate RAG systems and identify potential hallucinations.&lt;/p&gt;

&lt;p&gt;Some of the important metrics are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Faithfulness&lt;/strong&gt; – Checks whether the results are backed by the provided context. This can be used to check hallucination.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Answer Relevancy&lt;/strong&gt; – Suppose the context and answer are relevant. This metric checks how relevant the answer is to the query.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Context Precision&lt;/strong&gt; – Checks how many of the retrieved documents are useful and relevant.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Context Recall&lt;/strong&gt; – Checks whether the necessary documents have been retrieved for the query.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Answer Correctness&lt;/strong&gt; – Checks the response against the ground truth.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Answer Similarity&lt;/strong&gt; – Checks the semantic similarity between the expected answer and the generated answer.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;RAGAS can be used in a &lt;strong&gt;CI/CD pipeline&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We can write unit test cases and compare the actual answer with the expected answer using the above metrics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DeepEval&lt;/strong&gt; can also be used to evaluate RAG systems and detect hallucinations.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>nlp</category>
    </item>
    <item>
      <title>RAG - Async Pipelines, MCP</title>
      <dc:creator>Ramya Perumal</dc:creator>
      <pubDate>Tue, 18 Aug 2026 19:47:08 +0000</pubDate>
      <link>https://dev.to/ramya_perumal/rag-async-pipelines-mcp-4j8j</link>
      <guid>https://dev.to/ramya_perumal/rag-async-pipelines-mcp-4j8j</guid>
      <description>&lt;h2&gt;
  
  
  What is Synchronous?
&lt;/h2&gt;

&lt;p&gt;Everything goes sequentially.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example:
&lt;/h3&gt;

&lt;p&gt;P1, P2, and P3 are the three processes.&lt;/p&gt;

&lt;p&gt;Synchronous means P2 will start when P1 starts and finishes its job. P3 will start when P2 starts and finishes its job.&lt;/p&gt;

&lt;p&gt;It is not required all the time.&lt;/p&gt;

&lt;p&gt;During retrieval, in the case of &lt;strong&gt;hybrid search&lt;/strong&gt;, first we will do vector search, then text search, and then any work related to semantic caching / context search.&lt;/p&gt;

&lt;p&gt;The goal here is to give more relevant context to the LLM.&lt;/p&gt;

&lt;p&gt;Suppose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vector search takes 10 seconds&lt;/li&gt;
&lt;li&gt;Text search takes 5 seconds&lt;/li&gt;
&lt;li&gt;Semantic caching / context search takes 2 seconds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the case of a sequential process, we need to wait &lt;strong&gt;17 seconds&lt;/strong&gt; to get the context.&lt;/p&gt;

&lt;p&gt;So, is there any way we can reduce the waiting time?&lt;/p&gt;

&lt;p&gt;The answer is &lt;strong&gt;Async Pipelines&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here, we will start 3 threads at the same time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One thread will do vector search.&lt;/li&gt;
&lt;li&gt;Another thread will do text search.&lt;/li&gt;
&lt;li&gt;The third thread will do semantic caching / context search.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Their finishing times may be different.&lt;/p&gt;

&lt;p&gt;At most, we have to wait only &lt;strong&gt;10 seconds&lt;/strong&gt; to get the context.&lt;/p&gt;

&lt;p&gt;Through this async pipeline, we are reducing latency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context Switching
&lt;/h2&gt;

&lt;p&gt;A single thread switches between multiple tasks when needed. It is also called &lt;strong&gt;parallel processing&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multithreading
&lt;/h2&gt;

&lt;p&gt;Each task will be allotted a separate thread. So, it can finish on its own time.&lt;/p&gt;

&lt;p&gt;These threads are limited to the available CPU cores.&lt;/p&gt;

&lt;p&gt;We can see the real difference in latency when we do this at the production level.&lt;/p&gt;

&lt;h1&gt;
  
  
  MCP - Model Context Protocol
&lt;/h1&gt;

&lt;p&gt;If we ask the question &lt;strong&gt;"What happened today?"&lt;/strong&gt;, an LLM cannot answer.&lt;/p&gt;

&lt;p&gt;If we ask the same question to ChatGPT or Gemini, it gives a response. How?&lt;/p&gt;

&lt;p&gt;Because of &lt;strong&gt;tool calling&lt;/strong&gt;, which means attaching some tools or functionality to the LLM. The result of the tool will be fed into the LLM.&lt;/p&gt;

&lt;p&gt;The application developer will be responsible for writing the code for the tool/functionality.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Suppose the idea of the application is to fetch weather details.&lt;/p&gt;

&lt;p&gt;Every developer may write their own code to fetch the weather details. At the end, all users/developers will get more or less the same result.&lt;/p&gt;

&lt;p&gt;This is not the right approach.&lt;/p&gt;

&lt;p&gt;So, here comes the concept of &lt;strong&gt;MCP&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The responsible body/owner that provides the weather details will write the common tool or protocol (a set of rules).&lt;/p&gt;

&lt;p&gt;The consumer/developer will use the common tool/protocol to fetch the result.&lt;/p&gt;

&lt;p&gt;Here, the developer does not need to write their own code.&lt;/p&gt;

&lt;p&gt;The common tool/protocol is called &lt;strong&gt;MCP&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;MCP will have functions and their descriptions. The LLM will decide which function to call.&lt;/p&gt;

&lt;p&gt;We can call the tool either by:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. StdIO (Standard Input/Output)
&lt;/h3&gt;

&lt;p&gt;MCP is within the same machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. HTTP
&lt;/h3&gt;

&lt;p&gt;We can also use the HTTP method to call the MCP, such as calling an API.&lt;/p&gt;

&lt;p&gt;However, we are introducing latency when using HTTP.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is the Relation Between MCP and RAG?
&lt;/h1&gt;

&lt;p&gt;Create an MCP for a RAG system.&lt;/p&gt;

&lt;p&gt;For example, suppose we have built a RAG system using documents that we gathered.&lt;/p&gt;

&lt;p&gt;Since you have the database and RAG system, you are the only person who can invoke the RAG system directly.&lt;/p&gt;

&lt;p&gt;Instead of keeping the RAG functionality restricted to your application, we can expose the RAG functionality through &lt;strong&gt;MCP&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We can segregate the functionality according to different responsibilities or divisions.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;RAG system → Responsible for retrieving relevant information from the documents&lt;/li&gt;
&lt;li&gt;MCP → Exposes the RAG functionality as a common tool&lt;/li&gt;
&lt;li&gt;LLM/Application → Can invoke the MCP tool when it needs information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, anyone who has access to the MCP can use the RAG functionality without directly accessing the underlying database or writing their own retrieval code.&lt;/p&gt;

&lt;p&gt;In this way, &lt;strong&gt;MCP acts as a common interface between the RAG system and different applications or LLMs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The RAG system continues to handle document retrieval, while MCP provides a standardized way for other applications or agents to access that functionality.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>nlp</category>
    </item>
    <item>
      <title>RAG - Memory Systems</title>
      <dc:creator>Ramya Perumal</dc:creator>
      <pubDate>Thu, 13 Aug 2026 18:08:59 +0000</pubDate>
      <link>https://dev.to/ramya_perumal/rag-memory-systems-17aj</link>
      <guid>https://dev.to/ramya_perumal/rag-memory-systems-17aj</guid>
      <description>&lt;p&gt;We need memory to store the previous conversational history. &lt;/p&gt;

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

&lt;p&gt;Previous question is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User:&lt;/strong&gt; File handling in Python&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Assistant:&lt;/strong&gt; Explain about file handling.&lt;/p&gt;

&lt;p&gt;Next time, the user asks:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User:&lt;/strong&gt; What are the modes in it?&lt;/p&gt;

&lt;p&gt;The LLM should understand the context and then respond.&lt;/p&gt;




&lt;p&gt;Below are the details that can be stored in the memory.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Past Conversations&lt;/li&gt;
&lt;li&gt;User Preferences that we specify in the system prompts, e.g., JSON format&lt;/li&gt;
&lt;li&gt;Past Decisions&lt;/li&gt;
&lt;li&gt;Previous Tasks&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Based on the details we are storing, we will choose between long-term or short-term memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Short-Term Memory
&lt;/h2&gt;

&lt;p&gt;Redis, Valkey, Memcached, and Cosmos, which are cached databases, can be used for short-term memory to store the last few conversations or a summary.&lt;/p&gt;

&lt;p&gt;We can set a general data invalidation rule to erase the content or use an &lt;strong&gt;LRU cache eviction policy&lt;/strong&gt;, where the least recently used data will be erased from the database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Long-Term Memory
&lt;/h2&gt;

&lt;p&gt;Postgres, Pinecone, and MongoDB can be used for long-term memory to store long conversation histories.&lt;/p&gt;

&lt;h3&gt;
  
  
  How It Is Functioning
&lt;/h3&gt;

&lt;p&gt;A summary of the entire conversation history will be stored in short-term memory to reduce latency whenever needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Episodic Memory
&lt;/h2&gt;

&lt;p&gt;Episodic memory is a type of memory that stores specific events or experiences that happened in the past, usually together with information about what happened, when it happened, and the context surrounding it.&lt;/p&gt;

&lt;p&gt;We can use either a short-term or long-term memory database depending on the use case. It is a kind of combination of short-term and long-term memory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I am planning a trip to Paris.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agent:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
How many days will you stay?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
5 days.&lt;/p&gt;

&lt;p&gt;Later,&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Can you suggest an itinerary?&lt;/p&gt;

&lt;h3&gt;
  
  
  Episode 1
&lt;/h3&gt;

&lt;p&gt;User wants to travel to Paris.&lt;/p&gt;

&lt;p&gt;Trip duration: 5 days.&lt;/p&gt;

&lt;p&gt;User previously mentioned:&lt;/p&gt;

&lt;p&gt;Destination = Paris&lt;br&gt;&lt;br&gt;
Duration = 5 days&lt;/p&gt;

&lt;p&gt;This information can be used to provide a more relevant response.&lt;/p&gt;

&lt;p&gt;This helps the LLM understand what happened previously.&lt;/p&gt;

&lt;h2&gt;
  
  
  Semantic Memory
&lt;/h2&gt;

&lt;p&gt;Semantic memory contains facts extracted from previous conversational history. Semantic memory is generally considered long-term memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Paris is the capital of France.&lt;/p&gt;

&lt;p&gt;The Louvre is a museum in Paris.&lt;/p&gt;

&lt;p&gt;France uses the Euro.&lt;/p&gt;

&lt;p&gt;That's general knowledge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sliding Window Memory
&lt;/h2&gt;

&lt;p&gt;It is a short-term memory. Here, we store the last 3 to 4 conversations.&lt;/p&gt;

&lt;p&gt;Redis or Valkey, like any cache memory, can be used.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summarized Memory
&lt;/h2&gt;

&lt;p&gt;Each and every time, the conversation, which includes the user query and response, will be summarized.&lt;/p&gt;

&lt;p&gt;Even though token consumption during summarization is more, overall token consumption will be less.&lt;/p&gt;

&lt;p&gt;It is a long-term memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entity Fact Memory
&lt;/h2&gt;

&lt;p&gt;This memory is used to store facts about a particular entity.&lt;/p&gt;

&lt;p&gt;The difference between entity fact memory and semantic memory is that &lt;strong&gt;semantic memory is the broader category&lt;/strong&gt;. Entity fact memory is one way of organizing and storing semantic knowledge about specific entities.&lt;/p&gt;

&lt;p&gt;It can be used as either long-term or short-term memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Semantic Memory
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Entity: Python&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Python → is a programming language&lt;br&gt;&lt;br&gt;
Python → is used for AI&lt;br&gt;&lt;br&gt;
Python → supports object-oriented programming&lt;br&gt;&lt;br&gt;
Python → was created by Guido van Rossum&lt;/p&gt;

&lt;h3&gt;
  
  
  Entity Fact Memory
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Entity: Alice&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Alice → works at ABC Company&lt;br&gt;&lt;br&gt;
Alice → prefers Python&lt;br&gt;&lt;br&gt;
Alice → is working on Project X&lt;/p&gt;

&lt;p&gt;It is not a good practice to store the entire conversation. We can make decisions based on the conversation and then store the relevant information. This is a good practice.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>nlp</category>
    </item>
    <item>
      <title>RAG - Multivector Retrievel, Multi Hop, Conversational RAG</title>
      <dc:creator>Ramya Perumal</dc:creator>
      <pubDate>Wed, 12 Aug 2026 17:51:51 +0000</pubDate>
      <link>https://dev.to/ramya_perumal/rag-multivector-retrievel-multi-hop-conversational-rag-km7</link>
      <guid>https://dev.to/ramya_perumal/rag-multivector-retrievel-multi-hop-conversational-rag-km7</guid>
      <description>&lt;h2&gt;
  
  
  Multi-Vector Retrieval
&lt;/h2&gt;

&lt;p&gt;In a typical RAG pipeline, every chunk is converted into an embedding and stored in the vector database.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Multi-Vector Retrieval&lt;/strong&gt;, instead of creating a single embedding for a chunk, multiple embeddings are created to represent different aspects of the original chunk.&lt;/p&gt;

&lt;p&gt;Each embedding captures a different perspective of the same content. The metadata of each embedding contains a reference to the original chunk.&lt;/p&gt;

&lt;p&gt;When a user query is received, the retriever searches across all these embeddings. Since each embedding represents a different aspect of the content, the chances of retrieving more relevant information are higher.&lt;/p&gt;

&lt;p&gt;This approach generally provides better retrieval performance.&lt;/p&gt;

&lt;p&gt;However, it is a &lt;strong&gt;costly approach&lt;/strong&gt; because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple embeddings are generated for every chunk.&lt;/li&gt;
&lt;li&gt;More storage is required in the vector database.&lt;/li&gt;
&lt;li&gt;More tokens are consumed during embedding generation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If no other optimization technique is able to improve the RAG performance, &lt;strong&gt;Multi-Vector Retrieval&lt;/strong&gt; can be considered as a final optimization step.&lt;/p&gt;




&lt;h1&gt;
  
  
  Multi-Hop
&lt;/h1&gt;

&lt;p&gt;Multi-Hop Retrieval is used when the answer cannot be obtained from a single piece of context. Instead, the LLM has to retrieve multiple related contexts and connect them to generate the final answer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Suppose the knowledge base contains the following information:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Biryani contains spices.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The spices used in biryani are cardamom, cinnamon, cloves, etc.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now suppose the user asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"What spices need to be added to biryani?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The LLM first retrieves the information:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"Biryani contains spices."&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It then &lt;strong&gt;hops&lt;/strong&gt; to the next related context:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"The spices used in biryani are cardamom, cinnamon, cloves, etc."&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Finally, it combines both pieces of information to generate the complete answer.&lt;/p&gt;

&lt;p&gt;In this process, the LLM &lt;strong&gt;hops from one retrieved context to another&lt;/strong&gt; until it gathers enough information to answer the user's query.&lt;/p&gt;

&lt;p&gt;Each retrieved context should have a meaningful relationship with the next one so that the LLM can follow the chain of information and produce the correct response.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conversational RAG
&lt;/h1&gt;

&lt;p&gt;A user may not restrict themselves to asking only one query. They may ask a sequence of queries. Here, we are going to look at how to build &lt;strong&gt;Conversational RAG&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Traditional Flow
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;User Query&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Retriever&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related Documents&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;LLM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Answer&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A user may ask questions that are indirect or related to the previous question. So, we need to implement &lt;strong&gt;Query Transformation and Expansion&lt;/strong&gt; to get the related queries and their responses.&lt;/p&gt;

&lt;p&gt;Therefore, we need to have memory to store the previous conversation history.&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%2Fhqaubq2088jxc2ogjldf.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%2Fhqaubq2088jxc2ogjldf.png" alt=" " width="351" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Conversational RAG will be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Conversation History + Current Question&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Intent&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Query Transformation and Expansion&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Retriever&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Relevant Context&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;LLM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Context-Aware Answer&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here, we are going to see how we can store conversation history in memory.&lt;/p&gt;

&lt;p&gt;We can use &lt;strong&gt;persistent memory&lt;/strong&gt; such as PostgreSQL or SQLite, or &lt;strong&gt;short-term memory&lt;/strong&gt; using Redis, Valkey, Memcached, etc. We can also use a pickle file to store the history.&lt;/p&gt;

&lt;p&gt;If we are using a file, make sure that the application we are using is &lt;strong&gt;single-threaded&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To store the history, we can use the &lt;strong&gt;session ID&lt;/strong&gt; as the primary key.&lt;/p&gt;

&lt;p&gt;Always store the entire history in long-term memory. However, we cannot store the entire history in short-term memory.&lt;/p&gt;

&lt;p&gt;The purpose of storing history in short-term memory is to reduce latency.&lt;/p&gt;

&lt;p&gt;To solve this problem, we can store the entire history in long-term memory and summarize the conversation history and store the summary in short-term memory whenever needed.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>nlp</category>
      <category>rag</category>
    </item>
    <item>
      <title>RAG - Parent Retriever</title>
      <dc:creator>Ramya Perumal</dc:creator>
      <pubDate>Wed, 05 Aug 2026 01:52:04 +0000</pubDate>
      <link>https://dev.to/ramya_perumal/rag-parent-retriever-49dd</link>
      <guid>https://dev.to/ramya_perumal/rag-parent-retriever-49dd</guid>
      <description>&lt;h2&gt;
  
  
  RAG Pipeline Optimization Techniques
&lt;/h2&gt;

&lt;p&gt;The following techniques are commonly used to optimize a RAG pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Semantic Caching&lt;/li&gt;
&lt;li&gt;Query Transformation and Expansion&lt;/li&gt;
&lt;li&gt;Context Compression&lt;/li&gt;
&lt;li&gt;Parent Retrieval&lt;/li&gt;
&lt;li&gt;Multi-Vector Retrieval&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These techniques are used to improve the quality of the responses generated by the LLM.&lt;/p&gt;




&lt;h2&gt;
  
  
  Parent Retrieval
&lt;/h2&gt;

&lt;p&gt;Today, we are going to focus on &lt;strong&gt;Parent Retrieval&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A chunk is a small portion of a document or paragraph, typically consisting of &lt;strong&gt;500–1000 words&lt;/strong&gt;. When these chunks are converted into embeddings and stored in a vector database, semantically related chunks are positioned close to one another.&lt;/p&gt;

&lt;p&gt;When a user submits a query, the system retrieves the chunks that are closest to the query. However, not all the retrieved chunks may be the most relevant. Sometimes, we may miss other chunks that provide better context for the user's query.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Suppose we have the following paragraphs:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Paragraph 1 (P1)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;L1&lt;/li&gt;
&lt;li&gt;L2&lt;/li&gt;
&lt;li&gt;L3&lt;/li&gt;
&lt;li&gt;L4&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each line is stored as an individual chunk:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;P1C1&lt;/li&gt;
&lt;li&gt;P1C2&lt;/li&gt;
&lt;li&gt;P1C3&lt;/li&gt;
&lt;li&gt;P1C4&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Paragraph 2 (P2)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;L1&lt;/li&gt;
&lt;li&gt;L2&lt;/li&gt;
&lt;li&gt;L3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each line is also stored as individual chunks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;P2C1&lt;/li&gt;
&lt;li&gt;P2C2&lt;/li&gt;
&lt;li&gt;P2C3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Suppose the expected answer to the user query is &lt;strong&gt;P1C2&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The vector database retrieves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;P1C2&lt;/li&gt;
&lt;li&gt;P2C3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although &lt;strong&gt;P1C2&lt;/strong&gt; is correctly retrieved, the related chunks &lt;strong&gt;P1C1&lt;/strong&gt;, &lt;strong&gt;P1C3&lt;/strong&gt;, and &lt;strong&gt;P1C4&lt;/strong&gt; may provide much better context than &lt;strong&gt;P2C3&lt;/strong&gt;. Since these chunks are not retrieved, we may lose important context that could improve the final LLM response.&lt;/p&gt;




&lt;p&gt;If we store the document paragraph-wise instead of using smaller chunks, we may retrieve unnecessary context, which increases token consumption.&lt;/p&gt;




&lt;h2&gt;
  
  
  Solution – Parent Retrieval
&lt;/h2&gt;

&lt;p&gt;Suppose &lt;strong&gt;Paragraph 1&lt;/strong&gt; is divided into four chunks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;P1C1&lt;/li&gt;
&lt;li&gt;P1C2&lt;/li&gt;
&lt;li&gt;P1C3&lt;/li&gt;
&lt;li&gt;P1C4&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whenever a specific chunk is retrieved from the vector database, it also contains a reference to its &lt;strong&gt;parent paragraph&lt;/strong&gt;, which is stored in the chunk's metadata.&lt;/p&gt;

&lt;p&gt;For example, if &lt;strong&gt;P1C2&lt;/strong&gt; is retrieved, the metadata also contains a reference to &lt;strong&gt;Paragraph 1&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Using this reference, the retriever can also fetch the remaining chunks belonging to the same parent paragraph:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;P1C1&lt;/li&gt;
&lt;li&gt;P1C3&lt;/li&gt;
&lt;li&gt;P1C4&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures that we do not miss important context that is closely related to the user's query.&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%2Fenyocpggmr7cuoiwem66.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%2Fenyocpggmr7cuoiwem66.png" alt=" " width="447" height="406"&gt;&lt;/a&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%2F973079vpt09pl2cwliy6.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%2F973079vpt09pl2cwliy6.png" alt=" " width="298" height="435"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;Suppose the user query is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"Create a dictionary"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The retrieved chunks are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;P1C2&lt;/li&gt;
&lt;li&gt;P2C2&lt;/li&gt;
&lt;li&gt;P2C3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of sending only these chunks to the LLM, Parent Retrieval also includes the remaining chunks from the same parent paragraph:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;P1C1&lt;/li&gt;
&lt;li&gt;P1C3&lt;/li&gt;
&lt;li&gt;P1C4&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Providing this additional context enables the LLM to generate a more accurate response.&lt;/p&gt;




&lt;h2&gt;
  
  
  When Should Parent Retrieval Be Used?
&lt;/h2&gt;

&lt;p&gt;Parent Retrieval is useful when we feel that important context is missing from the retrieved chunks and we want to include additional context that is closely related to the query.&lt;/p&gt;

&lt;p&gt;The parent paragraph is stored similarly to other chunks. However, it is &lt;strong&gt;not used directly for vector search&lt;/strong&gt;. Instead, its reference is stored in each chunk's metadata, allowing the retriever to fetch the parent context whenever required.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>nlp</category>
    </item>
    <item>
      <title>RAG - Context Compression</title>
      <dc:creator>Ramya Perumal</dc:creator>
      <pubDate>Thu, 30 Jul 2026 01:58:52 +0000</pubDate>
      <link>https://dev.to/ramya_perumal/rag-context-compression-bok</link>
      <guid>https://dev.to/ramya_perumal/rag-context-compression-bok</guid>
      <description>&lt;p&gt;In a RAG pipeline, documents are first split into chunks, converted into embeddings, and stored in a vector database.&lt;/p&gt;

&lt;p&gt;When a user query arrives, it is converted into an embedding and used to retrieve relevant results from the vector database. Although the retrieved results may be relevant, they may not always be directly related to the user's query.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;User Query&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"FastAPI dependency injection"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The retrieved results may include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Use FastAPI in deployment"&lt;/li&gt;
&lt;li&gt;"How to dockerize a FastAPI application"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These results may be semantically related to FastAPI, but they are not necessarily the most accurate results for the user's query. This depends on how the documents were embedded and stored in the vector database.&lt;/p&gt;

&lt;p&gt;To improve the quality of the retrieved context, the fetched results can be compressed into one or two chunks before they are passed to the augmentation phase. This reduces the number of tokens used during augmentation and acts as an optimization technique.&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%2F015ssrvunq72fhy559f3.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%2F015ssrvunq72fhy559f3.png" alt=" " width="679" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the above example, the chunks retrieved from the vector database may not be completely relevant to the user query. Therefore, we compress the retrieved chunks without changing their original context and create one or two chunks that are more relevant to the query.&lt;/p&gt;

&lt;p&gt;Context compression is &lt;strong&gt;not&lt;/strong&gt; a mandatory step in every RAG pipeline. It is generally adopted based on trial and error and depends on the application's requirements.&lt;/p&gt;

&lt;p&gt;This compression technique is mainly useful when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There are token constraints.&lt;/li&gt;
&lt;li&gt;Higher-quality retrieval results are expected.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Context Compression Techniques
&lt;/h2&gt;

&lt;p&gt;There are different approaches for context compression:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;LLM-based Compression&lt;/li&gt;
&lt;li&gt;Embedding-based Compression&lt;/li&gt;
&lt;li&gt;Keyword-based Compression&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. LLM-based Compression
&lt;/h2&gt;

&lt;p&gt;In this approach, the relevant chunks retrieved from the vector database are given to an LLM for compression.&lt;/p&gt;

&lt;p&gt;For example, suppose four chunks are retrieved from the vector database. Instead of sending all four chunks to the main LLM, they are first passed to another LLM whose responsibility is only to compress them into one or two meaningful chunks.&lt;/p&gt;

&lt;p&gt;Although using an LLM for compression may appear expensive, a &lt;strong&gt;locally deployed LLM&lt;/strong&gt; or a &lt;strong&gt;low-cost LLM&lt;/strong&gt; is typically used for this task.&lt;/p&gt;

&lt;p&gt;The purpose of this LLM is &lt;strong&gt;not&lt;/strong&gt; to generate the final response. Its responsibility is only to merge and compress the retrieved chunks while preserving their context.&lt;/p&gt;

&lt;p&gt;The compressed chunks are then sent to a more powerful or application-specific LLM to generate the final response.&lt;/p&gt;

&lt;p&gt;This creates a &lt;strong&gt;two-stage pipeline&lt;/strong&gt;, which is more token-efficient while still producing high-quality output.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Embedding-based Compression
&lt;/h2&gt;

&lt;p&gt;In embedding-based compression, the embeddings of the top retrieved chunks are compared with the embedding of the user query using &lt;strong&gt;cosine similarity&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The chunks that are most relevant to the user query are selected and used as the compressed context.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Keyword-based Compression
&lt;/h2&gt;

&lt;p&gt;Keyword-based compression uses techniques such as &lt;strong&gt;TF-IDF&lt;/strong&gt; or the &lt;strong&gt;BM25&lt;/strong&gt; algorithm.&lt;/p&gt;

&lt;p&gt;The keywords present in the user query are compared with the retrieved chunks.&lt;/p&gt;

&lt;p&gt;The chunks that have the highest keyword relevance are selected and used as the compressed context.&lt;/p&gt;




&lt;h2&gt;
  
  
  Combining Compression Techniques
&lt;/h2&gt;

&lt;p&gt;A single application is not limited to using only one compression technique.&lt;/p&gt;

&lt;p&gt;Depending on the application requirements, two or more context compression techniques can be combined to improve retrieval quality while reducing token usage.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>nlp</category>
    </item>
    <item>
      <title>RAG - Query Transformation and Expansion</title>
      <dc:creator>Ramya Perumal</dc:creator>
      <pubDate>Wed, 29 Jul 2026 17:27:33 +0000</pubDate>
      <link>https://dev.to/ramya_perumal/rag-query-transformation-and-expansion-n6i</link>
      <guid>https://dev.to/ramya_perumal/rag-query-transformation-and-expansion-n6i</guid>
      <description>&lt;h2&gt;
  
  
  Query Transformation
&lt;/h2&gt;

&lt;p&gt;When a user asks a blended or incomplete query, such as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"How do I deploy it?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;the LLM uses the background context it already has to transform the query into a more meaningful one.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"How do I deploy a FastAPI application?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By transforming the query into a more specific one, the system is able to retrieve more relevant documents from the vector database.&lt;/p&gt;

&lt;p&gt;For query transformation to work effectively, the LLM should have some background information about the conversation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Query Expansion
&lt;/h2&gt;

&lt;p&gt;When a user query is converted into an embedding, the point obtained in the vector database may not be close to the most relevant documents.&lt;/p&gt;

&lt;p&gt;By expanding the query into different variations, we can retrieve more relevant documents.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Original User Query&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"How do I deploy a FastAPI application?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Expanded Queries&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploy FastAPI using Docker&lt;/li&gt;
&lt;li&gt;FastAPI deployment guide&lt;/li&gt;
&lt;li&gt;FastAPI deployment on AWS&lt;/li&gt;
&lt;li&gt;FastAPI with Gunicorn&lt;/li&gt;
&lt;li&gt;FastAPI with Uvicorn&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are different variations of the original user query.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Does Query Expansion Work?
&lt;/h2&gt;

&lt;p&gt;For each variation of the user query, the system retrieves a set of relevant contexts from the vector database.&lt;/p&gt;

&lt;p&gt;During the augmentation phase, the retrieved contexts, along with the original user query, are sent to the LLM so that it can generate more accurate results.&lt;/p&gt;




&lt;h2&gt;
  
  
  Query Expansion and Query Transformation
&lt;/h2&gt;

&lt;p&gt;Both &lt;strong&gt;query expansion&lt;/strong&gt; and &lt;strong&gt;query transformation&lt;/strong&gt; are performed by the LLM.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Query Transformation&lt;/strong&gt; rewrites an incomplete or ambiguous query into a more meaningful query.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query Expansion&lt;/strong&gt; generates multiple variations of the user query to improve document retrieval.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Alternative Approach
&lt;/h2&gt;

&lt;p&gt;Instead of calling the LLM for query expansion, we can use a rule-based approach by storing related queries for a user query as a cluster in the vector database.&lt;/p&gt;

&lt;p&gt;When a user submits a query, the system retrieves the related queries from the cluster and uses them to improve document retrieval.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>nlp</category>
    </item>
    <item>
      <title>RAG - Semantic Caching</title>
      <dc:creator>Ramya Perumal</dc:creator>
      <pubDate>Sat, 18 Jul 2026 17:12:20 +0000</pubDate>
      <link>https://dev.to/ramya_perumal/rag-semantic-caching-2h67</link>
      <guid>https://dev.to/ramya_perumal/rag-semantic-caching-2h67</guid>
      <description>&lt;p&gt;When a user submits a query, the query is converted into an embedding and searched against the vector database to retrieve the relevant documents.&lt;/p&gt;

&lt;p&gt;But what happens if the user asks the same or a very similar query again?&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;semantic caching&lt;/strong&gt; comes into the picture.&lt;/p&gt;

&lt;p&gt;Instead of searching the vector database again, the system stores the previous search result in a cache. A cache is a temporary storage where frequently accessed or recently queried results are stored. When the user asks the same or a semantically similar query again, the system can retrieve the result directly from the cache instead of querying the vector database again.&lt;/p&gt;




&lt;h2&gt;
  
  
  Benefits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Saves retrieval time&lt;/li&gt;
&lt;li&gt;Reduces token consumption&lt;/li&gt;
&lt;li&gt;Reduces the number of calls to the vector database&lt;/li&gt;
&lt;li&gt;Reduces the number of calls to the LLM&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How Do We Store Results in the Cache?
&lt;/h2&gt;

&lt;p&gt;We can use &lt;strong&gt;Redis&lt;/strong&gt; or &lt;strong&gt;Valkey&lt;/strong&gt; for semantic caching.&lt;/p&gt;

&lt;p&gt;These are &lt;strong&gt;in-memory databases&lt;/strong&gt;, which means they store data in &lt;strong&gt;RAM&lt;/strong&gt; instead of disk. Since data is stored in memory, retrieval is much faster compared to traditional databases.&lt;/p&gt;

&lt;p&gt;Typically, we store:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User query&lt;/li&gt;
&lt;li&gt;Related answer&lt;/li&gt;
&lt;li&gt;Metadata&lt;/li&gt;
&lt;li&gt;Embeddings&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;Suppose a user asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"What is today's gold price?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The query and its corresponding answer are stored in Redis.&lt;/p&gt;

&lt;p&gt;Later, another user asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"Gold price today?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Although both queries have the same meaning, Redis cannot directly retrieve the previous answer because it expects the key to match exactly.&lt;/p&gt;

&lt;p&gt;This is one of the limitations of using Redis as a simple key-value store.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Can We Solve This?
&lt;/h2&gt;

&lt;p&gt;One approach is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Retrieve all the keys stored in Redis (for example, using &lt;code&gt;KEYS *&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Generate or retrieve the embedding for each stored query.&lt;/li&gt;
&lt;li&gt;Convert the current user query into an embedding.&lt;/li&gt;
&lt;li&gt;Compare the current query embedding with the stored query embeddings using &lt;strong&gt;cosine similarity&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;If the similarity score is above a predefined threshold, retrieve the corresponding answer from Redis.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This allows semantically similar queries to reuse cached results even when the text is different.&lt;/p&gt;




&lt;h2&gt;
  
  
  Ways to Implement Semantic Caching
&lt;/h2&gt;

&lt;p&gt;Semantic caching can be implemented in two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using frameworks such as &lt;strong&gt;LangChain&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Using in-memory databases such as &lt;strong&gt;Redis&lt;/strong&gt;, &lt;strong&gt;Valkey&lt;/strong&gt;, or other similar databases&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Cache Invalidation
&lt;/h2&gt;

&lt;p&gt;One of the most important aspects of semantic caching is &lt;strong&gt;cache invalidation&lt;/strong&gt;, which determines how long cached data should remain valid before it is automatically removed or refreshed.&lt;/p&gt;

&lt;p&gt;For example, suppose a user asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"What is today's gold price?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answer should only be valid for a limited period. If the application returns yesterday's gold price, the information becomes incorrect.&lt;/p&gt;

&lt;p&gt;There is no single solution for cache invalidation. The appropriate strategy depends on the application and the type of data being cached.&lt;/p&gt;

&lt;p&gt;Different scenarios need to be considered before deciding when cached data should expire.&lt;/p&gt;




&lt;h2&gt;
  
  
  When Should In-Memory Databases Be Used?
&lt;/h2&gt;

&lt;p&gt;In-memory databases are well suited for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Temporary queries&lt;/li&gt;
&lt;li&gt;Frequently asked questions&lt;/li&gt;
&lt;li&gt;Data that is accessed repeatedly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By understanding the meaning of the query, we can define guardrails to determine which queries should be cached and when the cache should be invalidated.&lt;/p&gt;

&lt;p&gt;The main objective is to optimize the RAG pipeline by reducing unnecessary calls to both the vector database and the LLM.&lt;/p&gt;

&lt;p&gt;Although it is not possible to eliminate duplicate requests completely, semantic caching can significantly reduce them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Important Consideration
&lt;/h2&gt;

&lt;p&gt;We should &lt;strong&gt;not&lt;/strong&gt; store every query in an in-memory database.&lt;/p&gt;

&lt;p&gt;Only queries that are valuable for caching should be stored because &lt;strong&gt;RAM has limited storage capacity&lt;/strong&gt;. Therefore, an effective caching strategy should carefully decide which queries are worth storing and for how long.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>beginners</category>
      <category>nlp</category>
    </item>
    <item>
      <title>RAG - Meta Filtering and Reranking</title>
      <dc:creator>Ramya Perumal</dc:creator>
      <pubDate>Sun, 12 Jul 2026 21:43:55 +0000</pubDate>
      <link>https://dev.to/ramya_perumal/rag-meta-filtering-and-reranking-22i1</link>
      <guid>https://dev.to/ramya_perumal/rag-meta-filtering-and-reranking-22i1</guid>
      <description>&lt;p&gt;Generally, when a user asks a query, the system searches for the relevant chunks stored in the vector database using cosine similarity. The better we can filter the data, the smaller the search space becomes, resulting in faster and more efficient retrieval.&lt;/p&gt;

&lt;p&gt;Suppose we have a book with 10 chapters. If we want to search for a particular topic, all the points in the vector database are compared with the user query, and only the closest points are retrieved. This process is called &lt;strong&gt;KNN (K-Nearest Neighbors)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Another algorithm is &lt;strong&gt;ANN (Approximate Nearest Neighbors)&lt;/strong&gt;. Instead of checking all the points in the vector database, ANN searches only within a smaller region based on the proximity of the data. As the name suggests, it does not always return the exact result, but it provides the most preferred or approximate results much faster.&lt;/p&gt;

&lt;p&gt;Is there any other method we can use to make the search more effective?&lt;/p&gt;

&lt;p&gt;Metadata Filtering&lt;/p&gt;

&lt;p&gt;Metadata means &lt;strong&gt;data about the data&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Metadata is stored along with each chunk. It can contain information related to the chunk, such as the chapter name, topic description, author, or any other relevant details.&lt;/p&gt;

&lt;p&gt;When the user query contains information related to the metadata (for example, a chapter name or topic), the system can directly filter the relevant chunks before performing vector similarity search. This technique is called &lt;strong&gt;metadata filtering&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Metadata filtering is supported by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pinecone&lt;/li&gt;
&lt;li&gt;ChromaDB&lt;/li&gt;
&lt;li&gt;Qdrant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;FAISS does not provide built-in support for metadata filtering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reranking
&lt;/h2&gt;

&lt;p&gt;Documents are first split into chunks, and each chunk is converted into vectors and stored in the vector database.&lt;/p&gt;

&lt;p&gt;When a user query arrives, it is converted into a vector and searched against the vector database to retrieve the closest chunks. However, we do not know whether the retrieved documents are actually the most relevant to the query. It is not always true that the closest vectors represent the most relevant documents.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Reranking Works
&lt;/h3&gt;

&lt;p&gt;The documents retrieved from the vector database are passed to a &lt;strong&gt;cross-encoder&lt;/strong&gt; along with the user query.&lt;/p&gt;

&lt;p&gt;The cross-encoder assigns a relevance score that indicates how closely each document matches the query. The documents are then displayed in ascending or descending order based on these scores.&lt;/p&gt;

&lt;p&gt;The results produced by the cross-encoder are called &lt;strong&gt;reranked results&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The retrieved documents remain the same as those returned by the vector database, but their order changes. Documents with higher relevance scores appear before those with lower scores.&lt;/p&gt;

&lt;p&gt;A cross-encoder is a neural ranking model. Instead of encoding the query and documents separately, it takes both the query and the document together as input to a transformer model and generates a relevance score for each document.&lt;/p&gt;

&lt;p&gt;There are transformer models specifically designed for reranking tasks. The encoder understands the meaning of both the query and the document and reranks the documents accordingly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Use Reranking?
&lt;/h3&gt;

&lt;p&gt;Reranking is an important step in the RAG pipeline.&lt;/p&gt;

&lt;p&gt;It is especially useful when working with documents that contain images or other multimodal content.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;

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

&lt;p&gt;&lt;strong&gt;"Show me the front view of the truck."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The vector database may retrieve multiple images related to trucks because they are semantically similar.&lt;/p&gt;

&lt;p&gt;The reranker analyzes both the query and the retrieved images (or their associated text descriptions) and assigns relevance scores.&lt;/p&gt;

&lt;p&gt;As a result, the image showing the &lt;strong&gt;front view of the truck&lt;/strong&gt; receives a higher score than the other truck images, making it appear first in the final results.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>rag</category>
      <category>nlp</category>
    </item>
  </channel>
</rss>
