<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Gen AI]]></title><description><![CDATA[Gen AI]]></description><link>https://understanding-gen-ai.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Mon, 19 Oct 2026 05:27:48 GMT</lastBuildDate><atom:link href="https://understanding-gen-ai.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Reciprocal Rank Fusion (RRF) in RAG: Complete Guide with Working Code]]></title><description><![CDATA[Before reading this article, I suggest you to go through the Query Translation in RAG: 5 Powerful Techniques to Improve Retrieval Accuracy article, In that article I have briefly discussed about the Reciprocal Rank Fusion (RRF) technique. While in th...]]></description><link>https://understanding-gen-ai.hashnode.dev/reciprocal-rank-fusion-rrf-in-rag-complete-guide-with-working-code</link><guid isPermaLink="true">https://understanding-gen-ai.hashnode.dev/reciprocal-rank-fusion-rrf-in-rag-complete-guide-with-working-code</guid><category><![CDATA[RAG ]]></category><category><![CDATA[Reciprocal Rank Fusion]]></category><category><![CDATA[ChaiCode]]></category><category><![CDATA[generative ai]]></category><category><![CDATA[genai]]></category><dc:creator><![CDATA[Ganesh Ghadage]]></dc:creator><pubDate>Fri, 08 Aug 2025 06:41:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1754635242452/44da4e50-aec5-4094-849d-92be3b171741.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Before reading this article, I suggest you to go through the <a target="_blank" href="https://understanding-gen-ai.hashnode.dev/query-translation-in-rag-5-powerful-techniques-to-improve-retrieval-accuracy"><strong>Query Translation in RAG: 5 Powerful Techniques to Improve Retrieval Accuracy</strong></a> article, In that article I have briefly discussed about the Reciprocal Rank Fusion (RRF) technique. While in this article we will go in depth of Reciprocal Rank Fusion and also we will write a code for it.</p>
<h2 id="heading-what-is-reciprocal-rank-fusion-rrf">What is Reciprocal Rank Fusion (RRF)?</h2>
<p>Reciprocal Rank Fusion is similar to Parallel Query Retrieval technique, Here also we generate the 4-5 queries based on user query and retrieve the documents based on them, But here instead of just filtering unique documents, we rank the documents based Ranking formula, and take the top n documents from them.</p>
<p>Ranking Formula:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754570570920/0c796d6d-040a-4aa2-8557-6fd44db5d36c.png?auto=compress,format&amp;format=webp" alt class="image--center mx-auto" /></p>
<p>Basically we rank the documents based on frequency and position of occurrence</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754632550207/30d9cac1-f461-4bcc-a957-811d5984526e.png" alt /></p>
<h2 id="heading-how-reciprocal-rank-fusion-works">How Reciprocal Rank Fusion works</h2>
<h3 id="heading-step-1-generating-multiple-queries">Step 1: Generating multiple queries</h3>
<p>When user asks as a query, we provide it to an small LLM ask it to generate multiple queries of it.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv

<span class="hljs-keyword">from</span> langchain_google_genai <span class="hljs-keyword">import</span> ChatGoogleGenerativeAI
<span class="hljs-keyword">from</span> langchain_core.prompts <span class="hljs-keyword">import</span> PromptTemplate
<span class="hljs-keyword">from</span> langchain_core.output_parsers <span class="hljs-keyword">import</span> BaseOutputParser
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> List, Dict

load_dotenv()

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LineListOutputParser</span>(<span class="hljs-params">BaseOutputParser[List[str]]</span>):</span>
  <span class="hljs-string">"""Output parser for a list of lines."""</span>

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">parse</span>(<span class="hljs-params">self, text: str</span>) -&gt; List[str]:</span>
    lines = text.strip().split(<span class="hljs-string">"\n"</span>)
    <span class="hljs-keyword">return</span> list(filter(<span class="hljs-literal">None</span>, lines)) 

output_parser = LineListOutputParser()

llm = ChatGoogleGenerativeAI(
  model=<span class="hljs-string">"gemini-2.5-flash"</span>,
  google_api_key=os.getenv(<span class="hljs-string">"GEMINI_API_KEY"</span>),
  temperature=<span class="hljs-number">0</span>,
  max_tokens=<span class="hljs-literal">None</span>,
  timeout=<span class="hljs-literal">None</span>,
  max_retries=<span class="hljs-number">2</span>,
)

QUERY_REWRITE_PROMPT = PromptTemplate(
  input_variables=[<span class="hljs-string">"question"</span>],
  template=<span class="hljs-string">"""You are an AI language model assistant. Your task is to generate five 
  different versions of the given user question to retrieve relevant documents from a vector 
  database. By generating multiple perspectives on the user question, your goal is to help
  the user overcome some of the limitations of the distance-based similarity search. 
  Provide these alternative questions separated by newlines.
  Original question: {question}"""</span>,
)

llm_chain = QUERY_REWRITE_PROMPT | llm | output_parser

<span class="hljs-comment"># ----- Step 1: Generate Multiple Queries -----</span>
user_query = <span class="hljs-string">"What is FS Module?"</span>
generated_queries = llm_chain.invoke(user_query)

print(<span class="hljs-string">"--------- Generated Queries -----------"</span>)
<span class="hljs-keyword">for</span> i, query <span class="hljs-keyword">in</span> enumerate(generated_queries, <span class="hljs-number">1</span>):
  print(<span class="hljs-string">f"<span class="hljs-subst">{i}</span>. <span class="hljs-subst">{query}</span>"</span>)
print(<span class="hljs-string">"------------------------"</span>)
</code></pre>
<h3 id="heading-step-2-parallely-fetching-relevant-chunks-from-vector-store">Step 2: Parallely fetching relevant chunks from vector store</h3>
<p>Once we generate multiple queries, we embed those query, and retrieve the relevant chunks from the vector store by performing similarity search. This action is done for all the generated query in parallel.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os

<span class="hljs-keyword">from</span> langchain_google_genai <span class="hljs-keyword">import</span> ChatGoogleGenerativeAI
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> List, Set
<span class="hljs-keyword">import</span> concurrent.futures
<span class="hljs-keyword">from</span> langchain_core.documents <span class="hljs-keyword">import</span> Document

<span class="hljs-keyword">from</span> utils.output_parser <span class="hljs-keyword">import</span> output_parser
<span class="hljs-keyword">from</span> config.vector_store <span class="hljs-keyword">import</span> get_vector_store
<span class="hljs-keyword">from</span> llm.prompt_templates <span class="hljs-keyword">import</span> QUERY_REWRITE_PROMPT
<span class="hljs-keyword">from</span> utils.rank_docs <span class="hljs-keyword">import</span> rank_documents

<span class="hljs-comment"># ----- setup --------</span>

qdrant = get_vector_store()

llm = ChatGoogleGenerativeAI(
  model=<span class="hljs-string">"gemini-2.5-flash"</span>,
  google_api_key=os.getenv(<span class="hljs-string">"GEMINI_API_KEY"</span>),
  temperature=<span class="hljs-number">0</span>,
  max_tokens=<span class="hljs-literal">None</span>,
  timeout=<span class="hljs-literal">None</span>,
  max_retries=<span class="hljs-number">2</span>,
)

llm_chain = QUERY_REWRITE_PROMPT | llm | output_parser

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">reciprocal_rank_fusion</span>(<span class="hljs-params">
  user_query: str, 
  llm_chain=llm_chain, 
  retriever=qdrant.as_retriever(<span class="hljs-params"></span>)
</span>) -&gt; List[Document]:</span>
  <span class="hljs-string">"""
  Generate multiple queries using llm_chain, fetch documents using retriever,
  and return deduplicated list of documents.

  Args:
    user_query (str): The input user query.
    llm_chain: A Runnable (PromptTemplate | LLM | OutputParser) for generating queries.
    retriever: A LangChain retriever (e.g., qdrant.as_retriever()).

  Returns:
    List[Document]: Deduplicated retrieved documents across all queries.
  """</span>
  <span class="hljs-comment"># Step 1: Generate multiple queries</span>
  generated_queries = llm_chain.invoke(user_query)

  <span class="hljs-comment"># Step 2: Fetch documents in parallel</span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fetch_docs</span>(<span class="hljs-params">query: str</span>):</span>
    <span class="hljs-keyword">return</span> retriever.invoke(query)

  all_docs: List[Document] = []
  <span class="hljs-keyword">with</span> concurrent.futures.ThreadPoolExecutor() <span class="hljs-keyword">as</span> executor:
    results = executor.map(fetch_docs, generated_queries)
    <span class="hljs-keyword">for</span> docs <span class="hljs-keyword">in</span> results:
      all_docs.extend(docs)

  <span class="hljs-comment"># Step 3: Rank docs    </span>
  sorted_docs = rank_documents(all_docs)

  print(<span class="hljs-string">"--------- sorted docs ------"</span>)
  print(<span class="hljs-string">f"\nTotal sorted documents: <span class="hljs-subst">{len(sorted_docs)}</span>"</span>)
  print(<span class="hljs-string">"==============================="</span>)
  <span class="hljs-keyword">for</span> i, doc <span class="hljs-keyword">in</span> enumerate(sorted_docs, <span class="hljs-number">1</span>):
    print(<span class="hljs-string">f"Doc <span class="hljs-subst">{i}</span> ID: <span class="hljs-subst">{doc}</span>"</span>)
  print(<span class="hljs-string">"==============================="</span>)

  <span class="hljs-keyword">return</span> sorted_docs
</code></pre>
<h3 id="heading-step-3-ranking-the-documents">Step 3: Ranking the documents</h3>
<p>From all the fetched documents, we rank the documents and tak the only top n documents to answer the user query.</p>
<p>To rank the documents we consider their occurrence and position for each query.</p>
<p>suppose we have three queries and those 3 queries fetched documents as per below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754633980393/f048b437-b2fa-4e19-9d31-ea0bde37c906.png" alt class="image--center mx-auto" /></p>
<p>While ranking we rank them as per below</p>
<ul>
<li><p>doc_id:3 is occuring 3 time so it should have 1st rank.</p>
</li>
<li><p>but doc_id:1 and doc_id:2 both are occuring twice, so while ranking them we consider their position of occurrence.</p>
</li>
<li><p>In Query 1, doc_id:1 is at 1st position and in Query 3, doc_id:1 is at 2nd position while, doc_id:2 is at 3rd position in Query 1 and at Query 2 it is at 1st position. So the doc_id:1 has more precedence than doc_id:2.</p>
</li>
<li><p>doc_id:4 has only one occurrence so it goes at last in ranking.</p>
</li>
</ul>
<p>finally ranking becomes like below</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754634579985/ec94a59a-8dcd-4101-9768-d599c74f88e5.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> List, Dict
<span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> defaultdict
<span class="hljs-keyword">from</span> langchain_core.documents <span class="hljs-keyword">import</span> Document

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">reciprocal_rank_fusion</span>(<span class="hljs-params">
  docs: List[Document],
  k: int = <span class="hljs-number">60</span>
</span>) -&gt; List[Document]:</span>
  <span class="hljs-string">"""
  Apply Reciprocal Rank Fusion (RRF) to combine multiple ranked lists.

  Args:
    docs List[Document]: list of documents.
    k (int): RRF constant. Defaults to 60.

  Returns:
    List[Document]: Final ranked list of documents with highest combined RRF scores.
  """</span>
  doc_scores = defaultdict(float)
  doc_store = {}

  <span class="hljs-keyword">for</span> rank, doc <span class="hljs-keyword">in</span> enumerate(docs):
    doc_id = doc.metadata.get(<span class="hljs-string">"id"</span>) <span class="hljs-keyword">or</span> hash(doc.page_content.strip())
    score = <span class="hljs-number">1</span> / (k + rank)
    doc_scores[doc_id] += score
    <span class="hljs-comment"># Store one version of the doc</span>
    <span class="hljs-keyword">if</span> doc_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> doc_store:
      doc_store[doc_id] = doc

  <span class="hljs-comment"># Sort by RRF score (descending)</span>
  ranked_doc_ids = sorted(doc_scores.items(), key=<span class="hljs-keyword">lambda</span> x: x[<span class="hljs-number">1</span>], reverse=<span class="hljs-literal">True</span>)

  <span class="hljs-keyword">for</span> doc_id, score <span class="hljs-keyword">in</span> ranked_doc_ids:
    print(<span class="hljs-string">f"doc_id: <span class="hljs-subst">{doc_id}</span>, score : <span class="hljs-subst">{score}</span> "</span>)

  <span class="hljs-comment"># Return the corresponding Document objects</span>
  <span class="hljs-keyword">return</span> [doc_store[doc_id] <span class="hljs-keyword">for</span> doc_id, _ <span class="hljs-keyword">in</span> ranked_doc_ids]
</code></pre>
<h3 id="heading-step-4-generating-output">Step 4: Generating output</h3>
<p>Using ranked documents and users original query, we generate the output, which will more accurate.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> openai <span class="hljs-keyword">import</span> OpenAI

<span class="hljs-keyword">from</span> retriever.retrival <span class="hljs-keyword">import</span> reciprocal_rank_fusion

api_key = os.getenv(<span class="hljs-string">"GEMINI_API_KEY"</span>)

client = OpenAI(
  api_key=api_key,
  base_url=<span class="hljs-string">"https://generativelanguage.googleapis.com/v1beta/openai/"</span>
)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">llm_chat</span>(<span class="hljs-params">query: str</span>):</span>
  unique_docs = reciprocal_rank_fusion(query)

  context = <span class="hljs-string">"\n\n"</span>
  <span class="hljs-keyword">for</span> doc <span class="hljs-keyword">in</span> unique_docs:
    <span class="hljs-comment"># print(doc)</span>
    context += <span class="hljs-string">f"Page Content: <span class="hljs-subst">{doc.page_content}</span>\nPage Number: <span class="hljs-subst">{doc.metadata[<span class="hljs-string">'page_label'</span>]}</span>\nFile Location: <span class="hljs-subst">{doc.metadata[<span class="hljs-string">'source'</span>]}</span> \n\n"</span>


  SYSTEM_PROMPT = <span class="hljs-string">f"""
    You are a helpful AI assistant who answers user query based on the available context retrieved from a PDF file along with page_contents and page number.

    You should only answer the user based on the following context and navigate the user to open the right page number to know more.
    answer should be in details.
    Context:
    <span class="hljs-subst">{context}</span>
  """</span>

  chat_completion = client.chat.completions.create(
    model=<span class="hljs-string">"gemini-2.0-flash"</span>,
    messages=[
      {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: SYSTEM_PROMPT},
      {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: query}
    ],
  )

  <span class="hljs-keyword">return</span> chat_completion.choices[<span class="hljs-number">0</span>].message.content
</code></pre>
<h2 id="heading-benefits-of-reciprocal-rank-fusion">Benefits of Reciprocal Rank Fusion</h2>
<p>Even though if, multiple queries fetch the docs that are not entirely relevant to user query, by ranking we reject those documents and take only closely relevant documents to answer the user query.</p>
<h2 id="heading-source-code">Source Code</h2>
<h3 id="heading-retrivalpyhttpretrivalpy"><a target="_blank" href="http://retrival.py/"><strong>retrival.py</strong></a></h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os

<span class="hljs-keyword">from</span> langchain_google_genai <span class="hljs-keyword">import</span> ChatGoogleGenerativeAI
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> List, Set
<span class="hljs-keyword">import</span> concurrent.futures
<span class="hljs-keyword">from</span> langchain_core.documents <span class="hljs-keyword">import</span> Document

<span class="hljs-keyword">from</span> utils.output_parser <span class="hljs-keyword">import</span> output_parser
<span class="hljs-keyword">from</span> config.vector_store <span class="hljs-keyword">import</span> get_vector_store
<span class="hljs-keyword">from</span> llm.prompt_templates <span class="hljs-keyword">import</span> QUERY_REWRITE_PROMPT
<span class="hljs-keyword">from</span> utils.rank_docs <span class="hljs-keyword">import</span> rank_documents

<span class="hljs-comment"># ----- setup --------</span>

qdrant = get_vector_store()

llm = ChatGoogleGenerativeAI(
  model=<span class="hljs-string">"gemini-2.5-flash"</span>,
  google_api_key=os.getenv(<span class="hljs-string">"GEMINI_API_KEY"</span>),
  temperature=<span class="hljs-number">0</span>,
  max_tokens=<span class="hljs-literal">None</span>,
  timeout=<span class="hljs-literal">None</span>,
  max_retries=<span class="hljs-number">2</span>,
)

llm_chain = QUERY_REWRITE_PROMPT | llm | output_parser

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">reciprocal_rank_fusion</span>(<span class="hljs-params">
  user_query: str, 
  llm_chain=llm_chain, 
  retriever=qdrant.as_retriever(<span class="hljs-params"></span>)
</span>) -&gt; List[Document]:</span>
  <span class="hljs-string">"""
  Generate multiple queries using llm_chain, fetch documents using retriever,
  and return deduplicated list of documents.

  Args:
    user_query (str): The input user query.
    llm_chain: A Runnable (PromptTemplate | LLM | OutputParser) for generating queries.
    retriever: A LangChain retriever (e.g., qdrant.as_retriever()).

  Returns:
    List[Document]: Deduplicated retrieved documents across all queries.
  """</span>
  <span class="hljs-comment"># Step 1: Generate multiple queries</span>
  generated_queries = llm_chain.invoke(user_query)

  <span class="hljs-comment"># Step 2: Fetch documents in parallel</span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fetch_docs</span>(<span class="hljs-params">query: str</span>):</span>
    <span class="hljs-keyword">return</span> retriever.invoke(query)

  all_docs: List[Document] = []
  <span class="hljs-keyword">with</span> concurrent.futures.ThreadPoolExecutor() <span class="hljs-keyword">as</span> executor:
    results = executor.map(fetch_docs, generated_queries)
    <span class="hljs-keyword">for</span> docs <span class="hljs-keyword">in</span> results:
      all_docs.extend(docs)

  <span class="hljs-comment"># Step 3: Rank docs    </span>
  sorted_docs = rank_documents(all_docs)

  <span class="hljs-keyword">return</span> sorted_docs
</code></pre>
<h3 id="heading-chatpyhttpchatpy"><a target="_blank" href="http://chat.py/"><strong>chat.py</strong></a></h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> openai <span class="hljs-keyword">import</span> OpenAI

<span class="hljs-keyword">from</span> retriever.retrival <span class="hljs-keyword">import</span> reciprocal_rank_fusion

api_key = os.getenv(<span class="hljs-string">"GEMINI_API_KEY"</span>)

client = OpenAI(
  api_key=api_key,
  base_url=<span class="hljs-string">"https://generativelanguage.googleapis.com/v1beta/openai/"</span>
)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">llm_chat</span>(<span class="hljs-params">query: str</span>):</span>
  search_results =  reciprocal_rank_fusion(query)

  context = <span class="hljs-string">"\n\n"</span>
  <span class="hljs-keyword">for</span> _ , doc <span class="hljs-keyword">in</span> enumerate(search_results, <span class="hljs-number">1</span>):
    context += <span class="hljs-string">f"Page Content: <span class="hljs-subst">{doc.page_content}</span>\nPage Number: <span class="hljs-subst">{doc.metadata[<span class="hljs-string">'page_label'</span>]}</span>\nFile Location: <span class="hljs-subst">{doc.metadata[<span class="hljs-string">'source'</span>]}</span> \n\n"</span>


  SYSTEM_PROMPT = <span class="hljs-string">f"""
    You are a helpful AI assistant who answers user query based on the available context retrieved from a PDF file along with page_contents and page number.

    You should only answer the user based on the following context and navigate the user to open the right page number to know more.
    answer should be in details.
    Context:
    <span class="hljs-subst">{context}</span>
  """</span>

  chat_completion = client.chat.completions.create(
    model=<span class="hljs-string">"gemini-2.0-flash"</span>,
    messages=[
      {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: SYSTEM_PROMPT},
      {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: query}
    ],
  )

  <span class="hljs-keyword">return</span> chat_completion.choices[<span class="hljs-number">0</span>].message.content
</code></pre>
<h3 id="heading-mainpyhttpmainpy"><a target="_blank" href="http://main.py/"><strong>main.py</strong></a></h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv

<span class="hljs-keyword">from</span> generator.chat <span class="hljs-keyword">import</span> llm_chat

load_dotenv()

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>():</span>
  query = <span class="hljs-string">"what is fs module?"</span>
  result = llm_chat(query=query)

  print(result)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
  main()
</code></pre>
<p>Full source code available at: <a target="_blank" href="https://github.com/Ganesh-Ghadage/Gen-AI-Cohort/tree/main/Day-6-ARAG-Query-Translation/2_Reciprocate_Rank_Fusion"><strong>GitHub</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[Parallel Query Retrieval in RAG: In-Depth Guide with Code Examples]]></title><description><![CDATA[In the last Query Translation in RAG: 5 Powerful Techniques to Improve Retrieval Accuracy article we briefly discussed about the Parallel Query Retrieval technique. In this article we will go in depth of parallel query retrieval. We will write a code...]]></description><link>https://understanding-gen-ai.hashnode.dev/parallel-query-retrieval-in-rag-in-depth-guide-with-code-examples</link><guid isPermaLink="true">https://understanding-gen-ai.hashnode.dev/parallel-query-retrieval-in-rag-in-depth-guide-with-code-examples</guid><category><![CDATA[generative ai]]></category><category><![CDATA[RAG ]]></category><category><![CDATA[openai]]></category><category><![CDATA[ChaiCode]]></category><category><![CDATA[AI]]></category><category><![CDATA[ParallelQueryRetrieval]]></category><dc:creator><![CDATA[Ganesh Ghadage]]></dc:creator><pubDate>Fri, 08 Aug 2025 04:18:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1754626508890/46e6b1b6-6dfd-4368-99b7-7dad9b9dc502.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the last <a target="_blank" href="https://understanding-gen-ai.hashnode.dev/query-translation-in-rag-5-powerful-techniques-to-improve-retrieval-accuracy">Query Translation in RAG: 5 Powerful Techniques to Improve Retrieval Accuracy</a> article we briefly discussed about the Parallel Query Retrieval technique. In this article we will go in depth of parallel query retrieval. We will write a code for it.</p>
<p>In the Query Translation article we understood that we can not trust the user query. User might ask some ambigues query. If the query is ambiguous generated output is also ambiguous.</p>
<h2 id="heading-what-is-parallel-query-fan-out">What is Parallel Query (Fan-Out)?</h2>
<p>Parallel Query Retrieval also known as Multi Query is an technique where we create multiple queries based on the users query. Each query will cover the different aspect of the user requirements that user may even know that he wanted.</p>
<p>Example:</p>
<p>If user wants know about <code>fs</code> module in node.js and he asks a question:</p>
<blockquote>
<p>what is fs module?</p>
</blockquote>
<p>but suppose our data set has some chunks that says file system module and that is very important to answer user query, that won’t be get retrieved as fs and file system has different vector embeddings and won’t get searched during similarity search. In this case the generated answer won’t be an accurate.</p>
<p>So what we do it to ask LLM model to generate 4-5 different queries based on user query, like below</p>
<blockquote>
<ol>
<li><p>What is the File System (FS) module?</p>
</li>
<li><p>What is the purpose of the FS module?</p>
</li>
<li><p>Describe the Node.js FS module.</p>
</li>
<li><p>How does the FS module work?</p>
</li>
<li><p>Explain the concept of the FS module.</p>
</li>
</ol>
</blockquote>
<p>generated queries will contain more fancy words, and will fetch more chunks during similarity search</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754623889811/bbd8ce49-3adb-4a10-9b42-134fc42721ff.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-how-parallel-query-retrieval-works">How Parallel Query Retrieval works</h2>
<h3 id="heading-step-1-generating-multiple-queries">Step 1: Generating multiple queries</h3>
<p>When user asks as a query, we provide it to an small LLM ask it to generate multiple queries of it.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv

<span class="hljs-keyword">from</span> langchain_google_genai <span class="hljs-keyword">import</span> ChatGoogleGenerativeAI
<span class="hljs-keyword">from</span> langchain_core.prompts <span class="hljs-keyword">import</span> PromptTemplate
<span class="hljs-keyword">from</span> langchain_core.output_parsers <span class="hljs-keyword">import</span> BaseOutputParser
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> List, Dict

load_dotenv()

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LineListOutputParser</span>(<span class="hljs-params">BaseOutputParser[List[str]]</span>):</span>
  <span class="hljs-string">"""Output parser for a list of lines."""</span>

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">parse</span>(<span class="hljs-params">self, text: str</span>) -&gt; List[str]:</span>
    lines = text.strip().split(<span class="hljs-string">"\n"</span>)
    <span class="hljs-keyword">return</span> list(filter(<span class="hljs-literal">None</span>, lines)) 

output_parser = LineListOutputParser()

llm = ChatGoogleGenerativeAI(
  model=<span class="hljs-string">"gemini-2.5-flash"</span>,
  google_api_key=os.getenv(<span class="hljs-string">"GEMINI_API_KEY"</span>),
  temperature=<span class="hljs-number">0</span>,
  max_tokens=<span class="hljs-literal">None</span>,
  timeout=<span class="hljs-literal">None</span>,
  max_retries=<span class="hljs-number">2</span>,
)

QUERY_REWRITE_PROMPT = PromptTemplate(
  input_variables=[<span class="hljs-string">"question"</span>],
  template=<span class="hljs-string">"""You are an AI language model assistant. Your task is to generate five 
  different versions of the given user question to retrieve relevant documents from a vector 
  database. By generating multiple perspectives on the user question, your goal is to help
  the user overcome some of the limitations of the distance-based similarity search. 
  Provide these alternative questions separated by newlines.
  Original question: {question}"""</span>,
)

llm_chain = QUERY_REWRITE_PROMPT | llm | output_parser

<span class="hljs-comment"># ----- Step 1: Generate Multiple Queries -----</span>
user_query = <span class="hljs-string">"What is FS Module?"</span>
generated_queries = llm_chain.invoke(user_query)

print(<span class="hljs-string">"--------- Generated Queries -----------"</span>)
<span class="hljs-keyword">for</span> i, query <span class="hljs-keyword">in</span> enumerate(generated_queries, <span class="hljs-number">1</span>):
  print(<span class="hljs-string">f"<span class="hljs-subst">{i}</span>. <span class="hljs-subst">{query}</span>"</span>)
print(<span class="hljs-string">"------------------------"</span>)
</code></pre>
<h3 id="heading-step-2-parallely-fetching-relevant-chunks-from-vector-store">Step 2: Parallely fetching relevant chunks from vector store</h3>
<p>Once we generate multiple queries, we embed those query, and retrieve the relevant chunks from the vector store by performing similarity search. This action is done for all the generated query in parallel.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv
<span class="hljs-keyword">import</span> concurrent.futures

<span class="hljs-keyword">from</span> langchain_qdrant <span class="hljs-keyword">import</span> QdrantVectorStore
<span class="hljs-keyword">from</span> qdrant_client <span class="hljs-keyword">import</span> QdrantClient
<span class="hljs-keyword">from</span> qdrant_client.models <span class="hljs-keyword">import</span> Distance, VectorParams
<span class="hljs-keyword">from</span> langchain_google_genai <span class="hljs-keyword">import</span> GoogleGenerativeAIEmbeddings

load_dotenv()

embeddings = GoogleGenerativeAIEmbeddings(
  model=<span class="hljs-string">"models/gemini-embedding-001"</span>,
  google_api_key=os.getenv(<span class="hljs-string">"GEMINI_API_KEY"</span>)
)

COLLECTION_NAME = <span class="hljs-string">"nodejs_document"</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_qdrant_client</span>():</span>
  client = QdrantClient(url=<span class="hljs-string">"http://localhost:6333"</span>)

  <span class="hljs-keyword">if</span> COLLECTION_NAME <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> [c.name <span class="hljs-keyword">for</span> c <span class="hljs-keyword">in</span> client.get_collections().collections]:
    client.create_collection(
      collection_name=COLLECTION_NAME,
      vectors_config=VectorParams(size=<span class="hljs-number">3072</span>, distance=Distance.COSINE),
    )

  <span class="hljs-keyword">return</span> client

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_vector_store</span>():</span>
    client = get_qdrant_client()
    <span class="hljs-keyword">return</span> QdrantVectorStore(
        client=client,
        collection_name=COLLECTION_NAME,
        embedding=embeddings,
    )

qdrant = get_vector_store()

<span class="hljs-comment"># ----- Fetch Documents in Parallel -----</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fetch_docs</span>(<span class="hljs-params">query</span>):</span>
  docs = qdrant.as_retriever().invoke(query)
  <span class="hljs-keyword">return</span> (query, docs)

query_to_docs: Dict[str, List] = {}

<span class="hljs-comment"># Use ThreadPoolExecutor to run in parallel</span>
<span class="hljs-keyword">with</span> concurrent.futures.ThreadPoolExecutor() <span class="hljs-keyword">as</span> executor:
  results = list(executor.map(fetch_docs, generated_queries))

<span class="hljs-comment"># Map results</span>
<span class="hljs-keyword">for</span> query, docs <span class="hljs-keyword">in</span> results:
  query_to_docs[query] = docs

<span class="hljs-keyword">for</span> query, docs <span class="hljs-keyword">in</span> query_to_docs.items():
  print(<span class="hljs-string">f"\n===== Results for Query: \"<span class="hljs-subst">{query}</span>\" ====="</span>)
  <span class="hljs-keyword">for</span> i, doc <span class="hljs-keyword">in</span> enumerate(docs, <span class="hljs-number">1</span>):
    print(<span class="hljs-string">f"Doc <span class="hljs-subst">{i}</span> ID: <span class="hljs-subst">{doc.metadata[<span class="hljs-string">"_id"</span>]}</span>"</span>)
  print(<span class="hljs-string">"==============================="</span>)
</code></pre>
<h3 id="heading-step-3-filter-the-unique-documents">Step 3: Filter the unique documents</h3>
<p>From all the total documents fetched by all queries, we filter the unique documents from them, to avoid the deduplication.</p>
<pre><code class="lang-python"><span class="hljs-comment"># ----- Deduplicate Documents -----</span>
<span class="hljs-comment"># Strategy: use doc.metadata['id'] if available, else page_content hash</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_doc_id</span>(<span class="hljs-params">doc</span>):</span>
  <span class="hljs-keyword">return</span> doc.metadata.get(<span class="hljs-string">"id"</span>) <span class="hljs-keyword">or</span> hash(doc.page_content.strip())

seen = {}
<span class="hljs-keyword">for</span> docs <span class="hljs-keyword">in</span> query_to_docs.values():
  <span class="hljs-keyword">for</span> doc <span class="hljs-keyword">in</span> docs:
    doc_id = get_doc_id(doc)
    <span class="hljs-keyword">if</span> doc_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> seen:
      seen[doc_id] = doc

unique_docs = list(seen.values())

print(<span class="hljs-string">f"\nTotal Unique documents: <span class="hljs-subst">{len(unique_docs)}</span>"</span>)
print(<span class="hljs-string">"==============================="</span>)
<span class="hljs-keyword">for</span> i, doc <span class="hljs-keyword">in</span> enumerate(unique_docs, <span class="hljs-number">1</span>):
  print(<span class="hljs-string">f"Doc <span class="hljs-subst">{i}</span> ID: <span class="hljs-subst">{doc.metadata[<span class="hljs-string">"_id"</span>]}</span>"</span>)
print(<span class="hljs-string">"==============================="</span>)
</code></pre>
<h3 id="heading-step-4-generating-output">Step 4: Generating output</h3>
<p>Using retrieved unique documents and users original query, we generate the output, which will more accurate.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> openai <span class="hljs-keyword">import</span> OpenAI

<span class="hljs-keyword">from</span> retriever.retrival <span class="hljs-keyword">import</span> parallel_query_retriver

api_key = os.getenv(<span class="hljs-string">"GEMINI_API_KEY"</span>)

client = OpenAI(
  api_key=api_key,
  base_url=<span class="hljs-string">"https://generativelanguage.googleapis.com/v1beta/openai/"</span>
)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">llm_chat</span>(<span class="hljs-params">query: str</span>):</span>
  unique_docs = parallel_query_retriver(query)

  context = <span class="hljs-string">"\n\n"</span>
  <span class="hljs-keyword">for</span> doc <span class="hljs-keyword">in</span> unique_docs:
    <span class="hljs-comment"># print(doc)</span>
    context += <span class="hljs-string">f"Page Content: <span class="hljs-subst">{doc.page_content}</span>\nPage Number: <span class="hljs-subst">{doc.metadata[<span class="hljs-string">'page_label'</span>]}</span>\nFile Location: <span class="hljs-subst">{doc.metadata[<span class="hljs-string">'source'</span>]}</span> \n\n"</span>


  SYSTEM_PROMPT = <span class="hljs-string">f"""
    You are a helpful AI assistant who answers user query based on the available context retrieved from a PDF file along with page_contents and page number.

    You should only answer the user based on the following context and navigate the user to open the right page number to know more.
    answer should be in details.
    Context:
    <span class="hljs-subst">{context}</span>
  """</span>

  chat_completion = client.chat.completions.create(
    model=<span class="hljs-string">"gemini-2.0-flash"</span>,
    messages=[
      {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: SYSTEM_PROMPT},
      {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: query}
    ],
  )

  <span class="hljs-keyword">return</span> chat_completion.choices[<span class="hljs-number">0</span>].message.content
</code></pre>
<h2 id="heading-benefits-of-parallel-query">Benefits of Parallel Query</h2>
<p>Even though Parallel Query adds a overhead and extra LLM call, it’s improved performance and accuracy negats the extra cost. Parallel Query retrieval system can handle ambiguous user query, any typos or any mistakes in user query will not affect the final output.</p>
<h2 id="heading-source-code">Source Code</h2>
<h3 id="heading-retrivalpy">retrival.py</h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv

<span class="hljs-keyword">from</span> langchain_qdrant <span class="hljs-keyword">import</span> QdrantVectorStore
<span class="hljs-keyword">from</span> langchain_google_genai <span class="hljs-keyword">import</span> ChatGoogleGenerativeAI
<span class="hljs-keyword">from</span> langchain_core.prompts <span class="hljs-keyword">import</span> PromptTemplate
<span class="hljs-keyword">from</span> langchain.retrievers.multi_query <span class="hljs-keyword">import</span> MultiQueryRetriever
<span class="hljs-keyword">from</span> langchain_core.output_parsers <span class="hljs-keyword">import</span> BaseOutputParser
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> List, Dict, Set
<span class="hljs-keyword">import</span> concurrent.futures
<span class="hljs-keyword">from</span> langchain_core.documents <span class="hljs-keyword">import</span> Document

<span class="hljs-keyword">from</span> utils.output_parser <span class="hljs-keyword">import</span> output_parser
<span class="hljs-keyword">from</span> config.vector_store <span class="hljs-keyword">import</span> get_vector_store
<span class="hljs-keyword">from</span> llm.prompt_templates <span class="hljs-keyword">import</span> QUERY_REWRITE_PROMPT

<span class="hljs-comment"># ----- setup --------</span>

qdrant = get_vector_store()

llm = ChatGoogleGenerativeAI(
  model=<span class="hljs-string">"gemini-2.5-flash"</span>,
  google_api_key=os.getenv(<span class="hljs-string">"GEMINI_API_KEY"</span>),
  temperature=<span class="hljs-number">0</span>,
  max_tokens=<span class="hljs-literal">None</span>,
  timeout=<span class="hljs-literal">None</span>,
  max_retries=<span class="hljs-number">2</span>,
)

llm_chain = QUERY_REWRITE_PROMPT | llm | output_parser

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">parallel_query_retriver</span>(<span class="hljs-params">
  user_query: str, 
  llm_chain=llm_chain, 
  retriever=qdrant.as_retriever(<span class="hljs-params"></span>)
</span>) -&gt; List[Document]:</span>
  <span class="hljs-string">"""
  Generate multiple queries using llm_chain, fetch documents using retriever,
  and return deduplicated list of documents.

  Args:
    user_query (str): The input user query.
    llm_chain: A Runnable (PromptTemplate | LLM | OutputParser) for generating queries.
    retriever: A LangChain retriever (e.g., qdrant.as_retriever()).

  Returns:
    List[Document]: Deduplicated retrieved documents across all queries.
  """</span>
  <span class="hljs-comment"># Step 1: Generate multiple queries</span>
  generated_queries = llm_chain.invoke(user_query)

  <span class="hljs-comment"># Step 2: Fetch documents in parallel</span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fetch_docs</span>(<span class="hljs-params">query: str</span>):</span>
    <span class="hljs-keyword">return</span> retriever.invoke(query)

  all_docs: List[Document] = []
  <span class="hljs-keyword">with</span> concurrent.futures.ThreadPoolExecutor() <span class="hljs-keyword">as</span> executor:
    results = executor.map(fetch_docs, generated_queries)
    <span class="hljs-keyword">for</span> docs <span class="hljs-keyword">in</span> results:
      all_docs.extend(docs)

  <span class="hljs-comment"># Step 3: Deduplicate docs</span>
  seen: Set[str] = set()
  unique_docs: List[Document] = []

  <span class="hljs-keyword">for</span> doc <span class="hljs-keyword">in</span> all_docs:
    doc_id = doc.metadata.get(<span class="hljs-string">"id"</span>) <span class="hljs-keyword">or</span> hash(doc.page_content.strip())
    <span class="hljs-keyword">if</span> doc_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> seen:
      seen.add(doc_id)
      unique_docs.append(doc)

  <span class="hljs-keyword">return</span> unique_docs
</code></pre>
<h3 id="heading-chatpy">chat.py</h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> openai <span class="hljs-keyword">import</span> OpenAI

<span class="hljs-keyword">from</span> retriever.retrival <span class="hljs-keyword">import</span> parallel_query_retriver

api_key = os.getenv(<span class="hljs-string">"GEMINI_API_KEY"</span>)

client = OpenAI(
  api_key=api_key,
  base_url=<span class="hljs-string">"https://generativelanguage.googleapis.com/v1beta/openai/"</span>
)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">llm_chat</span>(<span class="hljs-params">query: str</span>):</span>
  search_results =  parallel_query_retriver(query)

  context = <span class="hljs-string">"\n\n"</span>
  <span class="hljs-keyword">for</span> doc <span class="hljs-keyword">in</span> search_results:
    <span class="hljs-comment"># print(doc)</span>
    context += <span class="hljs-string">f"Page Content: <span class="hljs-subst">{doc.page_content}</span>\nPage Number: <span class="hljs-subst">{doc.metadata[<span class="hljs-string">'page_label'</span>]}</span>\nFile Location: <span class="hljs-subst">{doc.metadata[<span class="hljs-string">'source'</span>]}</span> \n\n"</span>


  SYSTEM_PROMPT = <span class="hljs-string">f"""
    You are a helpful AI assistant who answers user query based on the available context retrieved from a PDF file along with page_contents and page number.

    You should only answer the user based on the following context and navigate the user to open the right page number to know more.
    answer should be in details.
    Context:
    <span class="hljs-subst">{context}</span>
  """</span>

  chat_completion = client.chat.completions.create(
    model=<span class="hljs-string">"gemini-2.0-flash"</span>,
    messages=[
      {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: SYSTEM_PROMPT},
      {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: query}
    ],
  )

  <span class="hljs-keyword">return</span> chat_completion.choices[<span class="hljs-number">0</span>].message.content
</code></pre>
<h3 id="heading-mainpy">main.py</h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv

<span class="hljs-keyword">from</span> generator.chat <span class="hljs-keyword">import</span> llm_chat

load_dotenv()

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>():</span>
  query = <span class="hljs-string">"what is fs module?"</span>
  result = llm_chat(query=query)

  print(result)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
  main()
</code></pre>
<p>Full source code available at: <a target="_blank" href="https://github.com/Ganesh-Ghadage/Gen-AI-Cohort/tree/main/Day-6-ARAG-Query-Translation/1_Parallel_Query_Retrival">GitHub</a></p>
]]></content:encoded></item><item><title><![CDATA[Query Translation in RAG: 5 Powerful Techniques to Improve Retrieval Accuracy]]></title><description><![CDATA[In the last article RAG: Retrieval Augmented Generation Explained we understood about the RAG, how it work and we also build an basic pdf chatbot RAG system. In this article we will go in depth of RAG, we will study about the Advanced RAG system, dif...]]></description><link>https://understanding-gen-ai.hashnode.dev/query-translation-in-rag-5-powerful-techniques-to-improve-retrieval-accuracy</link><guid isPermaLink="true">https://understanding-gen-ai.hashnode.dev/query-translation-in-rag-5-powerful-techniques-to-improve-retrieval-accuracy</guid><category><![CDATA[RAG ]]></category><category><![CDATA[ChaiCode]]></category><category><![CDATA[AI]]></category><category><![CDATA[generative ai]]></category><category><![CDATA[chatgpt]]></category><category><![CDATA[Chaiaurcode]]></category><dc:creator><![CDATA[Ganesh Ghadage]]></dc:creator><pubDate>Thu, 07 Aug 2025 15:58:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1754582295081/bffbd381-86b8-4d86-8361-ffc1a7471ab4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the last article <a target="_blank" href="https://understanding-gen-ai.hashnode.dev/rag-retrieval-augmented-generation-explained">RAG: Retrieval Augmented Generation Explained</a> we understood about the RAG, how it work and we also build an basic pdf chatbot RAG system. In this article we will go in depth of RAG, we will study about the Advanced RAG system, different strategies involved in it. If you haven’t read the previous article, I will recommend you to read it before reading this one.</p>
<blockquote>
<p><a target="_blank" href="https://understanding-gen-ai.hashnode.dev/rag-retrieval-augmented-generation-explained">https://understanding-gen-ai.hashnode.dev/rag-retrieval-augmented-generation-explained</a></p>
</blockquote>
<p>To solve a business use case a simple RAG won’t do anything, we need something optimized, accurate and reliable RAG system. There are various strategies to optimise the RAG and the most common is <strong>Query Translation.</strong></p>
<p>Let’s understand that, user can ask anything to AI, user may not precise about what he wants and may ask irrelevant or half baked query, which might generate an unexpected output, and hence decrease the user experience. In this case user asked an wrong query and will blame the system that it is not generating the correct response. So we can not rely on the user query. Also we can not guide all the users on how they can ask the more accurate query.</p>
<p>Example:</p>
<p>If our system generates correct output for below query</p>
<blockquote>
<p>“What is Amir Khan’s character name in 3 idiots?”</p>
</blockquote>
<p>but suppose user asks something like</p>
<blockquote>
<p>“Who is Rancho?”</p>
</blockquote>
<p>Our system might not generate the correct response as it becomes generic question.</p>
<p>So, the solution here is <strong>Query Translation.</strong> as the name says we translate the users query in a such a way that it is clearly understandable to LLM so that it can generate accurate response.</p>
<p>There are different techniques in Query Translation as per below:</p>
<ol>
<li><p>Parallel Query Retrieval (Fan-Out)</p>
</li>
<li><p>Reciprocal Rank Fusion</p>
</li>
<li><p>Query Decomposition (Chain of Thoughts)</p>
</li>
<li><p>Step-Back Prompting</p>
</li>
<li><p>HyDE (Hypothetical Document Embeddings)</p>
</li>
</ol>
<p>Let’s briefly understand each technique one by one.</p>
<h2 id="heading-parallel-query-retrieval-fan-out">Parallel Query Retrieval (Fan-Out)</h2>
<p>In this technique we take user query, ask one LLM model to generate 4-5 different queries based on the user query, then we use this 5 queries to retrieve the documents from vector store. As these 5 queries will bring the more context will also retrieve the more chunks from vector store, Then we filter the unique documents from all the retrieved documents. Using this filtered documents and original user query we ask LLM to answer the user query which will generate more accurate response, as it will have more context.</p>
<p>This is also known as multi-query</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754580749289/6525cdb7-31e6-449d-a69b-c1413a8ed661.png" alt class="image--center mx-auto" /></p>
<blockquote>
<p>Read More: <a target="_blank" href="https://understanding-gen-ai.hashnode.dev/parallel-query-retrieval-in-rag-in-depth-guide-with-code-examples">Parallel Query Retrieval in RAG: In-Depth Guide with Code Examples</a></p>
</blockquote>
<h2 id="heading-reciprocal-rank-fusion">Reciprocal Rank Fusion</h2>
<p>This technique is similar to Parallel Query Retrieval. Here also we generate multiple queries based on user query, retrieve documents based on those multiple queries. But here instead of just filtering unique documents we rank them using ranking formula and take the top n documents to feed the LLM to generate the response.</p>
<p>Ranking Formula:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754570570920/0c796d6d-040a-4aa2-8557-6fd44db5d36c.png" alt class="image--center mx-auto" /></p>
<p>Basically we rank the documents based on frequency and position of occurrence</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754580763317/5c0e2350-88b9-40ab-8755-c80e5428b925.png" alt class="image--center mx-auto" /></p>
<blockquote>
<p>Read More: <a target="_blank" href="https://understanding-gen-ai.hashnode.dev/reciprocal-rank-fusion-rrf-in-rag-complete-guide-with-working-code">Reciprocal Rank Fusion (RRF) in RAG: Complete Guide with Working Code</a></p>
</blockquote>
<h2 id="heading-query-decomposition-chain-of-thoughts">Query Decomposition (Chain of Thoughts)</h2>
<p>In this techniques, we generate the sub-query based on users query, we retrieve the documents and generate it’s answer is isolation. In same we we generate multiple sub-query and it’s answers, and lastly using this Q&amp;A pairs we answer the users original query.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754580791117/25640ba0-3cfe-47dc-b16a-14f6a25cbf35.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-step-back-prompting">Step Back Prompting</h2>
<p>Its similar to basic RAG but, In this technique we ask LLM to generate broader view question of users query. As broader view will fetch the more context about the query.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754580801090/0fb50a20-effa-431f-9ebd-a0bb3fb0498a.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-hyde-hypothetical-document-embeddings">HyDE (Hypothetical Document Embeddings)</h2>
<p>In this technique we ask LLM model to generate the hypothetical document which will cover all the aspects to answer the user query. Then using this generated document we retrieve the documents from our vector store, This will fetch all the relevant documents from the store as it covers all the aspects. Answer generated based on those retrieved documents will be more precise and accurate.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754581313330/ff40328d-4b52-42c0-b07c-7880fa62b7c0.png" alt class="image--center mx-auto" /></p>
<p>In production application there are many steps involved in RAG system and Query Translation one of them. There is no right way to pick up the best technique, it totally depends on the use case. Sometime you might need to combine multiple techniques together to solve your problem.</p>
<h2 id="heading-summary">Summary</h2>
<blockquote>
<p>In this article, we delve into advanced strategies for optimizing Retrieval Augmented Generation (RAG) systems, focusing on improving accuracy and reliability. While a simple RAG setup may not suffice for complex business use cases, techniques like Query Translation can enhance performance. Key methods discussed include Parallel Query Retrieval, Reciprocal Rank Fusion, Query Decomposition, Step Back Prompting, and HyDE. These strategies involve transforming user queries to ensure precise document retrieval and response generation. The choice of technique depends on specific applications, and sometimes combining multiple methods is necessary for optimal results.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[RAG: Retrieval Augmented Generation Explained]]></title><description><![CDATA[In the era of Gen AI, understanding about RAG is very important. In GenAI industry developer who can build scalable RAG system are considered as hirable talent. Now days most of the company’s are betting on RAG application. Every organisation wants t...]]></description><link>https://understanding-gen-ai.hashnode.dev/rag-retrieval-augmented-generation-explained</link><guid isPermaLink="true">https://understanding-gen-ai.hashnode.dev/rag-retrieval-augmented-generation-explained</guid><category><![CDATA[RAG ]]></category><category><![CDATA[AI]]></category><category><![CDATA[ChaiCode]]></category><category><![CDATA[chatgpt]]></category><category><![CDATA[generative ai]]></category><dc:creator><![CDATA[Ganesh Ghadage]]></dc:creator><pubDate>Thu, 07 Aug 2025 07:27:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1754551617521/249b1e4c-8933-44a1-8109-26267d64c391.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the era of Gen AI, understanding about RAG is very important. In GenAI industry developer who can build scalable RAG system are considered as hirable talent. Now days most of the company’s are betting on RAG application. Every organisation wants to have their own AI assistant. To build the AI assistant you need to have understanding of RAG.</p>
<p>In this blog we will talk about RAG, how it works, what are different aspects of RAG system, different techniques involved in it, also we will build our own basic pdf chat RAG.</p>
<h2 id="heading-what-is-rag">What is RAG?</h2>
<p>As you know, When you talk with any AI model, it gives you the the responses based on it’s pretrained data. But what if I want model to answer based on my data which resides in by dataset which can be anything like, documents(pdf, word, excel), database or even website. It is won’t happen directly as model don’t have context of our data, it’s not trained on it.</p>
<p>So, we need to give context to model. But we can’t provide everything to model for every query users asks, it will go outside of its context windows and also increase the cost and irrelevant data to userquery might decrease the accuracy. Here RAG solves our problem.</p>
<h2 id="heading-how-rag-works">How RAG Works?</h2>
<p>When user asks query, we first search the relevant information from our datasource. Then using this information we ask LLM to generate the response, which will be based on our data. But is not that simple,</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754547686560/beb8c97a-a9a2-46b7-a604-f0d505a3d0a6.png" alt class="image--center mx-auto" /></p>
<p>The above diagram show the typical RAG system. As you can see in the above diagram you can see that RAG consists of 3 parts:</p>
<ol>
<li><p>Indexing / Ingestion</p>
</li>
<li><p>Retrieval</p>
</li>
<li><p>Generation</p>
</li>
</ol>
<blockquote>
<p>PS: Real-world RAG system will be more complex, This is just for understanding of RAG.</p>
</blockquote>
<p>let’s understand each part one by one.</p>
<h3 id="heading-indexing">Indexing:</h3>
<p>Indexing also referred as Ingestion, means loading the data from your dataset into vector store. This step in only performed for first time or when the dataset is changed. Generally we will have seperate script or pipeline for this.</p>
<p>In Indexing we first split the large dataset into smaller chunks. Then this chunks are converted into vector embeddings using any embedding model. Then this embeddings are stored into a vector store.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754546887224/0074c98e-9c26-41f2-9860-43a2186e2aea.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-retrieval">Retrieval</h3>
<p>In retrieval part, we retrive the relevant documents from vector store as per the user query. Retrieval itself has two steps in it.</p>
<p>First, Indexing: We Index the user query with a same embedding model that we used in the Indexing part, and generate it’s vector embeddings.</p>
<p>Second, Retrieval: Based on this vector embeddings of user query we perform the similarity search operation in the vector store, and fetch the top k similar documents from it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754548608416/e390034c-45b6-499c-902f-cde909126806.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-generation">Generation</h3>
<p>In this part, we take the user query and retrieved relevant data and feed it to the LLM Chat model and generate the response.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754549090671/3fa71db6-7d91-4d61-b3c3-2b407f2af270.png" alt class="image--center mx-auto" /></p>
<p>This generated response will based on our provided context to LLM.</p>
<h2 id="heading-basic-rag">Basic RAG</h2>
<p>Now once you have understood about the RAG, lets build basic pdf chat RAG.</p>
<p>We will take one pdf (nodejs.pdf), index it, store it’s embeddings in vector store (QdrantDB) and we will chat over it. We will be using langchain for this.</p>
<p>For this example, We will using self hosted QdrantDB using docker. Below is <code>docker-compose.yml</code> file for it. You can user by running <code>docker compose up</code> command.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">services:</span>
  <span class="hljs-attr">qdrant:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">qdrant/qdrant</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-number">6333</span><span class="hljs-string">:6333</span>
</code></pre>
<p>Step 1: Create qdrant client:</p>
<pre><code class="lang-python"><span class="hljs-comment">#qdrant.py</span>

<span class="hljs-keyword">from</span> qdrant_client <span class="hljs-keyword">import</span> QdrantClient

qdrant_client = QdrantClient(url=<span class="hljs-string">"http://localhost:6333"</span>)
</code></pre>
<p>Step 2: create an embedder</p>
<pre><code class="lang-python"><span class="hljs-comment">#embedder.py</span>

<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv
<span class="hljs-keyword">from</span> langchain_google_genai <span class="hljs-keyword">import</span> GoogleGenerativeAIEmbeddings

load_dotenv()

embeddings = GoogleGenerativeAIEmbeddings(
  model=<span class="hljs-string">"models/gemini-embedding-001"</span>,
  google_api_key=os.getenv(<span class="hljs-string">"GEMINI_API_KEY"</span>)
)
</code></pre>
<p>Step 3: Now, create a ingestion pipeline</p>
<pre><code class="lang-python"><span class="hljs-comment">#Ingestion.py</span>

<span class="hljs-keyword">from</span> pathlib <span class="hljs-keyword">import</span> Path

<span class="hljs-keyword">from</span> langchain_community.document_loaders <span class="hljs-keyword">import</span> PyPDFLoader
<span class="hljs-keyword">from</span> langchain_text_splitters <span class="hljs-keyword">import</span> RecursiveCharacterTextSplitter
<span class="hljs-keyword">from</span> langchain_qdrant <span class="hljs-keyword">import</span> QdrantVectorStore
<span class="hljs-keyword">from</span> qdrant_client.http.models <span class="hljs-keyword">import</span> Distance, VectorParams
<span class="hljs-keyword">from</span> langchain_google_genai._common <span class="hljs-keyword">import</span> GoogleGenerativeAIError

<span class="hljs-keyword">from</span> embedder <span class="hljs-keyword">import</span> embeddings
<span class="hljs-keyword">from</span> qdrant <span class="hljs-keyword">import</span> qdrant_client

print(<span class="hljs-string">"-------- Starting Ingestion ------------"</span>)

pdf_path = Path(__file__).parent / <span class="hljs-string">"nodejs.pdf"</span>
print(<span class="hljs-string">"File Path:"</span>, pdf_path)

loader = PyPDFLoader(file_path=pdf_path)
docs = loader.load()
print(<span class="hljs-string">"Doc length : "</span>, len(docs))

splitter = RecursiveCharacterTextSplitter(
  chunk_size=<span class="hljs-number">1000</span>,
  chunk_overlap=<span class="hljs-number">200</span>
)

chunks = splitter.split_documents(documents=docs)
print(<span class="hljs-string">"Chunks length : "</span>, len(chunks))

qdrant_client.create_collection(
  collection_name=<span class="hljs-string">"nodejs_document"</span>,
  vectors_config=VectorParams(size=<span class="hljs-number">3072</span>, distance=Distance.COSINE)
)

qdrant = QdrantVectorStore(
  client=qdrant_client,
  collection_name=<span class="hljs-string">"nodejs_document"</span>,
  embedding=embeddings
)

qdrant.add_documents(documents=batch)

print(<span class="hljs-string">"----------- Ingestion completed ------------"</span>)
</code></pre>
<p>Step 4: Create a retrieval and generation pipeline</p>
<pre><code class="lang-python"><span class="hljs-comment">#reterival.py</span>

<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv

<span class="hljs-keyword">from</span> langchain_qdrant <span class="hljs-keyword">import</span> QdrantVectorStore
<span class="hljs-keyword">from</span> langchain_google_genai <span class="hljs-keyword">import</span> ChatGoogleGenerativeAI
<span class="hljs-keyword">from</span> langchain_core.prompts <span class="hljs-keyword">import</span> ChatPromptTemplate

<span class="hljs-keyword">from</span> qdrant <span class="hljs-keyword">import</span> qdrant_client
<span class="hljs-keyword">from</span> embedder <span class="hljs-keyword">import</span> embeddings

load_dotenv()

qdrant = QdrantVectorStore(
  client=qdrant_client,
  collection_name=<span class="hljs-string">"nodejs_document"</span>,
  embedding=embeddings
)

llm = ChatGoogleGenerativeAI(
  model=<span class="hljs-string">"gemini-2.5-flash"</span>,
  google_api_key=os.getenv(<span class="hljs-string">"GEMINI_API_KEY"</span>),
  temperature=<span class="hljs-number">0</span>,
  max_tokens=<span class="hljs-literal">None</span>,
  timeout=<span class="hljs-literal">None</span>,
  max_retries=<span class="hljs-number">2</span>,
)

prompt = ChatPromptTemplate.from_messages(
  [
    (
      <span class="hljs-string">"system"</span>,
      <span class="hljs-string">"""You are an helpfull AI assistant, you answwr user query based on 
         revlevant context data provided to you.
      Relevant Context data :
      {relavent_chunks}"""</span>,
    ),
    (<span class="hljs-string">"human"</span>, <span class="hljs-string">"{input}"</span>),
  ]
)

chain = prompt | llm

query = input(<span class="hljs-string">"&gt; "</span>)
relavent_chunks = qdrant.similarity_search(query=query)

ai_msg = chain.invoke({
  <span class="hljs-string">"relavent_chunks"</span>: relavent_chunks,
  <span class="hljs-string">"input"</span>: query
})

print(ai_msg.content)
</code></pre>
<p>As this is basic RAG we will be doing retrieval and generation in same pipeline.</p>
<pre><code class="lang-python">relavent_chunks = qdrant.similarity_search(query=query)
</code></pre>
<p>The above single line acts as a retriever in this case.</p>
<pre><code class="lang-python">qdrant.similarity_search(query=query)
</code></pre>
<p>The above function from langchain will do both the indexing of user query, and fetch the relevant chunks from the vector store.</p>
<h2 id="heading-summary">Summary</h2>
<blockquote>
<p>In today's Gen AI landscape, mastering Retrieval-Augmented Generation (RAG) is crucial. RAG is a powerful method enabling AI models to provide responses using specific user data rather than just pretrained data. It involves three main components: Indexing/Ingestion, Retrieval, and Generation. This article explains how RAG systems work, outlining the steps to create a basic PDF chat RAG using tools like QdrantDB, Langchain, and Docker. By indexing data into vector stores and retrieving relevant information, we can enhance AI's contextual responses, making RAG an essential skill for developers in AI-driven industries.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[AI Agents]]></title><description><![CDATA[Now days you must have heard everyone talking about AI Agents or Agentic AI workflows. If you want to know what are the AI agents and how to build them,this is guide for you. In this blog we will talk about AI Agents and We will aslo build a small re...]]></description><link>https://understanding-gen-ai.hashnode.dev/ai-agents</link><guid isPermaLink="true">https://understanding-gen-ai.hashnode.dev/ai-agents</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[AI]]></category><category><![CDATA[#ai-tools]]></category><category><![CDATA[ai agents]]></category><category><![CDATA[agentic AI]]></category><dc:creator><![CDATA[Ganesh Ghadage]]></dc:creator><pubDate>Thu, 31 Jul 2025 14:16:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/5L0R8ZqPZHk/upload/4199a5a02e630c455906c6d8c2b4cf9e.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Now days you must have heard everyone talking about AI Agents or Agentic AI workflows. If you want to know what are the AI agents and how to build them,this is guide for you. In this blog we will talk about AI Agents and We will aslo build a small real-time weather AI Agent.</p>
<h2 id="heading-ai-agents">AI Agents</h2>
<p>AI agents are not a secret agents like James Bond. They are just a piece of code, which will fo some task for us.</p>
<p>All the pre trained LLM models are very good in understating user query, logical reasoning and thinking, but you ask them to perform any task they can not perform it, it’s like brain without hands and legs which can think but can not act. Agentic AI is like giving hands and legs to brain so that it can perform any action or task for us.</p>
<p>In Agentic AI workflow, we build some tools which acts as hands and legs of model and can perform any actions. We gave it’s access to LLM model, LLM model does the NLP (Natural Language Processing) of the user query, and based on the query it uses appropriate tool to perform the action asked by the user.</p>
<h2 id="heading-building-an-weather-ai-agent">Building An Weather AI Agent</h2>
<p>To build AI Agents we have to build an tool which will perform the action that we need.</p>
<p>Here we need an tool which make an API call to weather API and get a real-time current weather information for us.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_weather</span>(<span class="hljs-params">city: str</span>):</span>
  print(<span class="hljs-string">"🔨: get_weather tool called, input : "</span>, city)

  url = <span class="hljs-string">f"https://wttr.in/<span class="hljs-subst">{city}</span>?format=%C+%t"</span>
  response = requests.get(url)

  <span class="hljs-keyword">if</span> response.status_code == <span class="hljs-number">200</span>:
    <span class="hljs-keyword">return</span> response.text

  <span class="hljs-keyword">return</span> <span class="hljs-string">"Something went wrong"</span>
</code></pre>
<p>Now we have tell model that we have a tool which makes an and gets the real-time weather information. we provide this information in <code>SYSTEM_PROMPT</code></p>
<pre><code class="lang-python">avaliable_tools = {
  <span class="hljs-string">"get_weather"</span>: {
    <span class="hljs-string">"fn"</span>: get_weather,
    <span class="hljs-string">"description"</span>: <span class="hljs-string">"This function takes a city as a input and retuns the weather infomation for it."</span>
  }
}

tool_descriptions = <span class="hljs-string">"\n"</span>.join(
  <span class="hljs-string">f"- <span class="hljs-subst">{tool_name}</span>: <span class="hljs-subst">{avaliable_tools[tool_name][<span class="hljs-string">'description'</span>]}</span>"</span> <span class="hljs-keyword">for</span> tool_name <span class="hljs-keyword">in</span> avaliable_tools
)

system_prompt = <span class="hljs-string">f"""
  You are an helpfull weather AI assistant, you help in user to finding the current weather of their location.
  If user asks anything besids weather info, kindly reject the question.

  once user asks his query, you break down the query, analyze it, you plan how to answer it,
  use the approprate tool from the list to get required data, wait for it, and once you get data from tool
  use it to answer user query. include some funy message in output

  Follow the steps in sequence:
    analyze &gt; plan &gt; action &gt; observe &gt; output

  Rules:
    - follow strict JSON output format.
    - perform one step at a time and wait for next step
    - carefully analyze the user query

  Output JSON Format:
    {{
      "step": "string",
      "content": "string",
      "function": "string", # Name of the function in action step
      "input": "string", # Input paramenter for the function
      "result": string" # Output of the function call
    }}

  Avaliable tools:
    <span class="hljs-subst">{tool_descriptions}</span>

  Example:
    Input: What is weather in Pune?
    Output: {{"step": "analyze", "content": "User is instreated in knowing the weather information of pune"}}
    Output: {{"step": "plan", "content": "In order to get weather information I need to call get_weather tool with pune as parameter"}}
    Output: {{"step": "action", "function": "get_weather", "input": "pune"}}
    Output: {{"step": "observe", "result": "raniy, 20 degree Celcuis"}}
    Output: {{"step": "output", "content": "Curent weather of pune is raniy with 20 degree Celcuis, don't forget to take your umbrella!!"}}
"""</span>
</code></pre>
<p>Notice in the above <code>system_prompt</code> we have asked model to follow the strict JSON output and also asked him to follow the certain steps, here in this case <code>analyze &gt; plan &gt; action &gt; observe &gt; output</code>. Also provided model an available tools list and example demonstrating how he should approach for the answer.</p>
<p>When we ask AI a query which is related to weather, it will give us a tool name to call with it’s input parameter during an action step, By checking which step currently we are in, we only have call the function, decided by model. Note: model only provide us the tool name and we only have to invoke is, model can not invoke the tool.</p>
<pre><code class="lang-python"><span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
    response = client.chat.completions.create(
      model=<span class="hljs-string">"gemini-2.5-flash"</span>,
      response_format={<span class="hljs-string">"type"</span>: <span class="hljs-string">"json_object"</span>},
      messages=messages
    )

    parsed_response = json.loads(response.choices[<span class="hljs-number">0</span>].message.content)
    messages.append({<span class="hljs-string">"role"</span>: <span class="hljs-string">"assistant"</span>, <span class="hljs-string">"content"</span>: json.dumps(parsed_response)})

    <span class="hljs-keyword">if</span> parsed_response.get(<span class="hljs-string">"step"</span>) == <span class="hljs-string">"output"</span>:
      print(<span class="hljs-string">f"🤖: <span class="hljs-subst">{parsed_response.get(<span class="hljs-string">"content"</span>)}</span>"</span>)
      <span class="hljs-keyword">break</span>

    <span class="hljs-keyword">if</span> parsed_response.get(<span class="hljs-string">"step"</span>) == <span class="hljs-string">"action"</span>:
      function_name = parsed_response.get(<span class="hljs-string">"function"</span>)
      function_input = parsed_response.get(<span class="hljs-string">"input"</span>)

      <span class="hljs-keyword">if</span> function_name <span class="hljs-keyword">in</span> avaliable_tools:
        result = avaliable_tools[function_name][<span class="hljs-string">"fn"</span>](function_input)
        messages.append({<span class="hljs-string">"role"</span>: <span class="hljs-string">"assistant"</span>, <span class="hljs-string">"content"</span>: json.dumps({<span class="hljs-string">"step"</span>: <span class="hljs-string">"observe"</span>, <span class="hljs-string">"result"</span>: result})})
        <span class="hljs-keyword">continue</span>
      <span class="hljs-keyword">else</span>:
        print(<span class="hljs-string">f"❌ Invalid function name"</span>)
</code></pre>
<p>Notice if step is action we are extracting <code>function_name</code> and <code>function_input</code> from the models response and invoking the function from <code>avaliable_tools</code> list with <code>function_input</code> and appending the function’s output in the messages list to give the context to model.</p>
<p>Complete Code:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> json
<span class="hljs-keyword">import</span> requests

<span class="hljs-keyword">from</span> openai <span class="hljs-keyword">import</span> OpenAI
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv

load_dotenv()

client = OpenAI()

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_weather</span>(<span class="hljs-params">city: str</span>):</span>
  print(<span class="hljs-string">"🔨: get_weather tool called, input : "</span>, city)

  url = <span class="hljs-string">f"https://wttr.in/<span class="hljs-subst">{city}</span>?format=%C+%t"</span>
  response = requests.get(url)

  <span class="hljs-keyword">if</span> response.status_code == <span class="hljs-number">200</span>:
    <span class="hljs-keyword">return</span> response.text

  <span class="hljs-keyword">return</span> <span class="hljs-string">"Something went wrong"</span>

avaliable_tools = {
  <span class="hljs-string">"get_weather"</span>: {
    <span class="hljs-string">"fn"</span>: get_weather,
    <span class="hljs-string">"description"</span>: <span class="hljs-string">"This function takes a city as a input and retuns the weather infomation for it."</span>
  }
}

tool_descriptions = <span class="hljs-string">"\n"</span>.join(
  <span class="hljs-string">f"- <span class="hljs-subst">{tool_name}</span>: <span class="hljs-subst">{avaliable_tools[tool_name][<span class="hljs-string">'description'</span>]}</span>"</span> <span class="hljs-keyword">for</span> tool_name <span class="hljs-keyword">in</span> avaliable_tools
)

system_prompt = <span class="hljs-string">f"""
  You are an helpfull weather AI assistant, you help in user to finding the current weather of their location.
  If user asks anything besids weather info, kindly reject the question.

  once user asks his query, you break down the query, analyze it, you plan how to answer it,
  use the approprate tool from the list to get required data, wait for it, and once you get data from tool
  use it to answer user query. include some funy message in output

  Rules:
    - follow strict JSON output format.
    - perform one step at a time and wait for next step
    - carefully analyze the user query

  Output JSON Format:
    {{
      "step": "string",
      "content": "string",
      "function": "string", # Name of the function in action step
      "input": "string", # Input paramenter for the function
      "result": string" # Output of the function call
    }}

  Avaliable tools:
    <span class="hljs-subst">{tool_descriptions}</span>

  Example:
    Input: What is weather in Pune?
    Output: {{"step": "analyze", "content": "User is instreated in knowing the weather information of pune"}}
    Output: {{"step": "plan", "content": "In order to get weather information I need to call get_weather tool with pune as parameter"}}
    Output: {{"step": "action", "function": "get_weather", "input": "pune"}}
    Output: {{"step": "observe", "result": "raniy, 20 degree Celcuis"}}
    Output: {{"step": "output", "content": "Curent weather of pune is raniy with 20 degree Celcuis, don't forget to take your umbrella!!"}}
"""</span>

messages = []
messages.append({<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: system_prompt})

print(<span class="hljs-string">"Welcome 🙋🏼‍♂️, Know the weather of your location!⛅"</span>)
<span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
  query = input(<span class="hljs-string">"&gt; "</span>)
  messages.append({<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: query})

  <span class="hljs-keyword">if</span> query.lower() <span class="hljs-keyword">in</span> [<span class="hljs-string">'exit'</span>, <span class="hljs-string">'quit'</span>] :
    print(<span class="hljs-string">"Good Bye!! 👋🏼"</span>)
    <span class="hljs-keyword">break</span>

  <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
    response = client.chat.completions.create(
      model=<span class="hljs-string">"gemini-2.5-flash"</span>,
      response_format={<span class="hljs-string">"type"</span>: <span class="hljs-string">"json_object"</span>},
      messages=messages
    )

    parsed_response = json.loads(response.choices[<span class="hljs-number">0</span>].message.content)
    messages.append({<span class="hljs-string">"role"</span>: <span class="hljs-string">"assistant"</span>, <span class="hljs-string">"content"</span>: json.dumps(parsed_response)})

    <span class="hljs-keyword">if</span> parsed_response.get(<span class="hljs-string">"step"</span>) == <span class="hljs-string">"output"</span>:
      print(<span class="hljs-string">f"🤖: <span class="hljs-subst">{parsed_response.get(<span class="hljs-string">"content"</span>)}</span>"</span>)
      <span class="hljs-keyword">break</span>

    <span class="hljs-keyword">if</span> parsed_response.get(<span class="hljs-string">"step"</span>) == <span class="hljs-string">"action"</span>:
      function_name = parsed_response.get(<span class="hljs-string">"function"</span>)
      function_input = parsed_response.get(<span class="hljs-string">"input"</span>)

      <span class="hljs-keyword">if</span> function_name <span class="hljs-keyword">in</span> avaliable_tools:
        result = avaliable_tools[function_name][<span class="hljs-string">"fn"</span>](function_input)
        messages.append({<span class="hljs-string">"role"</span>: <span class="hljs-string">"assistant"</span>, <span class="hljs-string">"content"</span>: json.dumps({<span class="hljs-string">"step"</span>: <span class="hljs-string">"observe"</span>, <span class="hljs-string">"result"</span>: result})})
        <span class="hljs-keyword">continue</span>
      <span class="hljs-keyword">else</span>:
        print(<span class="hljs-string">f"❌ Invalid function name"</span>)

    print(<span class="hljs-string">f"🧠: <span class="hljs-subst">{parsed_response.get(<span class="hljs-string">"content"</span>)}</span>"</span>)
</code></pre>
<p>Above is the complete for a simple real-time weather AI Agent code. You can directly copy and run it. Make sure you provide the OpenAI API Key.</p>
<p>Now, once you understand the Agentic AI concept, we just have to build various tools and give their access to model. Use case this can be anything, we can build function which can read/write in database, a function which can even write a code for us, any function which fulfills your requirement.</p>
<p>You are just one function away to build your own personalized AI Agent.</p>
<h2 id="heading-summary">Summary</h2>
<blockquote>
<p>The article introduces AI Agents and Agentic AI workflows, explaining their function as code pieces that execute tasks, akin to giving hands and legs to a brain (LLM models). It outlines steps to build an AI agent with a real-time weather example, showcasing how to create a tool for weather data retrieval via API calls. The guide emphasizes a structured workflow: analyze, plan, action, observe, and output. The article also highlights the capability of creating personalized AI agents by developing various functions that can interact with databases, generate code, or meet specific needs, contingent on integrating them with AI models like OpenAI's.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[Prompting and it's techniques]]></title><description><![CDATA[When type you query to Chat GPT or Gemini or any other AI model. you might have wondered that sometime is gives correct and precise response but sometimes it gives some garbage response. You might have wondered how this happens, Well it’s because how...]]></description><link>https://understanding-gen-ai.hashnode.dev/prompting-and-its-techniques</link><guid isPermaLink="true">https://understanding-gen-ai.hashnode.dev/prompting-and-its-techniques</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[generative ai]]></category><category><![CDATA[#PromptEngineering]]></category><category><![CDATA[AI]]></category><category><![CDATA[chatgpt]]></category><dc:creator><![CDATA[Ganesh Ghadage]]></dc:creator><pubDate>Sat, 26 Jul 2025 17:42:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/npxXWgQ33ZQ/upload/c02f94331b0309c0f62e9d05b0949713.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When type you query to Chat GPT or Gemini or any other AI model. you might have wondered that sometime is gives correct and precise response but sometimes it gives some garbage response. You might have wondered how this happens, Well it’s because how you give input query to AI. If you asks you question precise and accurate it will give precise answer, but if you asks incorrect question, it will give incorrect response. So understanding how you give your prompt LLM is very necessary to get output you desired.</p>
<p>Before learning about Prompting techniques, let’s understand few key concepts.</p>
<h2 id="heading-what-is-prompt">What is Prompt?</h2>
<p>Prompt is a piece of text or input given to AI model, We can say that it’s nothing but initial tokens.</p>
<h2 id="heading-system-prompt">System Prompt</h2>
<p>System prompt is set of predefined instructions which sets the initial context. System prompt are guidelines given to the model by its developer or administrator to shape the behaviour of model, how AI responds, its tone.</p>
<h1 id="heading-prompting-techniques">Prompting Techniques</h1>
<h2 id="heading-zero-shot-prompting">Zero Shot Prompting</h2>
<p>In this prompting technique we directly ask question to LLM, we didn’t provide any background context or give any example to LLM</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> openai <span class="hljs-keyword">import</span> OpenAI
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv

load_dotenv()

client = OpenAI()

responce = client.chat.completions.create(
  model=<span class="hljs-string">"gpt-4"</span>,
  messages=[
   { <span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"What is 2 + 2?"</span>}
  ]
)

print(responce.choices[<span class="hljs-number">0</span>].message.content)
</code></pre>
<h2 id="heading-few-shot-prompting">Few Shot Prompting</h2>
<p>In this prompting technique we sets context to LLM, give few examples for it. Which will help LLM to answer the query efficiently.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv
<span class="hljs-keyword">from</span> openai <span class="hljs-keyword">import</span> OpenAI

load_dotenv()

client = OpenAI()

system_prompt = <span class="hljs-string">"""
You are an AI Assistant who is specialized in maths.
You should not answer any query that is not related to maths.

For a given query help user to solve that along with explanation.

Example:
Input: 2 + 2
Output: 2 + 2 is 4 which is calculated by adding 2 with 2.

Input: 3 * 10
Output: 3 * 10 is 30 which is calculated by multipling 3 by 10. Funfact you can even multiply 10 * 3 which gives same result.

Input: Why is sky blue?
Output: Bruh? You alright? Is it maths query?
"""</span>

result = client.chat.completions.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        { <span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: system_prompt },
        { <span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"what is a mobile phone?"</span> }
    ]
)

print(result.choices[<span class="hljs-number">0</span>].message.content)
</code></pre>
<h2 id="heading-chain-of-thoughts">Chain of Thoughts</h2>
<p>In this type of technique we encourage model to break down the user query and think over it 3-5 times before answering the question.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> json

<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv
<span class="hljs-keyword">from</span> openai <span class="hljs-keyword">import</span> OpenAI

load_dotenv()

client = OpenAI()

system_prompt = <span class="hljs-string">"""
You are an AI assistant who is expert in breaking down complex problems and then resolve the user query.

For the given user input, analyse the input and break down the problem step by step.
Atleast think 5-6 steps on how to solve the problem before solving it down.

The steps are you get a user input, you analyse, you think, you again think for several times and then return an output with explanation and then finally you validate the output as well before giving final result.

Follow the steps in sequence that is "analyse", "think", "output", "validate" and finally "result".

Rules:
1. Follow the strict JSON output as per Output schema.
2. Always perform one step at a time and wait for next input
3. Carefully analyse the user query

Output Format:
{{ step: "string", content: "string" }}

Example:
Input: What is 2 + 2.
Output: {{ step: "analyse", content: "Alright! The user is intersted in maths query and he is asking a basic arthermatic operation" }}
Output: {{ step: "think", content: "To perform the addition i must go from left to right and add all the operands" }}
Output: {{ step: "output", content: "4" }}
Output: {{ step: "validate", content: "seems like 4 is correct ans for 2 + 2" }}
Output: {{ step: "result", content: "2 + 2 = 4 and that is calculated by adding all numbers" }}

"""</span>

messages = [
    { <span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: system_prompt },
]


query = input(<span class="hljs-string">"&gt; "</span>)
messages.append({ <span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: query })


<span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
    response = client.chat.completions.create(
        model=<span class="hljs-string">"gpt-4o"</span>,
        response_format={<span class="hljs-string">"type"</span>: <span class="hljs-string">"json_object"</span>},
        messages=messages
    )

    parsed_response = json.loads(response.choices[<span class="hljs-number">0</span>].message.content)
    messages.append({ <span class="hljs-string">"role"</span>: <span class="hljs-string">"assistant"</span>, <span class="hljs-string">"content"</span>: json.dumps(parsed_response) })

    <span class="hljs-keyword">if</span> parsed_response.get(<span class="hljs-string">"step"</span>) != <span class="hljs-string">"output"</span>:
        print(<span class="hljs-string">f"🧠: <span class="hljs-subst">{parsed_response.get(<span class="hljs-string">"content"</span>)}</span>"</span>)
        <span class="hljs-keyword">continue</span>

    print(<span class="hljs-string">f"🤖: <span class="hljs-subst">{parsed_response.get(<span class="hljs-string">"content"</span>)}</span>"</span>)
    <span class="hljs-keyword">break</span>
</code></pre>
<h2 id="heading-persona-based-prompting">Persona-based Prompting</h2>
<p>In this type of technique, The model is instructed to respond as if it were a particular character or professional. We assign model some personality and expect model to answer the questions in tone of that person.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv
<span class="hljs-keyword">from</span> openai <span class="hljs-keyword">import</span> OpenAI

load_dotenv()

client = OpenAI()

system_prompt = <span class="hljs-string">"""
  Your are Hitesh sir, who is expert in Technologies like MERN Stack, Python, Gen AI
  You lot to talk about new and emerging techology, You talk in Hinglish (Hindi + English)
  like "Hannji kaise ho!", Hitesh uses "Hann ji!!" in most of sentences and love to drink Chai,
  Hitesh Sir have two youtube channels named ChaiAurCode and Hitesh Choudhri.

  Hitesh Sir guides students in their learning journy and loves to solve their doubts. keep answer short and sweet.


  Converation with Hitesh Sir looks like this:
  1.  
    Hitesh: Hnjii, to aap Ai se darney waalo me se hain ya use karney waalo me se hai?
    Student: Hum to AI ka use karne wale hai.
    Hitesh: To kal he humne chai aur code youtube channel pai ek n8 wala course dala hai wo dekha ki nahi?
    Student: Ji sir, dekha na badhiya hai.
    Hitesh: Glad you found this content valuable, more such videos coming!

  2. 
    Student: Without formal education can I get job in coding
    Hitesh: Bilkul lekin dekhate hai, dekho bahot sari company bolti hai ki hume education ki requirement nahi hai
            lekin agr unke pass 5000 application aa gayi to kaise filter karenge wo log, kaise filter kare ki aapko 
            le ya na le, tak lagta hai criteria, ta ki bhid ko chatana hai, agar aapke pass formal education nahi hai
            to aapko un logo se jyada mehant karni padegi, unse jyada aapko apne aap ko proof karna padega jinke pass
            education bhi hai aur, aap jitni mehnat bhi kr rahe hai.

  Some of Hitesh Sir's tweets 
    1. Jb protein ka paani aa hi gya h to, gol gappe bna do na uske. Per puchka 3gm 😂
    2. Ye flight travel se hi dr lagne laga h ab to. Affordable vs Zindgi me to Zindgi hi select krenge na. Kya hi chal h, fielding lagi hui h hr jgh🫣
    3. Ab @coolifyio jaise projects ki hum baat nhi krenge to kon krega Self host coolify on @Hostinger ChaiAurCode YouTube channel pe available h video, enjoy
"""</span>

result = client.chat.completions.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        { <span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: system_prompt },
        { <span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"what is a mobile phone?"</span> }
    ]
)

print(result.choices[<span class="hljs-number">0</span>].message.content)
</code></pre>
<h2 id="heading-self-consistency-prompting">Self-Consistency Prompting:</h2>
<p>In this type of technique, we ask model to generate multiple outputs and ask him to choose the most relevant answer.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> json

<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv
<span class="hljs-keyword">from</span> openai <span class="hljs-keyword">import</span> OpenAI

load_dotenv()

client = OpenAI()

system_prompt = <span class="hljs-string">"""
  You are an helpfull AI assistant, you help is solving users query.
  User can ask you about any thing, you have carefully understand the user input and
  generate at least 4 to 5 responces carefully analyze the responce cross check each on them with
  user query and give user the best sutiable and relevant responce.

  The steps are you get an user input, you analyze it, you generate 4-5 responces, you analyze the responces and query, and finally you give the output

  Follow the steps in squence that is "analyze", "think", "reponces", "responce_analysis" and "output"

  Rules:
    1. Follow the strict JSON output as per Output schema.
    2. Always perform one step at a time and wait for next input
    3. Carefully analyse the user query

  Output Format:
    {{ step: "string", content: "string" }}

  Example:
  Input: what is greater 9.8 or 9.11
  Output: {{ step: "analyze", content: "The user is asking about what is greater 9.8 or 9.11?"}}
  Output: {{ step: "think", content: "To answer this question I must think is aspect of fileds, mathematic, writing, finical, time"}}
  Output: {{ step: "responce", content: [
      "If you are taking about mathematical terms 9.8 is greater that 9.11",
      "If you are asking in therms of book chapter 9.11 is greater than 9.8 as chapter 9.11 comes after 9.8",
      "User is asking about what is greater 9.8 or 9.11, 9.8 can be considered as 9.80, and 80 is greater than 11, so 9.8 is greater.",
      "If we look in aspect of time, 9 hrs 8 min is less than 9 hrs 11 min, so in this case 9.11 is greater."
    ]
  }}
  Output: {{ step: "responce_analysis", content: "after thinking in all the aspects like mathematic, writing, and time, 
          also noticed that user hasn't provided the aspecct he is looking, I will assume he maths aspect is most comman in this of questions 
          so the answer will be 9.8 is greater that 9.11"}}
  Output: {{ step: output" content: "9.8 is greater that 9.11"}}

"""</span>

messages = [
    { <span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: system_prompt },
]


query = input(<span class="hljs-string">"&gt; "</span>)
messages.append({ <span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: query })


<span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
    response = client.chat.completions.create(
        model=<span class="hljs-string">"gpt-4o"</span>,
        response_format={<span class="hljs-string">"type"</span>: <span class="hljs-string">"json_object"</span>},
        messages=messages
    )

    parsed_response = json.loads(response.choices[<span class="hljs-number">0</span>].message.content)
    messages.append({ <span class="hljs-string">"role"</span>: <span class="hljs-string">"assistant"</span>, <span class="hljs-string">"content"</span>: json.dumps(parsed_response) })

    <span class="hljs-keyword">if</span> parsed_response.get(<span class="hljs-string">"step"</span>) != <span class="hljs-string">"output"</span>:
        print(<span class="hljs-string">f"🧠: <span class="hljs-subst">{parsed_response.get(<span class="hljs-string">"content"</span>)}</span>"</span>)
        <span class="hljs-keyword">continue</span>

    print(<span class="hljs-string">f"🤖: <span class="hljs-subst">{parsed_response.get(<span class="hljs-string">"content"</span>)}</span>"</span>)
    <span class="hljs-keyword">break</span>
</code></pre>
<h2 id="heading-instruction-prompting">Instruction Prompting</h2>
<p>The model is explicitly instructed to follow a particular format or guideline.</p>
<h2 id="heading-direct-answer-prompting">Direct Answer Prompting</h2>
<p>The model is asked to give a concise and direct response without explanation.</p>
<h2 id="heading-role-playing-prompting">Role-Playing Prompting</h2>
<p>The model assumes a specific role and interacts accordingly.</p>
<h2 id="heading-contextual-prompting">Contextual Prompting</h2>
<p>The prompt includes background information to improve response quality.</p>
<h2 id="heading-multimodal-prompting">Multimodal Prompting</h2>
<p>The model is given a combination of text, images, or other modalities to generate a response.</p>
]]></content:encoded></item><item><title><![CDATA[Decoding AI Jargons]]></title><description><![CDATA[In the world of Artificial Intelligence (AI), almost 8 out 10 developer’s are starting their generative AI juronery, and I am one of them. Before starting with Gen AI, you should be aware of some important AI concepts. In this article we going to und...]]></description><link>https://understanding-gen-ai.hashnode.dev/decoding-ai-jargons</link><guid isPermaLink="true">https://understanding-gen-ai.hashnode.dev/decoding-ai-jargons</guid><category><![CDATA[AI]]></category><category><![CDATA[llm]]></category><category><![CDATA[ChaiCode]]></category><category><![CDATA[chatgpt]]></category><category><![CDATA[generative ai]]></category><dc:creator><![CDATA[Ganesh Ghadage]]></dc:creator><pubDate>Fri, 25 Jul 2025 03:49:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/nYSdjVD2ayo/upload/1925b6e02c4d9d75650d3e9cebfcb588.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the world of Artificial Intelligence (AI), almost 8 out 10 developer’s are starting their generative AI juronery, and I am one of them. Before starting with Gen AI, you should be aware of some important AI concepts. In this article we going to understand some core concepts of AI.</p>
<p>Everyone has used Chat GPT, but have you wondered how the GPT answers your query?, how it writes a code that fits to your requirements?, How it generates the content?, Let’s understand this.</p>
<p>Well, the answer of this is in the name of Chat GPT - <strong>GPT (Generative Pretrained Transformer)</strong>, it is a Transformer which is Pertained with high volume of data and it is generative in nature. Let’s understander this transformer in detail.</p>
<blockquote>
<p>Chat GPT is interface using which we can chat with GPT model with added functionality.</p>
</blockquote>
<h1 id="heading-transformer">Transformer</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753338067067/a3f90fb4-af7b-446e-a130-bacf5bdc74d0.png" alt class="image--center mx-auto" /></p>
<p>Ref: <a target="_blank" href="https://research.google/pubs/attention-is-all-you-need/">https://research.google/pubs/attention-is-all-you-need/</a></p>
<p>The transformer you see in the above image is proposed by Google, It was originally developed for Google translator, This also used in LLM training. We won’t going the depth of transform, but only going to understand how it works</p>
<h2 id="heading-phase-1-input-embedding">Phase 1 : Input Embedding</h2>
<h3 id="heading-tokenization">Tokenization</h3>
<p>When enter a query to GPT, your query is first tokenized based on some predertimed algorithms. Every LLM has its own tokenizer.</p>
<p>Tokenization is nothing but breaking down the text or input data into smaller chunks called tokens. This tokens are often converted into numerical for better understating of LLMs. Tokenization is first step in making data understandable for AI</p>
<p><a target="_blank" href="https://github.com/openai/tiktoken">tiktoken</a> is library used by OpenAI to convert words into tokens,</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> tiktoken

encoder = tiktoken.encoding_for_model(<span class="hljs-string">'gpt-4o'</span>)
print(<span class="hljs-string">"Vocab Size: "</span>, encoder.n_vocab) <span class="hljs-comment"># (200,019)</span>

text=<span class="hljs-string">"The cat sat on the mat"</span>

encoded = encoder.encode(text)
print(<span class="hljs-string">"Encoded Tokens: "</span>, encoded) <span class="hljs-comment"># [976, 9059, 10139, 402, 290, 2450]</span>

decoded = encoder.decode(encoded)
print(<span class="hljs-string">"Decoded Text: "</span>, decoded) <span class="hljs-comment"># "The cat sat on the mat"</span>
</code></pre>
<h3 id="heading-vector-embedding">Vector Embedding</h3>
<p>Once the your input query is tokenized, this data is transformed into multidimensional representation where each dimension represent the similar meaning and close relation among the words. This numerical repreparation of data points representing their meaning and relation is known as Vector Embedding. This enables LLM’s to process data efficiently.</p>
<p>The position of data points in space reflects its meaning and relation with other data points. The words with similar meaning will be placed closer in the space while words with dissimilar meaning will apart from each other.</p>
<p>Example:</p>
<p>King and Queen are similar words and has relation in between them, also the words Man and Woman has same meaning and same relation between them, when we plot this words on 3D space, it will looks something like below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753411344721/27f768fc-fb1b-425f-87bf-5dbfa35093bc.png" alt class="image--center mx-auto" /></p>
<p>On the graph there will be same distance between King to Queen and Man to Woman, King to Man and Queen to Woman.</p>
<p><a target="_blank" href="https://projector.tensorflow.org/">https://projector.tensorflow.org/</a> You can go to this link to visualize how vector embeddings looks like.</p>
<p>Vector Embeddings helps us find the <strong>semantic meaning</strong> of the words.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> google <span class="hljs-keyword">import</span> genai
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv
<span class="hljs-keyword">import</span> os

load_dotenv()

client = genai.Client(api_key=os.getenv(<span class="hljs-string">"GEMINI_API_KEY"</span>))

text=<span class="hljs-string">"The cat sat on the mat"</span>

result = client.models.embed_content(
  model=<span class="hljs-string">"gemini-embedding-001"</span>,
  contents=text
)

print(<span class="hljs-string">"Embeded Text: "</span>, result.embeddings)

<span class="hljs-comment">#  values=[</span>
<span class="hljs-comment">#     -0.022850024,</span>
<span class="hljs-comment">#     0.012087576,</span>
<span class="hljs-comment">#     -0.0012127935,</span>
<span class="hljs-comment">#     -0.07871191,</span>
<span class="hljs-comment">#     0.0022645553,</span>
<span class="hljs-comment">#     &lt;... 3067 more items ...&gt;,</span>
<span class="hljs-comment">#   ]</span>
</code></pre>
<h2 id="heading-phase-2-positional-encoding">Phase 2 : Positional Encoding</h2>
<p>Once the vector embeddings are generated then this embeddings are encoded based on their position. In This process the words in sentences are provided with the information about their sequence in the sentence. As the transformer process the all the input tokens parallely, and don’t capture the sequence of the words. This encoding is added to the word embeddings to allow the model to understand the relationships between words based on their position in the sentence. </p>
<p>Without positional information, the model would treat all words the same regardless of their position, making it difficult to understand context and relationships. Positional encoding involves adding a vector, representing the position of a token in the sequence, to the token's embedding vector. </p>
<p>Example</p>
<p>Consider the sentence “The Cat sat on the mat”, if we don’t consider the positional encoding sentence might become as “The mat sat on the Cat”, which will entirely change the meaning of the sentence.</p>
<h2 id="heading-phase-3-self-attention">Phase 3 : Self Attention</h2>
<p>Self Attention is the mechanism that allows the transformer to highlight the importance of the different words of input sentence when processing the words. It helps the model to understand the relation between the words by considering the entire context rather than just relaying on static embeddings. Self Attention allows the model to dynamically adjust the representation of each word based on its relationship with all other words in the sequence, leading to a more context-aware understanding of the input. </p>
<p>Example:</p>
<p>Consider we have two sentences -</p>
<ol>
<li><p>The river bank</p>
</li>
<li><p>The ICICI bank</p>
</li>
</ol>
<p>In this above sentences bank is common word, but it has different meaning in both the sentences. In Self Attention it has been made aware that in first sentence it is associated with river and in second sentence it is associated with ICICI, so the word back adjust its embedding to be more precise about which back are we talking about.</p>
<p>It can done in <strong>single headed</strong> or <strong>multi headed</strong> format.</p>
<p>Both Encoder and Decoder of LLM works on the nearly same principle.</p>
<h1 id="heading-extra-key-concepts">Extra key concepts</h1>
<h3 id="heading-knowledge-cutoff"><strong>Knowledge cutoff</strong></h3>
<p>All the LLM’s are trained with past data and can not answer the query related to real-time data. Every model has a <strong>Knowledge cutoff</strong>, the data till the data model is trained on.</p>
<p>When you ask the GPT what is current weather of Pune, It won’t be able to answer it, as it does not have current data.</p>
<blockquote>
<p>But Chat GPT can answer it, as it uses Agentic AI workflows to call Weather API and gets the real-time weather information. This is one of the added functionality</p>
</blockquote>
<h3 id="heading-temperature">Temperature</h3>
<p>It is a parameter of model that controls the randomness and creativity of the model's output</p>
<h3 id="heading-softmax">Softmax</h3>
<p>The softmax is function that is used in the final layer of a neural network model for classification of tasks, it converts raw output scores into probabilities. it also known as logits</p>
<h3 id="heading-vocab-size"><strong>Vocab Size:</strong></h3>
<p>Number of unique token available in the tokenization dictionary</p>
]]></content:encoded></item></channel></rss>