<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The technicalities Archives - TantusData</title>
	<atom:link href="https://tantusdata.com/insights-categories/technicalities/feed/" rel="self" type="application/rss+xml" />
	<link>https://tantusdata.com/insights-categories/technicalities/</link>
	<description>That uncovers wisdom.</description>
	<lastBuildDate>Tue, 25 Mar 2025 11:40:06 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.7.1</generator>

<image>
	<url>https://tantusdata.com/app/uploads/2023/01/cropped-Favicon-32x32.png</url>
	<title>The technicalities Archives - TantusData</title>
	<link>https://tantusdata.com/insights-categories/technicalities/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>What you need to know before deploying Open Source LLM</title>
		<link>https://tantusdata.com/insights/what-to-know-before-deploying-open-source-llm/</link>
		
		<dc:creator><![CDATA[Bartek Sadlej]]></dc:creator>
		<pubDate>Sat, 19 Oct 2024 13:57:27 +0000</pubDate>
				<category><![CDATA[Deployment Strategies for LLMs]]></category>
		<category><![CDATA[LLM]]></category>
		<category><![CDATA[LLM Benchmarks Understanding]]></category>
		<category><![CDATA[LLM Licensing]]></category>
		<category><![CDATA[LLM Performance Trade-offs]]></category>
		<category><![CDATA[Open Source LLM Deployment]]></category>
		<guid isPermaLink="false">https://tantusdata.com/?post_type=insights&#038;p=1925</guid>

					<description><![CDATA[<p>Navigating the complexities of deploying open-source Large Language Models (LLMs) can be daunting. From understanding licensing restrictions and making crucial decisions about accuracy, speed, and cost trade-offs, to comprehending benchmark evaluations and exploring deployment strategies, this guide provides essential insights for leveraging open-source LLMs effectively in your projects.</p>
<p>The post <a href="https://tantusdata.com/insights/what-to-know-before-deploying-open-source-llm/">What you need to know before deploying Open Source LLM</a> appeared first on <a href="https://tantusdata.com">TantusData</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="585" src="https://tantusdata.com/app/uploads/2024/03/What-you-need-to-know-before-deploying-Open-Source-LLM-1024x585.jpg" alt="" class="wp-image-2174" srcset="https://tantusdata.com/app/uploads/2024/03/What-you-need-to-know-before-deploying-Open-Source-LLM-1024x585.jpg 1024w, https://tantusdata.com/app/uploads/2024/03/What-you-need-to-know-before-deploying-Open-Source-LLM-300x171.jpg 300w, https://tantusdata.com/app/uploads/2024/03/What-you-need-to-know-before-deploying-Open-Source-LLM-768x439.jpg 768w, https://tantusdata.com/app/uploads/2024/03/What-you-need-to-know-before-deploying-Open-Source-LLM-1536x878.jpg 1536w, https://tantusdata.com/app/uploads/2024/03/What-you-need-to-know-before-deploying-Open-Source-LLM.jpg 1792w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>There are a few key questions which need to be thoroughly understood and answered before selecting a large language model to be used for building an application:</p>



<ul class="wp-block-list">
<li>License &#8211; because you don’t want to end up in a legal trap</li>



<li>Expectations: accuracy, speed and cost tradeoffs</li>



<li>Understanding of benchmarks the model was evaluated on &#8211; so you don’t get surprised when evaluating the model with your users on your data</li>



<li>Deployment options &#8211; because building a PoC you run on your laptop is often far from production deployment.</li>
</ul>



<h2 class="wp-block-heading">License</h2>



<p>This sounds easy; open source is open, as the name suggests. Well, not exactly. Ensure that the model you choose can be used as you want. For example, there is a statement in the Llama-2 license:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><em>v. You will not use the Llama Materials or any output or results of the Llama Materials to improve any other large language model (excluding Llama 2 or derivative works thereof)</em>.</p>
</blockquote>



<p>This means that if you start with Llama-2 or its fine-tuned successors and later, at some point in time, decide to switch to a different model, you are not allowed to use your historical data to train the new LLM. Or are you? If you were to modify one line of model code, it is no longer the original <code>Llama Material</code> and so on. In general, AI and code base product regulations are hard to assess and interpret, so it is probably safe to try finding a model with an Apache License or an even more permissive license first, if possible.</p>



<h2 class="wp-block-heading">Define your expectation: accuracy, speed and cost tradeoffs.</h2>



<p>It is tempting to dream big, especially for non-technical people who have seen the recent OpenAI Dev Day with the announcements of GPTs, Assistants and Google Gemini &amp; Lumiere models. But in reality, meeting excessive expectations is challenging and often impossible. Going from 0% to 90% AI automation is difficult but doable; closing the gap between 90% and 100% is exceptionally demanding.</p>



<p>Think about Github Copilot. It won&#8217;t write a project for you, but its blazingly fast few-line completions, which usually require little adjusting, make engineers far more productive.&nbsp;</p>



<p>Ask the question: does my model need to figure out the nitty-gritty details? Or leave some space for users to interact and fill the missing gaps while creating a valuable product.</p>



<p>Maybe some parts of the pipeline can be postponed and implemented as batch jobs? The cost reductions might be significant in this case since closed model providers don&#8217;t offer lower prices for batch requests. In-house LLM allows you to process tasks offline in batches.</p>



<p>The recently released small Open Source LLM, such as Llama-2 and Mistral, or their further fine-tuned versions, like Zephyr and OpenHermes-2.5, are a perfect match for such a scenario. If you cannot compromise on accuracy, maybe there is a way to algorithmically fix weak spots.&nbsp;</p>



<p>On the other hand, it might be valuable to provide users with a few different model outputs or allow them to iterate and guide the suggestions quickly, such as with GithubCopilot. GPT-4 is powerful, but it would take minutes to call it a few times. Smaller models allow you to do such things.&nbsp;<a href="https://huggingface.co/blog/optimum-nvidia" target="_blank" rel="noreferrer noopener">Recent features</a>&nbsp;from Hugging Face and Nvidia can run Llama-v2-13b with an unbelievable speed of 1200 tokens per second.&nbsp;</p>



<h2 class="wp-block-heading">Understand the benchmarks the model was evaluated on</h2>



<p>When choosing the model, you will probably focus on its size, performance, and &#8216;the vibe&#8217; &#8211; whether the model&#8217;s responses generally feel good. The performance is most often checked using the results of well-known benchmarks.</p>



<p>What are the weak spots of this approach?</p>



<p>First, the ML Labs releasing the model does not always publish the training data or even more precise information about what the model was trained on. It is often the case that we only see that &#8216;the model was trained on a well-curated corpus of X tokens&#8217;. And because those benchmarks are so popular, there is a possibility of some leakages into the training set. Not immediately the whole corpus, but for example, an automatic web crawl can contain conversations from Reddit or X/Twitter feeds about a particular task where people are discussing some parts of the benchmark.</p>



<p>Secondly, keep in mind that, in general, it is hard to benchmark written text automatically.&nbsp;&nbsp;</p>



<p>To uncover that, it is crucial to understand how each of those benchmarks is created and what it measures.&nbsp;</p>



<p>Let&#8217;s see an example question from one of the most popular ones, the MMLU (<a href="https://arxiv.org/abs/2009.03300" target="_blank" rel="noreferrer noopener">Massive Multitask Language Understanding</a>):</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Question: Glucose is transported into the muscle cell:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Choices:<br>A. via protein transporters called GLUT4.<br>B. only in the presence of insulin.<br>C. via hexokinase.<br>D. via monocarboxylic acid transporters.</p>
</blockquote>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Correct answer: A</p>
</blockquote>
</blockquote>



<p>And let’s ask ChatGPT:</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="676" src="https://tantusdata.com/app/uploads/2024/07/glucose_q-1024x676.jpg" alt="" class="wp-image-2132" srcset="https://tantusdata.com/app/uploads/2024/07/glucose_q-1024x676.jpg 1024w, https://tantusdata.com/app/uploads/2024/07/glucose_q-300x198.jpg 300w, https://tantusdata.com/app/uploads/2024/07/glucose_q-768x507.jpg 768w, https://tantusdata.com/app/uploads/2024/07/glucose_q-1536x1014.jpg 1536w, https://tantusdata.com/app/uploads/2024/07/glucose_q-2048x1352.jpg 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>Good? The answer is just &#8220;A&#8221;, so even though the model gets it, automatic evaluation would score it as a failure!</p>



<p>Without doing a deep dive into how the evaluation is actually done, there is an excellent&nbsp;<a target="_blank" href="https://huggingface.co/blog/evaluating-mmlu-leaderboard" rel="noreferrer noopener">blog</a>&nbsp;on HuggingFace explaining it in detail; you should just know that it requires taking bare following tokens&#8217; probabilities and using the model through code in a different way than you would interact with it through chat on some WebUI.</p>



<p>So, the key takeaway is that while those benchmarks provide us with a general ranking of models&#8217; performance, one should pay close attention to how they are evaluated and whether this form of evaluation is meaningful for their use case.&nbsp;</p>



<p>For example, ChatGPT is a so-called Instruction-Finetuned model tuned to follow user instructions and interact with them. If you put a phrase:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Can you help me with that:<br>{arbitrary problem description}</p>
</blockquote>



<p>It will very likely start it’s response with:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Certainly! {probably a good solution to your problem}</p>
</blockquote>



<p>And if you were to check tokens probabilities for options A, B, C, and D from the above-mentioned MMLU example, as it is done in one implementation of MMLU, you would get C! But not because the model thinks the completion for the</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Correct answer</p>
</blockquote>



<p>Is C, but because it wants to start with Certainly!</p>



<h2 class="wp-block-heading"><strong>Deployment options</strong></h2>



<p>Last but not least, let&#8217;s talk about inference. When you have chosen and maybe even fine-tuned your model further, it&#8217;s time to answer the question of what exactly you want to deploy and where.</p>



<p>The &#8216;what exactly&#8217; part is essential. To start with, you probably have X billion parameters model in (b)float16. There are two options for improvement here: quantization and pruning.</p>



<p>Quantization converts some 16-bit weights into 8 or 4 bits so you can run the model on a smaller and cheaper GPU. Of course, by doing so, we lose some information and accuracy. It can be done automatically using some general formulas, or you can specify an evaluation dataset to quantize in a way that reduces some metrics the least.</p>



<p>It is important to note that currently, on most hardware, quantization reduces memory usage but reduces inference speed. Although the model weights are much smaller, some values must be cast back and forth. But it allows you to inference/fine-tune the model on cheaper hardware or just the available hardware since it might be hard for new players to get access to A100 &amp; H100 clusters.</p>



<p>Both ways are available in the HuggingFace library and can be easily applied.&nbsp;<a target="_blank" href="https://huggingface.co/blog/overview-quantization-transformers" rel="noreferrer noopener">Here</a>, you can find the blog post going through their pros and cons and inference speed/memory comparison.</p>



<p>Pruning, on the other hand, works by completely removing some weights from the model.</p>



<p>It is important to remember that the transformer model under the hood does matrix multiplication, so you can just remove all entries close to zero and expect the performance to improve because it will cause some non-sequential memory accesses. A more gentle solution is needed. The PyTorch team has recently posted 2&nbsp;<a href="https://pytorch.org/blog/accelerating-generative-ai/" target="_blank" rel="noreferrer noopener">blog posts</a>&nbsp;about accelerating Generativ-AI, where they go into detail about available options.</p>



<h2 class="wp-block-heading">Where to deploy?</h2>



<p>Though for real-time chat applications, data centre deployment or on-premise, with high availability, there are some cost-saving techniques if you have offline steps in your data pipeline.</p>



<p>Currently, everyone runs LLM models on either A10 or A100 / H100, but surprisingly, not so many people know that cards from the RTX family are also a good performance choice for such applications.</p>



<p>Unfortunately, NVIDIA knows that, and they put the following statements in their license.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>No Datacenter Deployment. The SOFTWARE is not licensed for datacenter deployment, except that blockchain processing in a datacenter is permitted.</p>
</blockquote>



<p>But there are companies like&nbsp;<a href="https://vast.ai/" target="_blank" rel="noreferrer noopener">vast.ai</a>&nbsp;which offer RTX cards but with lower reliability than, for example, AWS ec2 instances, which you can use for offline data processing. The default filter for availability here is set to 90%, while on the AWS EC2 Service Level Agreement, commitment is 99.99%.</p>
<p>The post <a href="https://tantusdata.com/insights/what-to-know-before-deploying-open-source-llm/">What you need to know before deploying Open Source LLM</a> appeared first on <a href="https://tantusdata.com">TantusData</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>RDD in Apache Spark</title>
		<link>https://tantusdata.com/insights/rdd-in-apache-spark/</link>
		
		<dc:creator><![CDATA[Amadeusz Kosik]]></dc:creator>
		<pubDate>Fri, 28 Jun 2024 07:33:40 +0000</pubDate>
				<category><![CDATA[Apache Spark]]></category>
		<category><![CDATA[data pipelines]]></category>
		<guid isPermaLink="false">https://tantusdata.com/?post_type=insights&#038;p=2128</guid>

					<description><![CDATA[<p>Learn how to utilize the RDD API in Apache Spark to check partition details or perform low-level operations. Despite being deprecated, the RDD API is accessible via the .rdd method on Datasets and DataFrames. Discover how to check the number of partitions with the getNumPartitions method and determine partition sizes using the glom function. Explore the remaining useful operations that RDD API offers for low-level hacking and internal Spark tasks.</p>
<p>The post <a href="https://tantusdata.com/insights/rdd-in-apache-spark/">RDD in Apache Spark</a> appeared first on <a href="https://tantusdata.com">TantusData</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="512" src="https://tantusdata.com/app/uploads/2024/06/shutterstock_2419641841-1024x512.jpg" alt="" class="wp-image-2185" srcset="https://tantusdata.com/app/uploads/2024/06/shutterstock_2419641841-1024x512.jpg 1024w, https://tantusdata.com/app/uploads/2024/06/shutterstock_2419641841-300x150.jpg 300w, https://tantusdata.com/app/uploads/2024/06/shutterstock_2419641841-768x384.jpg 768w, https://tantusdata.com/app/uploads/2024/06/shutterstock_2419641841-1536x768.jpg 1536w, https://tantusdata.com/app/uploads/2024/06/shutterstock_2419641841-2048x1024.jpg 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>Do you want to see the number of partitions? Or the partition size in rows from within the job? Or maybe you just like some low-level hacking? The RDD API is still there and accessible via the <em>.rdd</em> method.&nbsp;</p>



<h2 class="wp-block-heading">Why is RDD API still around?</h2>



<p>Despite deprecating the RDD API, the engine of Apache Spark (at least its Open Source part &#8211; see our article on Photon), the RDDs are still used in its internals. It is also available via the .<em>rdd</em> method of <em>Datasets</em>, and, therefore, <em>DataFrames</em> as well. Keep in mind, though, that the number of actually useful operations not available from Dataset API is really low, and currently, excluding some low-level or Spark internals hacking, it boils down to partitions count and size checking &#8211; using getNumPartitions method or glom operator, respectively.</p>



<h2 class="wp-block-heading">Check number of partitions</h2>



<p>RDD API still keeps the <a href="https://spark.apache.org/docs/3.2.0/api/scala/org/apache/spark/rdd/RDD.html#getNumPartitions:Int"><em>getNumPartitions</em></a> method for that use case:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="println(inputData.rdd.getNumPartitions)" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">println</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">inputData</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">rdd</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">getNumPartitions</span><span style="color: #D8DEE9FF">)</span></span></code></pre></div>



<p></p>



<h2 class="wp-block-heading">Check number of rows per partition</h2>



<p>The <a href="https://spark.apache.org/docs/3.2.0/api/scala/org/apache/spark/rdd/RDD.html#glom():org.apache.spark.rdd.RDD[Array[T]]"><em>glom</em></a> function coalesces all rows in each partition into an array. It can be used to check the number of rows per partition. In the case of wide rows, consider using <em>select</em> to limit the number of columns—RDD are not optimized by most of Spark’s mechanisms.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="inputData.rdd.glom().map(_.length).collect().foreach(println _)" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">inputData</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">rdd</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">glom</span><span style="color: #D8DEE9FF">()</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">map</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">_</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">length)</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">collect</span><span style="color: #D8DEE9FF">()</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">foreach</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">println</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">_</span><span style="color: #D8DEE9FF">)</span></span></code></pre></div>
<p>The post <a href="https://tantusdata.com/insights/rdd-in-apache-spark/">RDD in Apache Spark</a> appeared first on <a href="https://tantusdata.com">TantusData</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Datasets and DataFrames</title>
		<link>https://tantusdata.com/insights/dtasets-and-dataframes/</link>
		
		<dc:creator><![CDATA[Amadeusz Kosik]]></dc:creator>
		<pubDate>Tue, 11 Jun 2024 06:41:52 +0000</pubDate>
				<category><![CDATA[Apache Spark]]></category>
		<category><![CDATA[data pipelines]]></category>
		<guid isPermaLink="false">https://tantusdata.com/?post_type=insights&#038;p=2105</guid>

					<description><![CDATA[<p>Understanding Spark's .as[T] Method: Best Practices and Defensive Programming</p>
<p>The post <a href="https://tantusdata.com/insights/dtasets-and-dataframes/">Datasets and DataFrames</a> appeared first on <a href="https://tantusdata.com">TantusData</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="576" src="https://tantusdata.com/app/uploads/2024/06/shutterstock_2301467093-1024x576.jpg" alt="" class="wp-image-2106" srcset="https://tantusdata.com/app/uploads/2024/06/shutterstock_2301467093-1024x576.jpg 1024w, https://tantusdata.com/app/uploads/2024/06/shutterstock_2301467093-300x169.jpg 300w, https://tantusdata.com/app/uploads/2024/06/shutterstock_2301467093-768x432.jpg 768w, https://tantusdata.com/app/uploads/2024/06/shutterstock_2301467093-1536x864.jpg 1536w, https://tantusdata.com/app/uploads/2024/06/shutterstock_2301467093-2048x1152.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>With the deprecation of the public use of the old good RDD API, Spark users are left with two options: typed <em>Datasets</em>and untyped <em>DataFrames </em>(that are actually a specific case of Datasets). The API also allows users to freely cast one to another &#8211; e.g. using the <em>.as[T]</em> method to cast an untyped <em>DataFrame</em> to a <em>Dataset[T]</em>. It does not change the underlying data though and can result in surprising results if one is not aware of that.</p>



<h2 class="wp-block-heading">What does <em>.as[T]</em> do?</h2>



<p>Let’s start by looking at the source (code):</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="Returns a new Dataset where each record has been mapped on to the specified type. The method used to map columns depend on the type of U:
When U is a class, fields for the class will be mapped to columns of the same name (case sensitivity is determined by spark. sql. caseSensitive).
When U is a tuple, the columns will be mapped by ordinal (i. e. the first column will be assigned to _1).
When U is a primitive type (i. e. String, Int, etc), then the first column of the DataFrame will be used.
If the schema of the Dataset does not match the desired U type, you can use select along with alias or as to rearrange or rename as required.
Note that as[] only changes the view of the data that is passed into typed operations, such as map(), and does not eagerly project away any columns that are not present in the specified class.
Since:
1.6.0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">Returns</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Dataset</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">where</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">each</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">record</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">has</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">been</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">mapped</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">on</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">to</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">specified</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">type</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">The</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">method</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">used</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">to</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">map</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">columns</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">depend</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">on</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">type</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">of</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">U</span><span style="color: #D8DEE9FF">:</span></span>
<span class="line"><span style="color: #D8DEE9">When</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">U</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">is</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">class</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">fields</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">class</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">will</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">be</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">mapped</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">to</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">columns</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">of</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">same</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">name</span><span style="color: #D8DEE9FF"> (</span><span style="color: #8FBCBB">case</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">sensitivity</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">is</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">determined</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">by</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">spark</span><span style="color: #D8DEE9FF">. </span><span style="color: #8FBCBB">sql</span><span style="color: #D8DEE9FF">. </span><span style="color: #8FBCBB">caseSensitive</span><span style="color: #D8DEE9FF">).</span></span>
<span class="line"><span style="color: #8FBCBB">When</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">U</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">is</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">a</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">tuple</span><span style="color: #D8DEE9FF">, </span><span style="color: #8FBCBB">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">columns</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">will</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">be</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">mapped</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">by</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">ordinal</span><span style="color: #D8DEE9FF"> (</span><span style="color: #8FBCBB">i</span><span style="color: #D8DEE9FF">. </span><span style="color: #8FBCBB">e</span><span style="color: #D8DEE9FF">. </span><span style="color: #8FBCBB">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">first</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">column</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">will</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">be</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">assigned</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">to</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">_1</span><span style="color: #D8DEE9FF">).</span></span>
<span class="line"><span style="color: #8FBCBB">When</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">U</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">is</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">a</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">primitive</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">type</span><span style="color: #D8DEE9FF"> (</span><span style="color: #8FBCBB">i</span><span style="color: #D8DEE9FF">. </span><span style="color: #8FBCBB">e</span><span style="color: #D8DEE9FF">. </span><span style="color: #8FBCBB">String</span><span style="color: #D8DEE9FF">, </span><span style="color: #8FBCBB">Int</span><span style="color: #D8DEE9FF">, </span><span style="color: #8FBCBB">etc</span><span style="color: #D8DEE9FF">), </span><span style="color: #8FBCBB">then</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">first</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">column</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">of</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">DataFrame</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">will</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">be</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">used</span><span style="color: #D8DEE9FF">.</span></span>
<span class="line"><span style="color: #8FBCBB">If</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">schema</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">of</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Dataset</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">does</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">not</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">match</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">desired</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">U</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">type</span><span style="color: #D8DEE9FF">, </span><span style="color: #8FBCBB">you</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">can</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">use</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">select</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">along</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">with</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">alias</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">or</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">as</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">to</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">rearrange</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">or</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">rename</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">as</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">required</span><span style="color: #D8DEE9FF">.</span></span>
<span class="line"><span style="color: #8FBCBB">Note</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">that</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">as</span><span style="color: #D8DEE9FF">[] </span><span style="color: #8FBCBB">only</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">changes</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">view</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">of</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">data</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">that</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">is</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">passed</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">into</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">typed</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">operations</span><span style="color: #D8DEE9FF">, </span><span style="color: #8FBCBB">such</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">as</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">map</span><span style="color: #D8DEE9FF">(), </span><span style="color: #8FBCBB">and</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">does</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">not</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">eagerly</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">project</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">away</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">any</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">columns</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">that</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">are</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">not</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">present</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">in</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">specified</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">class</span><span style="color: #D8DEE9FF">.</span></span>
<span class="line"><span style="color: #8FBCBB">Since</span><span style="color: #D8DEE9FF">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">1.6.0</span></span></code></pre></div>



<p></p>



<p>The last note is crucial: casting to a <em>Dataset</em> does not change the underlying data. Any columns not present in the <em>T</em> (e.g., columns without a corresponding field in the case class) will not be discarded.</p>



<h2 class="wp-block-heading">Why bother?</h2>



<p>There are a few situations where having extra columns may be surprising and create problems with a job run (or even worse &#8211; silently introduce data quality issues):</p>



<ul class="wp-block-list">
<li>running <em>union</em> or <em>unionAll</em> transformations on non-aligned data,</li>



<li>calling <em>distinct</em> (it will check for hidden columns’ uniqueness as well),</li>



<li>saving data (will include extra columns).</li>
</ul>



<h2 class="wp-block-heading">A defensive version of <em>.as[T]</em>&nbsp;</h2>



<p>The simple version of a defensive (meaning: adjusting the schema to the provided domain class) would be one with a <em>.select()</em> transformation call:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="case class Artist(id: String, name: String, location: String)

def toArtistsDefensive(input: DataFrame): Dataset[Artist] = { input
  .select(&quot;id&quot;, &quot;name&quot;, &quot;location&quot;)
  .as[Artist]
}" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">class</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Artist</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">id</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">String</span><span style="color: #D8DEE9FF">, </span><span style="color: #8FBCBB">name</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">String</span><span style="color: #D8DEE9FF">, </span><span style="color: #8FBCBB">location</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">String</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">toArtistsDefensive</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">input</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">DataFrame</span><span style="color: #D8DEE9FF">): </span><span style="color: #8FBCBB">Dataset</span><span style="color: #D8DEE9FF">[</span><span style="color: #8FBCBB">Artist</span><span style="color: #D8DEE9FF">] = </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> input</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">select</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">id</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">name</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">location</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">as</span><span style="color: #D8DEE9FF">[</span><span style="color: #D8DEE9">Artist</span><span style="color: #D8DEE9FF">]</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span></code></pre></div>



<p></p>



<p>This is a very DRY-unfriendly implementation, as each modification of the <em>Artists</em> class requires searching for all related <em>select</em> instances and updating them. Fortunately, with a bit of reflection, it can be refactored into a generic solution. This generic transformation will trim the Dataset to contain only the expected columns.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="import scala.reflect.runtime.universe._

def toTDefensive[T &lt;: Product: TypeTag](input: DataFrame): Dataset[T] = { 
  val caseClassFields = typeOf[T].members
    .collect { case m: MethodSymbol if m.isCaseAccessor =&gt; m.name.toString }
    .toSeq
  
  val columns = caseClassFields
    .map(F.col _)
    .reverse

  input
    .select(columns: _*)
    .as[T]
}" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">scala</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">reflect</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">runtime</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">universe</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">_</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">toTDefensive</span><span style="color: #D8DEE9FF">[</span><span style="color: #8FBCBB">T</span><span style="color: #D8DEE9FF"> &lt;: </span><span style="color: #8FBCBB">Product</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">TypeTag</span><span style="color: #D8DEE9FF">](</span><span style="color: #8FBCBB">input</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">DataFrame</span><span style="color: #D8DEE9FF">): </span><span style="color: #8FBCBB">Dataset</span><span style="color: #D8DEE9FF">[</span><span style="color: #8FBCBB">T</span><span style="color: #D8DEE9FF">] = </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #8FBCBB">val</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">caseClassFields</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">typeOf</span><span style="color: #D8DEE9FF">[</span><span style="color: #8FBCBB">T</span><span style="color: #D8DEE9FF">].</span><span style="color: #8FBCBB">members</span></span>
<span class="line"><span style="color: #D8DEE9FF">    .</span><span style="color: #8FBCBB">collect</span><span style="color: #D8DEE9FF"> { </span><span style="color: #8FBCBB">case</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">m</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">MethodSymbol</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">m</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">isCaseAccessor</span><span style="color: #D8DEE9FF"> =&gt; </span><span style="color: #8FBCBB">m</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">name</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">toString</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    .</span><span style="color: #8FBCBB">toSeq</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #8FBCBB">val</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">columns</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">caseClassFields</span></span>
<span class="line"><span style="color: #D8DEE9FF">    .</span><span style="color: #8FBCBB">map</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">F</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">col</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">_</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    .</span><span style="color: #8FBCBB">reverse</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #8FBCBB">input</span></span>
<span class="line"><span style="color: #D8DEE9FF">    .</span><span style="color: #8FBCBB">select</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">columns</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">_</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    .</span><span style="color: #8FBCBB">as</span><span style="color: #D8DEE9FF">[</span><span style="color: #8FBCBB">T</span><span style="color: #D8DEE9FF">]</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span></code></pre></div>



<p></p>
<p>The post <a href="https://tantusdata.com/insights/dtasets-and-dataframes/">Datasets and DataFrames</a> appeared first on <a href="https://tantusdata.com">TantusData</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Monitoring Airflow jobs with TIG 2: data quality metrics</title>
		<link>https://tantusdata.com/insights/monitoring-airflow-jobs-with-tig-2-data-quality-metrics/</link>
		
		<dc:creator><![CDATA[Amadeusz Kosik]]></dc:creator>
		<pubDate>Tue, 30 Apr 2024 13:31:53 +0000</pubDate>
				<category><![CDATA[data pipelines]]></category>
		<category><![CDATA[data quality]]></category>
		<category><![CDATA[monitoring]]></category>
		<guid isPermaLink="false">https://tantusdata.com/?post_type=insights&#038;p=1914</guid>

					<description><![CDATA[<p>In the first article on Monitoring Airflow jobs with TIG, &#8220;System Metrics&#8221;, we have seen an example of Airflow installation with a TIG stack set up to monitor it. To fully utilize this stack, we should enrich the raw system metrics with statistics on the processed data. Without this, the metrics would tell if the [&#8230;]</p>
<p>The post <a href="https://tantusdata.com/insights/monitoring-airflow-jobs-with-tig-2-data-quality-metrics/">Monitoring Airflow jobs with TIG 2: data quality metrics</a> appeared first on <a href="https://tantusdata.com">TantusData</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="585" src="https://tantusdata.com/app/uploads/2024/02/airflow_jobs-1-1024x585.jpg" alt="" class="wp-image-1919" srcset="https://tantusdata.com/app/uploads/2024/02/airflow_jobs-1-1024x585.jpg 1024w, https://tantusdata.com/app/uploads/2024/02/airflow_jobs-1-300x171.jpg 300w, https://tantusdata.com/app/uploads/2024/02/airflow_jobs-1-768x439.jpg 768w, https://tantusdata.com/app/uploads/2024/02/airflow_jobs-1-1536x878.jpg 1536w, https://tantusdata.com/app/uploads/2024/02/airflow_jobs-1.jpg 1792w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>In the first article on Monitoring Airflow jobs with TIG, &#8220;System Metrics&#8221;, we have seen an example of Airflow installation with a TIG stack set up to monitor it. To fully utilize this stack, we should enrich the raw system metrics with statistics on the processed data. Without this, the metrics would tell <em>if</em> the data pipelines are doing anything but not whether they are working on the <em>correct data</em>.</p>



<h2 class="wp-block-heading">What to look for?</h2>



<p>What can be realistically monitored is a pretty deep topic without a one-fits-all answer. The safe starting point is to look for the size of the data, duplicates (or unique rows), null/missing columns’ values and basic aggregates (count per some enumerated type or min/max values). The nice part of this issue is it is not limited by any software, and you can report any numeric value into an InfluxDB database.</p>



<p>Equally important is not limiting the monitoring to the output of the whole pipeline only. Being able to check the data volume and basic traits on the input and in intermediate steps is crucial, as it enables one to check, identify and react to problems early on (and avoid painful backtracking and recomputing of the whole pipeline).</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="515" src="https://tantusdata.com/app/uploads/2024/02/grafana-dashboard-2-1024x515.png" alt="" class="wp-image-1917" srcset="https://tantusdata.com/app/uploads/2024/02/grafana-dashboard-2-1024x515.png 1024w, https://tantusdata.com/app/uploads/2024/02/grafana-dashboard-2-300x151.png 300w, https://tantusdata.com/app/uploads/2024/02/grafana-dashboard-2-768x386.png 768w, https://tantusdata.com/app/uploads/2024/02/grafana-dashboard-2-1536x772.png 1536w, https://tantusdata.com/app/uploads/2024/02/grafana-dashboard-2.png 1999w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">An example data metrics dashboard showing row count, unique row count, and null rows for three steps in the imaginary data pipeline: load, process, and export. It is available to run a local demo on our GitHub.</figcaption></figure>



<h2 class="wp-block-heading">Computing the metrics</h2>



<p>Technically speaking, such monitoring requires two things in the pipeline: a code (or job) to compute the metric and a wrapper to send it to the metrics database. We did not cover the former here &#8211; it may vary from a simple SQL query run via Hive / Impala to a side output of a Spark job.</p>



<h2 class="wp-block-heading">Storing the data for graphs</h2>



<p>The second part to be done in Airflow is sending the data to the database. At the time of writing this article, the built-in InfluxDB connector allows only querying the database. Please see our demo (especially <em>the plugins</em> directory) for an example implementation of InfluxDB write. You can also use the REST API or <em>BashOperator</em> to call the influx command there.</p>



<h2 class="wp-block-heading">Merging both steps or not?</h2>



<p>Both compute and send metrics steps may be squashed into a single bash step instead of scheduling them separately and stitching them via XComs. However, the more complicated or time-consuming the calculation may be, the better the separated approach would seem. This is a decision for you to make; we provide an example of the former approach.</p>



<h2 class="wp-block-heading">Summary</h2>



<p>After the first step, the example stack has monitoring of the system, and an operator can see whether the system is working and does not have an overload or some kind of bottleneck. This step adds a base monitoring of the data quality. Adding those <em>on multiple points </em>in the data pipeline will also enable verification <em>during the processing</em> &#8211; in a centralized place (or, in this case, WebUI). Once again, a development/demo environment is available on our GitHub.</p>
<p>The post <a href="https://tantusdata.com/insights/monitoring-airflow-jobs-with-tig-2-data-quality-metrics/">Monitoring Airflow jobs with TIG 2: data quality metrics</a> appeared first on <a href="https://tantusdata.com">TantusData</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Monitoring Airflow jobs with TIG 1: system metrics</title>
		<link>https://tantusdata.com/insights/monitoring-airflow-jobs-with-tig-1-system-metrics/</link>
		
		<dc:creator><![CDATA[Amadeusz Kosik]]></dc:creator>
		<pubDate>Tue, 16 Apr 2024 10:25:34 +0000</pubDate>
				<category><![CDATA[Apache Airflow]]></category>
		<category><![CDATA[data pipelines]]></category>
		<category><![CDATA[devops]]></category>
		<category><![CDATA[monitoring]]></category>
		<category><![CDATA[sysops]]></category>
		<guid isPermaLink="false">https://tantusdata.com/?post_type=insights&#038;p=1907</guid>

					<description><![CDATA[<p>Like many server applications, Airflow can – and should – be monitored for metrics and logs. In this article, we will look into the former and the integration with the TIG stack. The goal is to pull example metrics into a time series database and visualize it in a web application. This article will focus [&#8230;]</p>
<p>The post <a href="https://tantusdata.com/insights/monitoring-airflow-jobs-with-tig-1-system-metrics/">Monitoring Airflow jobs with TIG 1: system metrics</a> appeared first on <a href="https://tantusdata.com">TantusData</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="585" src="https://tantusdata.com/app/uploads/2024/04/Airflow-jobs-with-the-TIG-stack_1-1024x585.jpg" alt="" class="wp-image-2176" srcset="https://tantusdata.com/app/uploads/2024/04/Airflow-jobs-with-the-TIG-stack_1-1024x585.jpg 1024w, https://tantusdata.com/app/uploads/2024/04/Airflow-jobs-with-the-TIG-stack_1-300x171.jpg 300w, https://tantusdata.com/app/uploads/2024/04/Airflow-jobs-with-the-TIG-stack_1-768x439.jpg 768w, https://tantusdata.com/app/uploads/2024/04/Airflow-jobs-with-the-TIG-stack_1-1536x878.jpg 1536w, https://tantusdata.com/app/uploads/2024/04/Airflow-jobs-with-the-TIG-stack_1.jpg 1792w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Like many server applications, Airflow can – and should – be monitored for metrics and logs. In this article, we will look into the former and the integration with the TIG stack. The goal is to pull example metrics into a time series database and visualize it in a web application. This article will focus on AF system metrics, like its performance, load or health. We will cover the topic of reporting the <em>data </em>metrics into the same database in an upcoming article, &#8220;TITLE&#8221;. So, stay tuned.&nbsp;</p>



<h2 class="wp-block-heading">Why?</h2>



<p>The Airflow itself finally got a <em>Cluster status</em> dashboard built-in. Therefore, it is valid to question the need for a separate dashboard that requires additional effort and maintenance. Why bother, then? There are several possible reasons to introduce a separate monitoring stack:</p>



<ul class="wp-block-list">
<li>Aggregated view: looking into one app is easier than browsing through 10 of them. TIG (or any other monitoring stack) can be used for monitoring multiple instances and apps and is easily integrated with custom ones.</li>
</ul>



<ul class="wp-block-list">
<li>Security: there is no need to give access to the AF itself (or any other application) to be able to see the metrics and pinpoint errors. It is aligned with the data mesh and any other data democratization approach.</li>



<li>Support friendly: your 1st line support has a starting point to check the status of the data processing and be able to call the right people in case of a problem.</li>
</ul>



<h2 class="wp-block-heading">The toolkit</h2>



<p>Out of the box (but with the right pip packages) Airflow supports sending its internal metrics to a statsd server. We can leverage that and set up such a server via <em>Telegraf</em> to proxy the metrics further into a time series database: InfluxDB. As a convenient UI, Grafana can be used.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1001" height="446" src="https://tantusdata.com/app/uploads/2024/02/example-architecture.png" alt="" class="wp-image-1910" srcset="https://tantusdata.com/app/uploads/2024/02/example-architecture.png 1001w, https://tantusdata.com/app/uploads/2024/02/example-architecture-300x134.png 300w, https://tantusdata.com/app/uploads/2024/02/example-architecture-768x342.png 768w" sizes="auto, (max-width: 1001px) 100vw, 1001px" /></figure>



<h2 class="wp-block-heading">TIG stack configuration</h2>



<p>Firstly, let’s configure the TIG stack to accept the metrics:</p>



<ol class="wp-block-list">
<li>Install an InfluxDB instance. Nothing fancy here.</li>



<li>Install the Telegraf. In the configuration, look for the <em>statsd</em> input (which has to be enabled) and <em>InfluxDB </em>output. The latter will require at least authentication. Note that the Telegraf supports many more inputs and allows monitoring of, e.g. system resources (CPU, memory, disk space, etc.). This is a good idea to configure in a production environment.</li>



<li>Install Grafana and configure the <em>data source</em> to point it to the InfluxDB.</li>
</ol>



<p></p>



<p>We have prepared a docker compose-based demo in the GitHub repository with a pre-configured environment. You can see there the example configuration for Telegraf (<em>telegraf.conf</em>), InfluxDB (<em>influxdb.env</em>) and Grafana (<em>grafana-provisioning/datasources</em>). Please note that this is only for dev/demo purposes, and real production environments need to be set up more securely (including the use of HTTPS and secure password handling).</p>



<h2 class="wp-block-heading">Airflow</h2>



<p>On the Airflow side, there are two significant points to be addressed.</p>



<ol class="wp-block-list">
<li>Airflow requires the <em>Apache-airflow [statsd]</em> package to have the <em>statsd </em>client available – you can do it via pip.</li>



<li>In the airflow configuration file (usually: <em>Airflow.cfg</em>), the <em>[metrics]</em> section must be configured to enable the <em>statsd</em>, point it to the Telegraf instance and prefix the metrics (very useful in case of multiple Airflow instances).</li>
</ol>



<p>There are several metrics available to be sent in Airflow. You can see the complete list in the Airflow documentation <a href="https://airflow.apache.org/docs/apache-airflow/stable/administration-and-deployment/logging-monitoring/metrics.html">here</a>. There, you can also limit which ones are actually reported to the Telegraf. Be aware that even though most of the metrics are said to be reported in seconds, you need to validate them yourself (<a href="https://github.com/apache/airflow/issues/20804">as in this example</a>).</p>



<h2 class="wp-block-heading">Dashboards</h2>



<p>The last step is to configure Grafana and set up some dashboards. The UI offers a WYSIWYG editor that you can use to tailor it to <em>your</em> needs. The example available on the GitHub might serve as a starting point, as it shows:</p>



<ul class="wp-block-list">
<li>state of the Airflow executors (queues and tasks being run at the moment) to see whether any processing is going on,</li>



<li>state of the pools (default and the custom ones) to check potential bottlenecks if you use multiple pools,</li>



<li>task times to identify unexpected stragglers (and compare instances’ run times and find any performance challenges early on).</li>
</ul>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="532" src="https://tantusdata.com/app/uploads/2024/02/grafana-dashboard-1024x532.png" alt="" class="wp-image-1912" srcset="https://tantusdata.com/app/uploads/2024/02/grafana-dashboard-1024x532.png 1024w, https://tantusdata.com/app/uploads/2024/02/grafana-dashboard-300x156.png 300w, https://tantusdata.com/app/uploads/2024/02/grafana-dashboard-768x399.png 768w, https://tantusdata.com/app/uploads/2024/02/grafana-dashboard-1536x798.png 1536w, https://tantusdata.com/app/uploads/2024/02/grafana-dashboard.png 1999w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">An example dashboard, available on our GitHub. It contains metrics useful to monitor the load on the Airflow instance and identify potential overload or bottlenecks in the data pipeline processing.</figcaption></figure>



<h2 class="wp-block-heading">Summary</h2>



<p>In conclusion, for Airflow monitoring, you can use specialized metrics tools like TIG stack and aggregate all the metrics from multiple AF instances. The stack can accommodate AF system metrics and data from other applications, including your custom ones. An example of sending data quality metrics is what we will look into in the second part. There is a demo environment on our GitHub to see whether this works for you.</p>
<p>The post <a href="https://tantusdata.com/insights/monitoring-airflow-jobs-with-tig-1-system-metrics/">Monitoring Airflow jobs with TIG 1: system metrics</a> appeared first on <a href="https://tantusdata.com">TantusData</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Databricks &#8211; Photon</title>
		<link>https://tantusdata.com/insights/databricks-photon/</link>
		
		<dc:creator><![CDATA[Amadeusz Kosik]]></dc:creator>
		<pubDate>Tue, 02 Apr 2024 12:52:56 +0000</pubDate>
				<category><![CDATA[Apache Airflow]]></category>
		<category><![CDATA[DAG dependencies]]></category>
		<category><![CDATA[data pipelines]]></category>
		<category><![CDATA[job orchestration]]></category>
		<guid isPermaLink="false">https://tantusdata.com/?post_type=insights&#038;p=1903</guid>

					<description><![CDATA[<p>The Databricks platform offers two execution engines for the clients: the standard Apache Spark (available as an open-source application) and one with Photon enhancement that brings a performance improvement (as well as extra pricing). Have you ever wondered where this speedup comes from and how it affects designing Apache Spark jobs? This article is based [&#8230;]</p>
<p>The post <a href="https://tantusdata.com/insights/databricks-photon/">Databricks &#8211; Photon</a> appeared first on <a href="https://tantusdata.com">TantusData</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="585" src="https://tantusdata.com/app/uploads/2024/04/improving_performance_1-1024x585.jpg" alt="" class="wp-image-2178" srcset="https://tantusdata.com/app/uploads/2024/04/improving_performance_1-1024x585.jpg 1024w, https://tantusdata.com/app/uploads/2024/04/improving_performance_1-300x171.jpg 300w, https://tantusdata.com/app/uploads/2024/04/improving_performance_1-768x439.jpg 768w, https://tantusdata.com/app/uploads/2024/04/improving_performance_1-1536x878.jpg 1536w, https://tantusdata.com/app/uploads/2024/04/improving_performance_1.jpg 1792w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The Databricks platform offers two execution engines for the clients: the standard Apache Spark (available as an open-source application) and one with Photon enhancement that brings a performance improvement (as well as extra pricing). Have you ever wondered where this speedup comes from and how it affects designing Apache Spark jobs?</p>



<p>This article is based on Berlkey’s paper on Photon by Databricks people, as that publication is the closest to the source, as the Photon engine is not an open-source project, and its source code is not available to the public.</p>



<h2 class="wp-block-heading">The general idea</h2>



<p>In a nutshell, Photon replaces the standard (bundled) query engine available in Apache Spark, using the same API. For some operations, mostly CPU-heavy ones, the Catalyst optimizer may decide to send the job to Photon instead of using the default execution path, all for performance reasons. In other words, it is an alternative way to execute Spark DAG tasks, not skipping/reordering/reorganizing the data engine.</p>



<h2 class="wp-block-heading">SIMD</h2>



<p>The SIMD stands for <em>Single Instruction, Multiple Data</em> and is one of the ground ideas for job optimisations in Photon. With current architectures running the same operation on multiple instances (values, rows, etc.), data can be optimised via <em>vectorisation</em>, even within a single thread. Photon is said to utilise those optimisations.</p>



<h2 class="wp-block-heading">C++ and Code generation</h2>



<p>The Photon engine is implemented in C++ instead of the JVM native languages (Scala, Java or others). The source paper points to performance reasons, including ‘hitting performance ceilings’. The communication with the rest of the Apache Spark is implemented via JNI. Databricks’ internal benchmarks indicate that the performance hit due to moving data in and out of JVM is not noticeable.&nbsp;</p>



<h2 class="wp-block-heading">Internal data format</h2>



<p>Photon engine uses columnar data representation (same as, e.g. Parquet data format) instead of row data (like the rest of Apache Spark). This is due to SIMD optimizations – kernel implementation that works best on columnar data. The memory management (calling, freeing, etc) is still done via Apache Spark’s memory manager. The data is kept off-heap, so transferring from Photon to Spark does not require copying the data.</p>



<p>When a shuffle operation is necessary, Photon writes a shuffle file and uses Spark API to execute the exchange. However, the data format is not compatible with vanilla spark, and a Photon shuffle read must follow the Photon shuffle write.</p>



<h2 class="wp-block-heading">When does it help?</h2>



<p>Photon is meant to address the CPU-heavy loads. This includes joins (especially hash join) and aggregations. On the other hand, being a non-JVM implementation, Photon obviously does not support UDFs or RDD API. Exact benchmarks and precise speedups are mentioned in the source paper.</p>



<h2 class="wp-block-heading">Sources</h2>



<ul class="wp-block-list">
<li>Source paper: <a href="https://people.eecs.berkeley.edu/~matei/papers/2022/sigmod_photon.pdf">Photon: A Fast Query Engine for Lakehouse Systems</a></li>
</ul>



<p>I hope this helps. Moreover, if you know any other good sources, do let us know on social media so that everyone can see them.</p>
<p>The post <a href="https://tantusdata.com/insights/databricks-photon/">Databricks &#8211; Photon</a> appeared first on <a href="https://tantusdata.com">TantusData</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Airflow — pools and mutexes.</title>
		<link>https://tantusdata.com/insights/airflow-pools-and-mutexes/</link>
		
		<dc:creator><![CDATA[Amadeusz Kosik]]></dc:creator>
		<pubDate>Tue, 19 Mar 2024 13:47:32 +0000</pubDate>
				<category><![CDATA[Apache Airflow]]></category>
		<category><![CDATA[DAG dependencies]]></category>
		<category><![CDATA[data pipelines]]></category>
		<category><![CDATA[job orchestration]]></category>
		<guid isPermaLink="false">https://tantusdata.com/?post_type=insights&#038;p=1898</guid>

					<description><![CDATA[<p>Although the ideal data pipeline is made of idempotent and independent tasks, there are some cases when setting up a mutex (a.k.a. part of the job that cannot be run concurrently) is necessary. Fortunately, Airflow supports such cases and offers a few tools varying by complexity to implement such a pipeline. In this article, we [&#8230;]</p>
<p>The post <a href="https://tantusdata.com/insights/airflow-pools-and-mutexes/">Airflow — pools and mutexes.</a> appeared first on <a href="https://tantusdata.com">TantusData</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="585" src="https://tantusdata.com/app/uploads/2024/03/airflow-1024x585.png" alt="" class="wp-image-2180" srcset="https://tantusdata.com/app/uploads/2024/03/airflow-1024x585.png 1024w, https://tantusdata.com/app/uploads/2024/03/airflow-300x171.png 300w, https://tantusdata.com/app/uploads/2024/03/airflow-768x439.png 768w, https://tantusdata.com/app/uploads/2024/03/airflow-1536x878.png 1536w, https://tantusdata.com/app/uploads/2024/03/airflow.png 1792w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Although the ideal data pipeline is made of idempotent and independent tasks, there are some cases when setting up a mutex (a.k.a. part of the job that cannot be run concurrently) is necessary. Fortunately, Airflow supports such cases and offers a few tools varying by complexity to implement such a pipeline.</p>



<p>In this article, we will look at the following DAG in AF. The graph itself is relatively simple; the catch is that <em>load_1 </em>and <em>load_2</em> operators cannot have concurrently running task instances. We will look at treating loads separately and looking at them as a group.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="408" src="https://tantusdata.com/app/uploads/2024/02/Airflow-DAG-1024x408.png" alt="" class="wp-image-1899" srcset="https://tantusdata.com/app/uploads/2024/02/Airflow-DAG-1024x408.png 1024w, https://tantusdata.com/app/uploads/2024/02/Airflow-DAG-300x120.png 300w, https://tantusdata.com/app/uploads/2024/02/Airflow-DAG-768x306.png 768w, https://tantusdata.com/app/uploads/2024/02/Airflow-DAG-1536x612.png 1536w, https://tantusdata.com/app/uploads/2024/02/Airflow-DAG.png 1586w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Therefore, there are three scenarios we will look into:</p>



<ol class="wp-block-list">
<li>Only one instance of the operator can be running.</li>



<li>One instance is that the operator cannot run before the older ones are successful.</li>



<li>Only one instance of a group of operators.</li>
</ol>



<p>The examples are using annotation syntax for Airflow. Still, the concept stays the same for the 1.0 compatible approach – instead of annotation params, use them in any <em>Operator</em> class constructor.</p>



<h2 class="wp-block-heading">Mutex on an operator</h2>



<p>The first scenario is that only one operator instance can be running at a time. If there are multiple runs ready to be scheduled, it does not matter which one goes first. One solution would be using the <em>max_active_tis_per_dag</em> option with the value of 1.&nbsp;</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="@task(
   max_active_tis_per_dag=1
)" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D08770">@task</span><span style="color: #D8DEE9FF">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">   </span><span style="color: #D08770">max_active_tis_per_dag</span><span style="color: #81A1C1">=</span><span style="color: #B48EAD">1</span></span>
<span class="line"><span style="color: #D8DEE9FF">)</span></span></code></pre></div>



<p></p>



<h2 class="wp-block-heading">Dependency on past runs</h2>



<p>The second example assumes that the <em>nth</em> batch cannot start before <em>the nth-1</em> one is completed successfully (or at least marked so in Airflow). For this use case, AF offers <em>depends_on_past</em> flag. In this case, you have to be careful and pay some attention to the state of the latest runs. One failed, upstream-failed, <em>or </em>waiting task can halt all future DAG runs.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="@task(
   depends_on_past=True
)" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D08770">@task</span><span style="color: #D8DEE9FF">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">   </span><span style="color: #D08770">depends_on_past</span><span style="color: #81A1C1">=</span><span style="color: #D08770">True</span></span>
<span class="line"><span style="color: #D8DEE9FF">)</span></span></code></pre></div>



<p></p>



<h2 class="wp-block-heading">Pools &#8211; mutex across multiple operators</h2>



<p>The most complex approach is required if we need to group multiple operators to make them share a mutex. One way to do it is to put them into one custom pool and limit it to accommodate only one task simultaneously – either by setting a pool with 1 slot or assigning a high number of required slots to each operator.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="load_pool = Pool.create_or_update_pool(
   name=&quot;load_pool&quot;,
   slots=1,
   description=&quot;Pool for data load tasks.&quot;
)" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">load_pool</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Pool</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">create_or_update_pool</span><span style="color: #D8DEE9FF">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">   </span><span style="color: #D8DEE9">name</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">load_pool</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">   </span><span style="color: #D8DEE9">slots</span><span style="color: #81A1C1">=</span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">   </span><span style="color: #D8DEE9">description</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Pool for data load tasks.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">)</span></span></code></pre></div>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="@task(
   pool=load_pool.pool
)" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D08770">@task</span><span style="color: #D8DEE9FF">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">   </span><span style="color: #D08770">pool</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9">load_pool</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">pool</span></span>
<span class="line"><span style="color: #D8DEE9FF">)</span></span></code></pre></div>



<p></p>



<h2 class="wp-block-heading">Source</h2>



<p>The source code for all examples and the docker environment to run them is available on GitHub.</p>
<p>The post <a href="https://tantusdata.com/insights/airflow-pools-and-mutexes/">Airflow — pools and mutexes.</a> appeared first on <a href="https://tantusdata.com">TantusData</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Passing information between DAGs in Airflow.</title>
		<link>https://tantusdata.com/insights/passing-information-between-dags-in-airflow/</link>
		
		<dc:creator><![CDATA[Amadeusz Kosik]]></dc:creator>
		<pubDate>Thu, 08 Feb 2024 13:34:54 +0000</pubDate>
				<category><![CDATA[Apache Airflow]]></category>
		<category><![CDATA[DAG dependencies]]></category>
		<category><![CDATA[data pipelines]]></category>
		<category><![CDATA[job orchestration]]></category>
		<guid isPermaLink="false">https://tantusdata.com/?post_type=insights&#038;p=1893</guid>

					<description><![CDATA[<p>There are data pipelines where you must pass some values between tasks &#8211; not complete datasets, but ~ kilobytes. This can be managed even within the Airflow itself. As always, multiple options are available &#8211; let’s review some of them. In this article, we are looking at sharing data between DAGs, which are connected via [&#8230;]</p>
<p>The post <a href="https://tantusdata.com/insights/passing-information-between-dags-in-airflow/">Passing information between DAGs in Airflow.</a> appeared first on <a href="https://tantusdata.com">TantusData</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="585" src="https://tantusdata.com/app/uploads/2024/02/dependencies_1-1024x585.jpg" alt="" class="wp-image-2182" srcset="https://tantusdata.com/app/uploads/2024/02/dependencies_1-1024x585.jpg 1024w, https://tantusdata.com/app/uploads/2024/02/dependencies_1-300x171.jpg 300w, https://tantusdata.com/app/uploads/2024/02/dependencies_1-768x439.jpg 768w, https://tantusdata.com/app/uploads/2024/02/dependencies_1-1536x878.jpg 1536w, https://tantusdata.com/app/uploads/2024/02/dependencies_1.jpg 1792w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>There are data pipelines where you must pass some values between tasks &#8211; not complete datasets, but ~ kilobytes. This can be managed even within the Airflow itself. As always, multiple options are available &#8211; let’s review some of them.</p>



<p>In this article, we are looking at sharing data between DAGs, which are connected via run dependencies. Let’s assume that each DAG needs to be run daily, and the first DAG generates some important data for the second DAG.&nbsp;</p>



<h2 class="wp-block-heading">XCom</h2>



<p>XCom would be the first and the recommended approach. It works well with out-of-the-box features like ExternalTaskSensor:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="with DAG(
       dag_id=&quot;xcom-sink&quot;,
       schedule_interval=&quot;@daily&quot;,
       start_date=datetime(2023, 7, 1),
       catchup=True,
) as xcom_sink:
   ExternalTaskSensor(
       task_id=&quot;wait-for-dependency&quot;,
       external_dag_id=&quot;xcom-source&quot;,
       external_task_id=&quot;update-hive-table-events-triggers&quot;
   ) &gt;&gt; BashOperator(
       task_id=&quot;show-xcom&quot;,
       bash_command=&quot;echo {{ ti.xcom_pull(dag_id='xcom-source', task_ids='update-hive-table-events-triggers') }}&quot;
   )" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">with</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">DAG</span><span style="color: #D8DEE9FF">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">       </span><span style="color: #D8DEE9">dag_id</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">xcom-sink</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">       </span><span style="color: #D8DEE9">schedule_interval</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">@daily</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">       </span><span style="color: #D8DEE9">start_date</span><span style="color: #81A1C1">=</span><span style="color: #88C0D0">datetime</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">2023</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">7</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">       </span><span style="color: #D8DEE9">catchup</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9">True</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> xcom_sink:</span></span>
<span class="line"><span style="color: #D8DEE9FF">   </span><span style="color: #88C0D0">ExternalTaskSensor</span><span style="color: #D8DEE9FF">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">       </span><span style="color: #D8DEE9">task_id</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">wait-for-dependency</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">       </span><span style="color: #D8DEE9">external_dag_id</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">xcom-source</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">       </span><span style="color: #D8DEE9">external_task_id</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">update-hive-table-events-triggers</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">   ) </span><span style="color: #81A1C1">&gt;&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">BashOperator</span><span style="color: #D8DEE9FF">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">       </span><span style="color: #D8DEE9">task_id</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">show-xcom</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">       </span><span style="color: #D8DEE9">bash_command</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">echo {{ ti.xcom_pull(dag_id=&#39;xcom-source&#39;, task_ids=&#39;update-hive-table-events-triggers&#39;) }}</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">   )</span></span></code></pre></div>



<p></p>



<h2 class="wp-block-heading">XCom vs run id</h2>



<p>The XCom is identified by the DAG ID, task ID and run ID. If you want to run a single DAG with a custom run ID, you have to ensure there is an XCom value for that run ID already created. This complicates issuing manual runs.</p>



<h2 class="wp-block-heading">When not to XCom?</h2>



<p>Rather than discussing cases that are tailored to use XCom, let’s focus on examples that are not well supported. Basically, XCom does not work well with Datasets, and you might get some quirky results here: <a href="https://github.com/apache/airflow/discussions/33069">https://github.com/apache/airflow/discussions/33069</a>.&nbsp;</p>



<p>With datasets, you need to refer to the <em>last past value</em> of XCom, effectively losing all benefits of tight coupling. Using that parameter, you will need to deal with race conditions: if the not-latest sink DAG is restarted, it will receive an incorrect value from the source. Moreover, let’s consider a design with multiple sources and a single sink:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="475" src="https://tantusdata.com/app/uploads/2024/02/example-dag-1024x475.png" alt="" class="wp-image-1894" srcset="https://tantusdata.com/app/uploads/2024/02/example-dag-1024x475.png 1024w, https://tantusdata.com/app/uploads/2024/02/example-dag-300x139.png 300w, https://tantusdata.com/app/uploads/2024/02/example-dag-768x357.png 768w, https://tantusdata.com/app/uploads/2024/02/example-dag-1536x713.png 1536w, https://tantusdata.com/app/uploads/2024/02/example-dag.png 1999w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Suppose the <em>events</em> dataset gets updated twice and <em>the users&#8217;</em> dataset only once. In that case, the <em>events-with-users</em> will receive only the latest value of the former one. It is up to you to decide whether this behaviour is expected or unacceptable.</p>



<h2 class="wp-block-heading">Variables</h2>



<p>In rare cases, you can use <em>Variables</em> from Airflow to solve the issue. <em>Variables</em> are built-in mechanisms in Airflow that provide a global state (or configuration) for all DAGs to read and write. You can use it to implement <a href="https://java-design-patterns.com/patterns/registry/"><em>the Registry</em> code pattern</a>:</p>



<ol class="wp-block-list">
<li>Put a hashmap of <em>the date of run -&gt; metadata</em> into a variable</li>



<li>Use the <em>execution date</em> (named <em>logical_date</em> in the newer versions) as the hashmap key.</li>



<li>Use <em>PythonOperator</em> to update the variable. Read can be done by either Python code or templating.</li>



<li>Use sensors or datasets to schedule DAGs in the correct order.</li>
</ol>



<h2 class="wp-block-heading">Beware!</h2>



<p>Before you go with the variable route, please keep in mind that compared to XComs, variables are way more costly to maintain. You might need to keep track of the variables’ sizes, implement error handling in your <em>PythonOperators</em> and be mindful of any unsolicited changes in the variables’ values.</p>



<h2 class="wp-block-heading">External system?</h2>



<p>There is always an option of using an external data service to synchronise, similarly to using built-in variables. This may come in the form of data paths on HDFS / S3 / other storage, batch load dates in the database or such. However, this solution creates an inferior design, as you would end up with disadvantages of the variables approach and new implicit dependencies between DAGs and external services.</p>



<h2 class="wp-block-heading">Summary</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><tbody><tr><td><mark style="background-color:rgba(0, 0, 0, 0);color:#c8855a" class="has-inline-color">XCom + dataset</mark></td><td><mark style="background-color:rgba(0, 0, 0, 0);color:#c8855a" class="has-inline-color">XCom + sensor</mark></td><td><mark style="background-color:rgba(0, 0, 0, 0);color:#c8855a" class="has-inline-color">Variables</mark></td><td><mark style="background-color:rgba(0, 0, 0, 0);color:#c8855a" class="has-inline-color">External</mark></td></tr><tr><td>+ no tight coupling between DAGs</td><td>+ supports 1:1 task run relationships</td><td>+ works with both sensors and datasets</td><td>+ works even with 3rd party systems</td></tr><tr><td>&#8211; race conditions,<br><br>&#8211; no guarantee for 1:1 run relationships</td><td>&#8211; a bit tighter coupling<br><br>&#8211; for manual run one must supply by hand the exec_date</td><td>&#8211; handles only data sharing, does not handle orchestration<br><br>&#8211; requires way more effort than XCom</td><td>&#8211; requires even more effort<br><br>&#8211; hidden dependencies outside AF<br><br>&#8211; complicated architecture</td></tr></tbody></table><figcaption class="wp-element-caption">Comparison</figcaption></figure>



<h2 class="wp-block-heading">Source</h2>



<p>The source code for both XCom and <em>Variable</em> examples and the docker environment to run them is available on GitHub.</p>
<p>The post <a href="https://tantusdata.com/insights/passing-information-between-dags-in-airflow/">Passing information between DAGs in Airflow.</a> appeared first on <a href="https://tantusdata.com">TantusData</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>NeMo-Guardrails</title>
		<link>https://tantusdata.com/insights/nvidia-nemo-guardrails-chatbot-development-guide/</link>
		
		<dc:creator><![CDATA[Bartek Sadlej]]></dc:creator>
		<pubDate>Tue, 05 Dec 2023 12:10:04 +0000</pubDate>
				<category><![CDATA[Chatbot Development]]></category>
		<category><![CDATA[Conversational AI]]></category>
		<category><![CDATA[Custom LLM Integration]]></category>
		<category><![CDATA[LLM]]></category>
		<category><![CDATA[Nvidia NeMo-Guardrails]]></category>
		<guid isPermaLink="false">https://tantusdata.com/?post_type=insights&#038;p=1865</guid>

					<description><![CDATA[<p>Building a dedicated chatbot is both challenging and dangerous. At company X, the model should talk about X&#8217;s offer and, ideally, nothing else to save cost, not block throughput, and be sure not to insult anyone. It would also be nice to meet all of those requirements while not sacrificing the chatbot&#8217;s performance. The field [&#8230;]</p>
<p>The post <a href="https://tantusdata.com/insights/nvidia-nemo-guardrails-chatbot-development-guide/">NeMo-Guardrails</a> appeared first on <a href="https://tantusdata.com">TantusData</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="1024" src="https://tantusdata.com/app/uploads/2023/12/circuit-board-patterns-1024x1024.png" alt="" class="wp-image-1866" srcset="https://tantusdata.com/app/uploads/2023/12/circuit-board-patterns-1024x1024.png 1024w, https://tantusdata.com/app/uploads/2023/12/circuit-board-patterns-300x300.png 300w, https://tantusdata.com/app/uploads/2023/12/circuit-board-patterns-150x150.png 150w, https://tantusdata.com/app/uploads/2023/12/circuit-board-patterns-768x768.png 768w, https://tantusdata.com/app/uploads/2023/12/circuit-board-patterns-1536x1536.png 1536w, https://tantusdata.com/app/uploads/2023/12/circuit-board-patterns-2048x2048.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Building a dedicated chatbot is both challenging and dangerous. At company X, the model should talk about X&#8217;s offer and, ideally, nothing else to save cost, not block throughput, and be sure not to insult anyone. It would also be nice to meet all of those requirements while not sacrificing the chatbot&#8217;s performance.</p>



<p>The field of LLM-powered bots is new and rapidly evolving, so many different solutions have emerged, but one of them caught our attention: Nvidia&nbsp;<a href="https://github.com/NVIDIA/NeMo-Guardrails">NeMo-Guardrails</a>. Its core value is the ability to define rails to guide conversations while being able to connect an LLM to other services seamlessly and securely.&nbsp;</p>



<p>You can check out how to get started using the examples and user guide on its GitHub page, but since it is very new and, at the time of this writing, the current release is alpha 0.5, there are not many resources online on how to build more complex applications. At TantusData, we&#8217;ve been using it a lot recently and want to share a few practical tips.</p>



<p>Agenda:</p>



<ul class="wp-block-list">
<li>How to make it work with a model of your choice</li>



<li>Multiple bot actions and responses per one user message and output formatting</li>



<li>Two chat histories: one for displaying to the user, different to guide the model</li>



<li>General tips</li>
</ul>



<h2 class="wp-block-heading">How to make it work with a model of your choice</h2>



<p>We will use&nbsp;<a href="https://docs.mistral.ai/quickstart">Mistal7BInstruct</a>&nbsp;to illustrate that. The advantage of using this open-source model is that it comes with an official Docker image, which you can use to self-host it, and the API schema follows the one from OpenAI, so it is super easy to integrate it. You can also use this Docker with any other model from HuggingFace. If it is a gated one, such as Llama-2, remember to run Docker with -e HF_TOKEN=&#8230; to get access.</p>



<p>There are two things to cover here—connection to the model and prompting.</p>



<p>The connection consists of two parts: config and implementation. The bare minimum implementation follows&nbsp;<a href="https://python.langchain.com/docs/modules/model_io/models/llms/custom_llm">LangChain LLM interface</a>, which should be put in `config.py` file with an additional line registering it in guardrails:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# config.py
import openai

class Mistral7BInstruct(LLM):
model: str
endpoint_url: str
# also useful to define: temperature ~ 0.0, max_tokens ~ 2K, frequency_penalty ~ 1.

def _call(
self,
prompt: str,
stop: Optional[List[str]] = None,
run_manager: Optional[CallbackManagerForLLMRun] = None,
**kwargs: Any,
) -&gt; str:

openai.api_key = None
openai.api_base = self.endpoint_url

response = openai.Completion.create(
model = self.model,
prompt = prompt,
stop = stop,
**kwargs
)

return response.choices[0].text

@property
def _identifying_params(self):
...

@property
def _llm_type(self):
return {}

register_llm_provider(&quot;my_engine_name&quot;, Mistral7BInstruct)" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">config</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">py</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">openai</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">class</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Mistral7BInstruct</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">LLM</span><span style="color: #D8DEE9FF">):</span></span>
<span class="line"><span style="color: #8FBCBB">model</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">str</span></span>
<span class="line"><span style="color: #8FBCBB">endpoint_url</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">str</span></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #8FBCBB">also</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">useful</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">to</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">define</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">temperature</span><span style="color: #D8DEE9FF"> ~ 0.0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">max_tokens</span><span style="color: #D8DEE9FF"> ~ 2</span><span style="color: #8FBCBB">K</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">frequency_penalty</span><span style="color: #D8DEE9FF"> ~ 1.</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">_call</span><span style="color: #D8DEE9FF">(</span></span>
<span class="line"><span style="color: #8FBCBB">self</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #8FBCBB">prompt</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">str</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #8FBCBB">stop</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">Optional</span><span style="color: #D8DEE9FF">[</span><span style="color: #8FBCBB">List</span><span style="color: #D8DEE9FF">[</span><span style="color: #8FBCBB">str</span><span style="color: #D8DEE9FF">]] = </span><span style="color: #8FBCBB">None</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #8FBCBB">run_manager</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">Optional</span><span style="color: #D8DEE9FF">[</span><span style="color: #8FBCBB">CallbackManagerForLLMRun</span><span style="color: #D8DEE9FF">] = </span><span style="color: #8FBCBB">None</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #81A1C1">**</span><span style="color: #8FBCBB">kwargs</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">Any</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">) -&gt; </span><span style="color: #8FBCBB">str</span><span style="color: #D8DEE9FF">:</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">openai</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">api_key</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">None</span></span>
<span class="line"><span style="color: #8FBCBB">openai</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">api_base</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">self</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">endpoint_url</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">response</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">openai</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">Completion</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">create</span><span style="color: #D8DEE9FF">(</span></span>
<span class="line"><span style="color: #8FBCBB">model</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">self</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">model</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #8FBCBB">prompt</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">prompt</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #8FBCBB">stop</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">stop</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #81A1C1">**</span><span style="color: #8FBCBB">kwargs</span></span>
<span class="line"><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">response</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">choices</span><span style="color: #D8DEE9FF">[0].</span><span style="color: #8FBCBB">text</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">@</span><span style="color: #8FBCBB">property</span></span>
<span class="line"><span style="color: #8FBCBB">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">_identifying_params</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">self</span><span style="color: #D8DEE9FF">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">...</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">@</span><span style="color: #8FBCBB">property</span></span>
<span class="line"><span style="color: #8FBCBB">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">_llm_type</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">self</span><span style="color: #D8DEE9FF">):</span></span>
<span class="line"><span style="color: #8FBCBB">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">register_llm_provider</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">my_engine_name</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Mistral7BInstruct</span><span style="color: #D8DEE9FF">)</span></span></code></pre></div>



<p></p>



<p>Then what you need to do is specify the engine and parameters in `config.yml` file.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="models:
- type: main
engine: my_engine_name
parameters:
model: mistralai/Mistral-7B-Instruct-v0.1
endpoint_url: ..." style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">models</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> type</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">main</span></span>
<span class="line"><span style="color: #D8DEE9FF">engine</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">my_engine_name</span></span>
<span class="line"><span style="color: #D8DEE9FF">parameters</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">model</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">mistralai</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">Mistral</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">7</span><span style="color: #D8DEE9">B</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">Instruct</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">v0</span><span style="color: #ECEFF4">.</span><span style="color: #B48EAD">1</span></span>
<span class="line"><span style="color: #D8DEE9FF">endpoint_url</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">...</span></span></code></pre></div>



<p></p>



<p>The next thing to cover is prompts.</p>



<p>By now, NeMo-Guardrails works best with `text-davinci-003` (first chat GPT). More recent OpenAI models expect different prompts to create structured output, whereas the OpenSource model needs more strict instructions on what to do; they won&#8217;t automatically spot the pattern in two examples and follow.</p>



<p>The main challenge is generating user intent given the current input and definitions provided in `*.co` files. There are prompts for some already implemented and general ones that will be used if the engine is not explicitly implemented. The problem with them is that they lack explicit instruction on what to do, and as we noticed, usually less powerful models, instead of following the intent pattern, go ahead and try to respond to user input.</p>



<p>The solution for mistral is to include explicit instruction.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="- task: generate_user_intent
content: |-
&quot;&quot;&quot;
{{ general_instruction }}
You must write only user intent as shown in the example. Do not respond to the user. Do not write anything else.
&quot;&quot;&quot;
..." style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> task</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">generate_user_intent</span></span>
<span class="line"><span style="color: #D8DEE9FF">content</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|-</span></span>
<span class="line"><span style="color: #ECEFF4">&quot;&quot;&quot;</span></span>
<span class="line"><span style="color: #A3BE8C">{{ general_instruction }</span><span style="color: #D8DEE9">}</span></span>
<span class="line"><span style="color: #D8DEE9">You</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">must</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">write</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">only</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">intent</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> shown in the example</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF"> Do not respond to the user</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF"> Do not write anything else</span><span style="color: #ECEFF4">.</span></span>
<span class="line"><span style="color: #ECEFF4">&quot;&quot;&quot;</span></span>
<span class="line"><span style="color: #A3BE8C">..</span><span style="color: #D8DEE9">.</span></span></code></pre></div>



<p></p>



<h2 class="wp-block-heading">Multiple bot actions and responses per one user message and output formatting</h2>



<p>There are situations when we want to execute more than one action or value extraction per round and combine all outputs into the final response. The reason not to just write a wrapper function which will do everything at once is the ability to later easily filter or modify some parts from history, which gets automatically inserted into the model prompt. I will cover that in the next section.&nbsp;&nbsp;</p>



<p>Also, when you want to include some line breaks for better formatting, in the default definition&#8230; it will either not be visible or displayed as &#8216;\n&#8217; instead and all bot messages from one round will simply get concatenated.</p>



<p>Now, let&#8217;s look at how an example flow might look like:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="define bot answer_with_cited_document provide answer
&quot;Answer: $answer_with_cited_document \n\n&quot;

define bot matches_in_db found matches
&quot;Found matches: $matches_in_db&quot;

define flow answer with cited documents
user ask question
$answer_with_cited_document = ...
bot $answer_with_cited_document provide answer
$cited_documents = ... 
$matches_in_db = execute db_search(cited_documents=$cited_documents)
bot $matches_in_db inform found matches" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">bot</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">answer_with_cited_document</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">provide</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">answer</span></span>
<span class="line"><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Answer: $answer_with_cited_document </span><span style="color: #EBCB8B">\n\n</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">bot</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">matches_in_db</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">found</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">matches</span></span>
<span class="line"><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Found matches: $matches_in_db</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">flow</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">answer</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">with</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">cited</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">documents</span></span>
<span class="line"><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ask</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">question</span></span>
<span class="line"><span style="color: #D8DEE9">$answer_with_cited_document</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">...</span></span>
<span class="line"><span style="color: #D8DEE9">bot</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">$answer_with_cited_document</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">provide</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">answer</span></span>
<span class="line"><span style="color: #D8DEE9">$cited_documents</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">...</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #D8DEE9">$matches_in_db</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">execute</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">db_search</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">cited_documents</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9">$cited_documents</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9">bot</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">$matches_in_db</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">inform</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">found</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">matches</span></span></code></pre></div>



<p></p>



<p>Here, the printed bot answer after concatenation will look as follows:</p>



<p>&#8220;Answer: $answer_with_cited_document \n\nFound matches: $matches_in_db”</p>



<p>The way to achieve better formatting might look like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="define bot formatted_answer print answer
&quot;$formatted_answer&quot;
define flow answer with cited documents
user ask question
$answer_with_cited_document = ...
$cited_documents = ... 
$matches_in_db = execute db_search(cited_documents=$cited_documents)
$formatted_answer = execute format_answer(ans=$answer_with_cited_document, docs=$matches_in_db)
bot formatted_answer print answer" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">bot</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">formatted_answer</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">print</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">answer</span></span>
<span class="line"><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">$formatted_answer</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">flow</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">answer</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">with</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">cited</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">documents</span></span>
<span class="line"><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ask</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">question</span></span>
<span class="line"><span style="color: #D8DEE9">$answer_with_cited_document</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">...</span></span>
<span class="line"><span style="color: #D8DEE9">$cited_documents</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">...</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #D8DEE9">$matches_in_db</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">execute</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">db_search</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">cited_documents</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9">$cited_documents</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9">$formatted_answer</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">execute</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">format_answer</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">ans</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9">$answer_with_cited_document</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">docs</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9">$matches_in_db</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9">bot</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">formatted_answer</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">print</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">answer</span></span></code></pre></div>



<p></p>



<h2 class="wp-block-heading">Two chat histories: one for displaying to the user, different to guide the model</h2>



<p>The most straightforward reason we must do something with history at some point is the fact that LLMs have limited context. But apart from that, one should understand what gets inserted into the model&#8217;s prompt and whether you are not wasting tokens unnecessarily.</p>



<p>By default, NeMo Guardrails inserts the action output into the prompt with such format:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="execute db_search
# The result was /* Full result returned from action here */" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">execute</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">db_search</span></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">The</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">result</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">was</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">/* Full result returned from action here */</span></span></code></pre></div>



<p></p>



<p>If our db_search returns a massive Json we have a problem. In the long run, it will fill up the context, but even before that, it can distract the model from paying attention to relevant parts.&nbsp;</p>



<p>It depends on the particular use case, but if all you want to do is display the results with, e.g. links and scores when left unchanged, the search results will be inserted into the prompt twice, once after action execution and the second time as a final bot answer if you use additional action for output formatting even thrice!</p>



<p>We can take advantage of filters to adjust that.</p>



<p>In general prompts, you can find templates like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# prompts_general.yml

{{ history | colang }}" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">prompts_general</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">yml</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">{{</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">history</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">colang</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}}</span></span></code></pre></div>



<p></p>



<p>— which takes the whole history and parses it into the prompt in colang.</p>



<p>To filter or modify some events, one can add a custom filter in such a way:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# config.py

def modify_actions(events: List[dict]) -&gt; List[dict]:
events = deepcopy(events)

# filter formatting since we will see the exact same string as a final bot answer
events = [event for event in events if not (event['type'] == 'InternalSystemActionFinished' and event['action_name'] == 'format_answer')]

for event in events:
if event['type'] == 'InternalSystemActionFinished' and event['action_name'] == &quot;your_action_name_here&quot;:

event['return_value'] = modify event['return_value']])

# filter formatting since we will see the exact same string as the final bot answer

return events

def init(llm_rails: LLMRails):
llm_rails.register_filter(modify_actions, &quot;modify_actions&quot;)" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">config</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">py</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">modify_actions</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">events</span><span style="color: #D8DEE9FF">: </span><span style="color: #D8DEE9">List</span><span style="color: #D8DEE9FF">[</span><span style="color: #D8DEE9">dict</span><span style="color: #D8DEE9FF">]) </span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">List</span><span style="color: #D8DEE9FF">[</span><span style="color: #D8DEE9">dict</span><span style="color: #D8DEE9FF">]:</span></span>
<span class="line"><span style="color: #D8DEE9">events</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">deepcopy</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">events</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">filter</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">formatting</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">since</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">we</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">will</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">see</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">exact</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">same</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">string</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> a final bot answer</span></span>
<span class="line"><span style="color: #D8DEE9">events</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> [</span><span style="color: #D8DEE9">event</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">event</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">in</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">events</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">not</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">event</span><span style="color: #D8DEE9FF">[</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">type</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF">] </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">InternalSystemActionFinished</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">and</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">event</span><span style="color: #D8DEE9FF">[</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">action_name</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF">] </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">format_answer</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF">)]</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">event</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">in</span><span style="color: #D8DEE9FF"> events</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">event</span><span style="color: #D8DEE9FF">[</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">type</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF">] </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">InternalSystemActionFinished</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">and</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">event</span><span style="color: #D8DEE9FF">[</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">action_name</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF">] </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">your_action_name_here</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">:</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">event</span><span style="color: #D8DEE9FF">[</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">return_value</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF">] </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">modify</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">event</span><span style="color: #D8DEE9FF">[</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">return_value</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF">]])</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">filter</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">formatting</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">since</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">we</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">will</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">see</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">exact</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">same</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">string</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> the final bot answer</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">events</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">init</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">llm_rails</span><span style="color: #D8DEE9FF">: </span><span style="color: #D8DEE9">LLMRails</span><span style="color: #D8DEE9FF">):</span></span>
<span class="line"><span style="color: #D8DEE9">llm_rails</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">register_filter</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">modify_actions</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">modify_actions</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span></code></pre></div>



<p></p>



<p>And then use it in prompts like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# prompts_general.yml

{{ history | modify_actions | colang }}" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">prompts_general</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">yml</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">{{</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">history</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">modify_actions</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">colang</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}}</span></span></code></pre></div>



<p></p>



<p>We use deepcopy because Python&#8217;s dictionary modifications like my_dict[&#8216;key&#8217;] = val modify the variable passed to function, and without it in later chat rounds, we would have to check whether the value is already modified or not.</p>



<p>Sometimes, it does make sense to clean up the whole history. For example, a user intends to start from the beginning and send a new request. Without history cleaning, previously entered information might produce incorrect prompts and cause irrelevant search results. To achieve that, we define the following flow in the colang file:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="define user start new search
    &quot;I'd like to start a new search&quot;
    &quot;May I look for something different&quot;
    &quot;I want to try another conditions&quot;
    &quot;Forget all I asked before&quot;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">start</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">search</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">I&#39;d like to start a new search</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">May I look for something different</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">I want to try another conditions</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Forget all I asked before</span><span style="color: #ECEFF4">&quot;</span></span></code></pre></div>



<p></p>



<p>After that, you can enhance modify_actions method with the following extract:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code=" history = []
    for event in events:
        history.append(event)
        if event['type'] == &quot;UserIntent&quot; and event['intent'] == &quot;start new search&quot;:
            while len(history) &gt; 0:
                history.pop()
    return history" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">history</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> []</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">event</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">in</span><span style="color: #D8DEE9FF"> events</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">history</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">append</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">event</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">event</span><span style="color: #D8DEE9FF">[</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">type</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF">] </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">UserIntent</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">and</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">event</span><span style="color: #D8DEE9FF">[</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">intent</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF">] </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">start new search</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">len</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">history</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">history</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">pop</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">history</span></span></code></pre></div>



<p></p>



<h2 class="wp-block-heading">General tips</h2>



<p>Also, when working with NeMo Guardrails you may find those tips useful.</p>



<ul class="wp-block-list">
<li>Use chat mode instead of server when developing. It makes errors easier to spot and highlights output in verbose mode</li>



<li>Take advantage of Python&#8217;s logging module. Guardrails print a lot in verbose mode, and configuring different files as output for different modules makes reading much more convenient.</li>



<li>When using a custom LLM, explicitly log its inputs and outputs as this is the most fragile part of Guardrails. If your model is not following the colang pattern for getting the user intent you can&#8217;t move forward.</li>
</ul>
<p>The post <a href="https://tantusdata.com/insights/nvidia-nemo-guardrails-chatbot-development-guide/">NeMo-Guardrails</a> appeared first on <a href="https://tantusdata.com">TantusData</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>What if the data is too large for the LLM context?</title>
		<link>https://tantusdata.com/insights/what-if-the-data-is-too-large-for-the-llm-context/</link>
		
		<dc:creator><![CDATA[Bartek Sadlej]]></dc:creator>
		<pubDate>Thu, 28 Sep 2023 11:00:00 +0000</pubDate>
				<category><![CDATA[ChatBot]]></category>
		<category><![CDATA[LangChain]]></category>
		<category><![CDATA[LLM]]></category>
		<category><![CDATA[RAG]]></category>
		<category><![CDATA[Self-Query]]></category>
		<guid isPermaLink="false">https://tantusdata.com/?post_type=insights&#038;p=1844</guid>

					<description><![CDATA[<p>Navigating Large Data with LLM: Splitting, Context, and Self-Query Solutions</p>
<p>The post <a href="https://tantusdata.com/insights/what-if-the-data-is-too-large-for-the-llm-context/">What if the data is too large for the LLM context?</a> appeared first on <a href="https://tantusdata.com">TantusData</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="513" src="https://tantusdata.com/app/uploads/2023/09/LLM2-1024x513.jpg" alt="" class="wp-image-1845" srcset="https://tantusdata.com/app/uploads/2023/09/LLM2-1024x513.jpg 1024w, https://tantusdata.com/app/uploads/2023/09/LLM2-300x150.jpg 300w, https://tantusdata.com/app/uploads/2023/09/LLM2-768x384.jpg 768w, https://tantusdata.com/app/uploads/2023/09/LLM2-1536x769.jpg 1536w, https://tantusdata.com/app/uploads/2023/09/LLM2-2048x1025.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>In the previous <a href="https://tantusdata.com/insights/what-data-format-is-suitable-for-llm/" target="_blank" rel="noreferrer noopener">article</a>, we covered extracting information from unstructured data. However, this is just the tip of the iceberg. Another problem can arise when you have long documents which don’t fit into the embedding model context length. The natural move in such a situation is splitting the documents into multiple parts. Another reason for using this technique is when the entire document does not create good enough embeddings. Last but not least, you might want to extract smaller chunks in order to lower the token usage.</p>



<p>The subject of the document or paragraph is usually at the beginning of the section. It does not show up in the latter parts of the document, so it is likely that when we just split the document into multiple parts, we end up with lots of documents that lack contextual information, for example.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="Subscription prices for 1 month:
20 USD / month


Subscription prices for 1 year:
200 USD / year
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">Subscription</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">prices</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF"> month</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #B48EAD">20</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">USD</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">month</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">Subscription</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">prices</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF"> year</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #B48EAD">200</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">USD</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">year</span></span>
<span class="line"></span></code></pre></div>



<p></p>



<p>In the snippet above, we see the price, but we lack information about what the price is for (for TV subscription, for broadband subscription)</p>



<p>When we query a vector database and provide the result to the LLM application, we will likely see that this document seems relevant to TV, broadband or mobile subscription requests. The reason is that we get a high cosine similarity score for any query related to the subscription price. So here we go:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="from langchain.chains import RetrievalQA
from langchain.docstore.document import Document
from langchain.schema.retriever import BaseRetriever
from langchain.chat_models import ChatOpenAI


class ConstRetriever(BaseRetriever):
   def _get_relevant_documents(self, *args, **kwargs) -&gt; List[Document]:
       return [doc]
llm = ChatOpenAI(model_name=&quot;gpt-4&quot;)
retriever = ConstRetriever()
qa = RetrievalQA.from_llm(llm, retriever=retriever)


offers = [&quot;TV&quot;, &quot;Internet&quot;, &quot;Car&quot;, &quot;Gym membership&quot;]


for offer in offers:
   res = qa(f&quot;What is the {offer} subscription price for one year?&quot;)['result']
   print(res)" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">langchain</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">chains</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">RetrievalQA</span></span>
<span class="line"><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">langchain</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">docstore</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">document</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Document</span></span>
<span class="line"><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">langchain</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">schema</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">retriever</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">BaseRetriever</span></span>
<span class="line"><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">langchain</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">chat_models</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">ChatOpenAI</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">class</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">ConstRetriever</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">BaseRetriever</span><span style="color: #D8DEE9FF">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">   </span><span style="color: #8FBCBB">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">_get_relevant_documents</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">self</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #8FBCBB">args</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">**</span><span style="color: #8FBCBB">kwargs</span><span style="color: #D8DEE9FF">) -&gt; </span><span style="color: #8FBCBB">List</span><span style="color: #D8DEE9FF">[</span><span style="color: #8FBCBB">Document</span><span style="color: #D8DEE9FF">]:</span></span>
<span class="line"><span style="color: #D8DEE9FF">       </span><span style="color: #8FBCBB">return</span><span style="color: #D8DEE9FF"> [</span><span style="color: #8FBCBB">doc</span><span style="color: #D8DEE9FF">]</span></span>
<span class="line"><span style="color: #8FBCBB">llm</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">ChatOpenAI</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">model_name</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">gpt-4</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #8FBCBB">retriever</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">ConstRetriever</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"><span style="color: #8FBCBB">qa</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">RetrievalQA</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">from_llm</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">llm</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">retriever</span><span style="color: #D8DEE9FF">=</span><span style="color: #8FBCBB">retriever</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">offers</span><span style="color: #D8DEE9FF"> = [</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">TV</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Internet</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Car</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Gym membership</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">]</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">offer</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">in</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">offers</span><span style="color: #D8DEE9FF">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">   </span><span style="color: #8FBCBB">res</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">qa</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">f</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">What is the {offer} subscription price for one year?</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)[</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">result</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF">]</span></span>
<span class="line"><span style="color: #D8DEE9FF">   </span><span style="color: #8FBCBB">print</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">res</span><span style="color: #D8DEE9FF">)</span></span></code></pre></div>



<p></p>



<ul class="wp-block-list">
<li>The subscription price for one year is 200 USD.</li>



<li>The subscription price for one year is 200 USD.</li>



<li>The context does not provide information on the car subscription price for one year.</li>



<li>The context provided does not specify what the subscription prices are for, such as a gym membership. Therefore, I can&#8217;t provide the exact price for a gym membership subscription for one year.</li>
</ul>



<p>All those queries have ~0.85-0.9 cosine similarity with the example document. This document is ‘close enough’ and gets provided as input to the LLM. The LLM then has to decide how to answer the question. Moreover, if you think about it, the document content is not enough to say what the price is for, so the best you can expect is to say ‘I don’t know’ so at least it does not make information up, which it does not have in the first place. And that answer is not satisfying anyway &#8211; we do have the information about the prices, and we would like to chat to answer it. We just have to find a better way of providing it with the correct information.</p>



<h2 class="wp-block-heading">How do we tackle this problem?</h2>



<p>After splitting, the most straightforward solution is to include additional context for each part. For example, we can add “Details for the TV offer:” if those prices come from such an offer. It helps with solving hallucination problems, but the similarity score may remain high for such documents, which can prevent the retriever from fetching the most relevant documents. The model will answer that it does not have enough context to answer the question.&nbsp;</p>



<p>Another solution is to include document metadata and use a feature called self-query.</p>



<p>Here, instead of including context information directly in the document text, we set it as an additional filtering index and use LLM to produce a relevant query.</p>



<p>The difference is that even though the document has a high similarity score, it will not get fetched, and the retriever can provide genuinely relevant data sources. In other words, instead of relying on vector store to provide relevant documents only by their embeddings&#8217; similarity to the query, we add an extra index and provide the LLM with its description. The model can then decide whether to use it and with what arguments.&nbsp;&nbsp;</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Weaviate
from langchain.retrievers.self_query.base import SelfQueryRetriever
from langchain.chains.query_constructor.base import AttributeInfo


embeddings = OpenAIEmbeddings()


page_content=&quot;&quot;&quot;
Subscription prices for 1 month:
20 USD / month


Subscription prices for 1 year:
200 USD / year
&quot;&quot;&quot;


docs = [
   Document(
       page_content=page_content,
       metadata={
           &quot;product&quot;: &quot;TV&quot;,
       },
   ),
]
vectorstore = Weaviate.from_documents(
   docs, embeddings, weaviate_url=&quot;http://127.0.0.1:8080&quot;
)


metadata_field_info = [
   AttributeInfo(
       name=&quot;product&quot;,
       description=&quot;The name of the product for which the subscription prices are&quot;,
       type=&quot;string&quot;,
   ),
]
document_content_description = &quot;Details for all the products offers&quot;
llm = ChatOpenAI(model_name=&quot;gpt-3.5-turbo&quot;, temperature=0., verbose=True)
retriever = SelfQueryRetriever.from_llm(
   llm, vectorstore, document_content_description, metadata_field_info, verbose=True
)
qa_with_self_query = RetrievalQA.from_llm(llm, retriever=retriever, return_source_documents=True)


for offer in [&quot;TV&quot;, &quot;Internet&quot;, &quot;Car&quot;, &quot;Gym membership&quot;]:
    res = qa_with_self_query(f&quot;What is the {offer} subscription price for one year?&quot;)
    print(f&quot;n docs: {len(res['source_documents'])}, answer: {res['result']}&quot;)" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">langchain</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">embeddings</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">openai</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">OpenAIEmbeddings</span></span>
<span class="line"><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">langchain</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">vectorstores</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Weaviate</span></span>
<span class="line"><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">langchain</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">retrievers</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">self_query</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">base</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">SelfQueryRetriever</span></span>
<span class="line"><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">langchain</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">chains</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">query_constructor</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">base</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">AttributeInfo</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">embeddings</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">OpenAIEmbeddings</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">page_content</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;&quot;&quot;</span></span>
<span class="line"><span style="color: #A3BE8C">Subscription prices for 1 month</span><span style="color: #D8DEE9">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">20 </span><span style="color: #8FBCBB">USD</span><span style="color: #D8DEE9FF"> / </span><span style="color: #8FBCBB">month</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">Subscription</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">prices</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">for</span><span style="color: #D8DEE9FF"> 1 </span><span style="color: #8FBCBB">year</span><span style="color: #D8DEE9FF">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">200 </span><span style="color: #8FBCBB">USD</span><span style="color: #D8DEE9FF"> / </span><span style="color: #8FBCBB">year</span></span>
<span class="line"><span style="color: #ECEFF4">&quot;&quot;&quot;</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #A3BE8C">docs = </span><span style="color: #D8DEE9">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">   </span><span style="color: #8FBCBB">Document</span><span style="color: #D8DEE9FF">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">       </span><span style="color: #8FBCBB">page_content</span><span style="color: #D8DEE9FF">=</span><span style="color: #8FBCBB">page_content</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">       </span><span style="color: #8FBCBB">metadata</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">           &quot;</span><span style="color: #8FBCBB">product</span><span style="color: #D8DEE9FF">&quot;: &quot;</span><span style="color: #8FBCBB">TV</span><span style="color: #D8DEE9FF">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">       </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">   )</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">]</span></span>
<span class="line"><span style="color: #8FBCBB">vectorstore</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">Weaviate</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">from_documents</span><span style="color: #D8DEE9FF">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">   </span><span style="color: #8FBCBB">docs</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">embeddings</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">weaviate_url</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">http://127.0.0.1:8080</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">metadata_field_info</span><span style="color: #D8DEE9FF"> = [</span></span>
<span class="line"><span style="color: #D8DEE9FF">   </span><span style="color: #8FBCBB">AttributeInfo</span><span style="color: #D8DEE9FF">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">       </span><span style="color: #8FBCBB">name</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">product</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">       </span><span style="color: #8FBCBB">description</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">The name of the product for which the subscription prices are</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">       </span><span style="color: #8FBCBB">type</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">   )</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">]</span></span>
<span class="line"><span style="color: #8FBCBB">document_content_description</span><span style="color: #D8DEE9FF"> = </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Details for all the products offers</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #8FBCBB">llm</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">ChatOpenAI</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">model_name</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">gpt-3.5-turbo</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">temperature</span><span style="color: #D8DEE9FF">=0.</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">verbose</span><span style="color: #D8DEE9FF">=</span><span style="color: #8FBCBB">True</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #8FBCBB">retriever</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">SelfQueryRetriever</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">from_llm</span><span style="color: #D8DEE9FF">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">   </span><span style="color: #8FBCBB">llm</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">vectorstore</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">document_content_description</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">metadata_field_info</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">verbose</span><span style="color: #D8DEE9FF">=</span><span style="color: #8FBCBB">True</span></span>
<span class="line"><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #8FBCBB">qa_with_self_query</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">RetrievalQA</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">from_llm</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">llm</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">retriever</span><span style="color: #D8DEE9FF">=</span><span style="color: #8FBCBB">retriever</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">return_source_documents</span><span style="color: #D8DEE9FF">=</span><span style="color: #8FBCBB">True</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">offer</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">in</span><span style="color: #D8DEE9FF"> [</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">TV</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Internet</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Car</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Gym membership</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">]:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">res</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">qa_with_self_query</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">f</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">What is the {offer} subscription price for one year?</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">print</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">f</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">n docs: {len(res[&#39;source_documents&#39;])}, answer: {res[&#39;result&#39;]}</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span></code></pre></div>



<p></p>



<p>This is the result produced by the code above:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="query='TV subscription price' 
filter=Comparison(comparator=<Comparator.EQ: 'eq'&gt;, attribute='product', value='TV') limit=Nonen docs: 1, 
answer: The TV subscription price for one year is 200 USD.
—-----------------------------------------------
query='Internet subscription price' filter=Comparison(comparator=<Comparator.EQ: 'eq'&gt;, attribute='product', value='Internet') limit=None
n docs: 0, answer: I'm sorry, but I don't have access to specific pricing information …
query='Car subscription price' filter=Comparison(comparator=<Comparator.EQ: 'eq'&gt;, attribute='product', value='Car') limit=None
n docs: 0, answer: I'm sorry, but I don't have enough information …
query='Gym membership subscription price' filter=Comparison(comparator=<Comparator.EQ: 'eq'&gt;, attribute='product', value='Gym membership') limit=None
n docs: 0, answer: I'm sorry, but I don't have access to specific pricing information for gym memberships. …" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">query</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">TV subscription price</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #D8DEE9">filter</span><span style="color: #81A1C1">=</span><span style="color: #88C0D0">Comparison</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">comparator</span><span style="color: #81A1C1">=&lt;</span><span style="color: #D8DEE9">Comparator</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">EQ</span><span style="color: #D8DEE9FF">: </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">eq</span><span style="color: #ECEFF4">&#39;</span><span style="color: #81A1C1">&gt;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">attribute</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">product</span><span style="color: #ECEFF4">&#39;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">value</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">TV</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF">) </span><span style="color: #D8DEE9">limit</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9">Nonen</span><span style="color: #D8DEE9FF"> docs</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #D8DEE9FF">answer</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">The</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">TV</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">subscription</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">price</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">one</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">year</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">is</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">200</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">USD</span><span style="color: #ECEFF4">.</span></span>
<span class="line"><span style="color: #D8DEE9FF">—</span><span style="color: #81A1C1">-----------------------------------------------</span></span>
<span class="line"><span style="color: #D8DEE9">query</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">Internet subscription price</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">filter</span><span style="color: #81A1C1">=</span><span style="color: #88C0D0">Comparison</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">comparator</span><span style="color: #81A1C1">=&lt;</span><span style="color: #D8DEE9">Comparator</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">EQ</span><span style="color: #D8DEE9FF">: </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">eq</span><span style="color: #ECEFF4">&#39;</span><span style="color: #81A1C1">&gt;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">attribute</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">product</span><span style="color: #ECEFF4">&#39;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">value</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">Internet</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF">) </span><span style="color: #D8DEE9">limit</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9">None</span></span>
<span class="line"><span style="color: #D8DEE9">n</span><span style="color: #D8DEE9FF"> docs</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> answer</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">I</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">m sorry, but I don</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9">t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">have</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">access</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">to</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">specific</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pricing</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">information</span><span style="color: #D8DEE9FF"> …</span></span>
<span class="line"><span style="color: #D8DEE9">query</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">Car subscription price</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">filter</span><span style="color: #81A1C1">=</span><span style="color: #88C0D0">Comparison</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">comparator</span><span style="color: #81A1C1">=&lt;</span><span style="color: #D8DEE9">Comparator</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">EQ</span><span style="color: #D8DEE9FF">: </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">eq</span><span style="color: #ECEFF4">&#39;</span><span style="color: #81A1C1">&gt;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">attribute</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">product</span><span style="color: #ECEFF4">&#39;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">value</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">Car</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF">) </span><span style="color: #D8DEE9">limit</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9">None</span></span>
<span class="line"><span style="color: #D8DEE9">n</span><span style="color: #D8DEE9FF"> docs</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> answer</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">I</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">m sorry, but I don</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9">t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">have</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">enough</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">information</span><span style="color: #D8DEE9FF"> …</span></span>
<span class="line"><span style="color: #D8DEE9">query</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">Gym membership subscription price</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">filter</span><span style="color: #81A1C1">=</span><span style="color: #88C0D0">Comparison</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">comparator</span><span style="color: #81A1C1">=&lt;</span><span style="color: #D8DEE9">Comparator</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">EQ</span><span style="color: #D8DEE9FF">: </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">eq</span><span style="color: #ECEFF4">&#39;</span><span style="color: #81A1C1">&gt;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">attribute</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">product</span><span style="color: #ECEFF4">&#39;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">value</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">Gym membership</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF">) </span><span style="color: #D8DEE9">limit</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9">None</span></span>
<span class="line"><span style="color: #D8DEE9">n</span><span style="color: #D8DEE9FF"> docs</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> answer</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">I</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">m sorry, but I don</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9">t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">have</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">access</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">to</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">specific</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pricing</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">information</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gym</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">memberships</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF"> …</span></span></code></pre></div>



<p></p>



<p>The drawback of this approach is that it is significantly more expensive because additional calls are needed to provide this functionality. With LangChain OpenAICallback, we can easily monitor the API usage, and for the first solution, it is ~ 0.00015 $ per question, whereas for the second ~ 0.0015 $, so x10 increase.</p>



<p>We also have to keep in mind that creating metadata for splitted documents might not be trivial and may need human supervision.</p>



<p>All things considered, it’s not a surprise that LLM will be as good as the data you provide to it – the more detailed and relevant information you can provide, the higher the chance of getting a good response. Self-querying is a powerful technique which might be useful in the project you are working on. The exact decision on how to provide metadata and whether we should use self-querying depends on a specific business problem to be solved.</p>
<p>The post <a href="https://tantusdata.com/insights/what-if-the-data-is-too-large-for-the-llm-context/">What if the data is too large for the LLM context?</a> appeared first on <a href="https://tantusdata.com">TantusData</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
