<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:base="https://ruxu.dev/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Blog | Roger Oriol</title>
    <link>https://ruxu.dev/</link>
    <atom:link href="https://ruxu.dev/feed.xml" rel="self" type="application/rss+xml" />
    <description>My name is Roger Oriol, I am a Software Architect based in Barcelona, Spain. I am a MSc graduate in Big Data Management, Technologies and Analytics. This blog will be the vehicle to divulgate and discuss topics on web development, data architecture, software architecture and much more.</description>
    <language>en</language>
    <item>
      <title>CaixaBank importer for Beancount</title>
      <link>https://ruxu.dev/projects/beancount-caixabank/</link>
      <description>&lt;h2 id=&quot;motivation&quot; tabindex=&quot;-1&quot;&gt;Motivation&lt;/h2&gt;
&lt;p&gt;Easily import CaixaBank bank statements into your Beancount ledger.&lt;/p&gt;
&lt;h2 id=&quot;features&quot; tabindex=&quot;-1&quot;&gt;Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Format Support&lt;/strong&gt;: Handles CaixaBank Excel exports (.xls and .xlsx)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Robust Parsing&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;Flexible header detection (handles statements with metadata rows)&lt;/li&gt;
&lt;li&gt;Supports both Excel date serial numbers and DD/MM/YYYY string dates&lt;/li&gt;
&lt;li&gt;European number format parsing (comma as decimal, dot as thousands separator)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Full Beancount Integration&lt;/strong&gt;: Creates proper transactions with metadata, payee, and narration&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;contributing&quot; tabindex=&quot;-1&quot;&gt;Contributing&lt;/h2&gt;
&lt;p&gt;Contributions are welcome! Please feel free to submit a PR.&lt;/p&gt;
&lt;h2 id=&quot;license&quot; tabindex=&quot;-1&quot;&gt;License&lt;/h2&gt;
&lt;p&gt;This project is licensed under the MIT License - see the &lt;a href=&quot;https://github.com/rogiia/beancount-caixabank/blob/main/LICENSE.txt&quot;&gt;LICENSE.txt&lt;/a&gt; file for details.&lt;/p&gt;
</description>
      <pubDate>Sun, 04 Jan 2026 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/projects/beancount-caixabank/</guid>
    </item>
    <item>
      <title>Gym sessions tracker</title>
      <link>https://ruxu.dev/projects/gym-tracker/</link>
      <description>&lt;h2 id=&quot;motivation&quot; tabindex=&quot;-1&quot;&gt;Motivation&lt;/h2&gt;
&lt;p&gt;Track gym sessions as a heatmap to guilt myself into going more to the gym.&lt;/p&gt;
&lt;h2 id=&quot;project-overview&quot; tabindex=&quot;-1&quot;&gt;Project Overview&lt;/h2&gt;
&lt;p&gt;Gym Tracker is a containerized web application for tracking gym sessions and muscle group training frequency. It displays a heatmap of workout sessions, tracks muscle group balance, and provides insights into training patterns.&lt;/p&gt;
&lt;h2 id=&quot;features&quot; tabindex=&quot;-1&quot;&gt;Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Log gym sessions, including which muscles were trained
&lt;ul&gt;
&lt;li&gt;Can log sessions after the fact&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Visualize at a glance how often I&#39;m training using a heatmap like Github&#39;s&lt;/li&gt;
&lt;li&gt;For each body part, see the last time I&#39;ve trained it, to easily see which body parts I need to train the next session&lt;/li&gt;
&lt;li&gt;Self-hostable application&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;tech-stack&quot; tabindex=&quot;-1&quot;&gt;Tech Stack:&lt;/h2&gt;
&lt;p&gt;Backend: Node.js with Express
Database: SQLite
Frontend: Vanilla JavaScript
Deployment: Docker container with Nginx reverse proxy&lt;/p&gt;
&lt;h2 id=&quot;contributing&quot; tabindex=&quot;-1&quot;&gt;Contributing&lt;/h2&gt;
&lt;p&gt;Contributions are welcome! Please feel free to submit a PR.&lt;/p&gt;
&lt;h2 id=&quot;license&quot; tabindex=&quot;-1&quot;&gt;License&lt;/h2&gt;
&lt;p&gt;This project is licensed under the MIT License&lt;/p&gt;
</description>
      <pubDate>Sun, 02 Nov 2025 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/projects/gym-tracker/</guid>
    </item>
    <item>
      <title>[Link] GPT-5</title>
      <link>https://ruxu.dev/links/gpt-5/</link>
      <description>&lt;p&gt;OpenAI has finally released it&#39;s &lt;strong&gt;GPT-5&lt;/strong&gt; model, and as we were already expecting, it&#39;s a hybrid reasoning model. Now the model itself chooses how much to think about each task, and you can force the reasoning effort as well. This probably means the end of the o series of reasoning models from OpenAI, as the regular language models and the reasoning models will now be unified.&lt;/p&gt;
&lt;p&gt;Of course, the benchmarks look good but saturated. What stands out to me is that they announced a &lt;strong&gt;74.9&lt;/strong&gt; score on SWE-bench (with high reasoning effort), which is just a tad over the score from Claude Opus 4.1 just announced this very same week (74.5).&lt;/p&gt;
&lt;p&gt;With the GPT-5 iteration, come 4 new models: &lt;strong&gt;GPT-5, GPT-5-mini, GPT-5-nano and GPT-5 Chat&lt;/strong&gt;. Free users will be allowed to use GPT-5, although when they hit the maximum quota, they will fallback to GPT-5-mini.&lt;/p&gt;
&lt;p&gt;GPT-5 allows to &lt;strong&gt;set the reasoning effort&lt;/strong&gt; using the &amp;quot;reasoning.effort&amp;quot; parameter, although you can also force it telling the model to &amp;quot;Think hard about this&amp;quot;. These new models introduce a new reasoning tier called &amp;quot;minimal&amp;quot; which produces a few as possible reasoning tokens before answering. The output tokens can also be customized by setting the &amp;quot;verbosity&amp;quot; parameter, which didn&#39;t exist for past models. This parameter can be set to &amp;quot;high&amp;quot;, &amp;quot;medium&amp;quot; or &amp;quot;low&amp;quot;.&lt;/p&gt;
&lt;p&gt;The new models also bring some new quality of life improvements for tool calling:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tool choice:&lt;/strong&gt; While the models can choose to call zero, one or multiple tools, you can now set &amp;quot;tool_choice&amp;quot; to &amp;quot;forced&amp;quot; to force the invocation of at least one tool. You can also set a specific function that must be called by passing {&amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;, &amp;quot;name&amp;quot;: &amp;quot;function name&amp;quot;} to the &amp;quot;tool_choice&amp;quot; parameter. Finally, in &amp;quot;tool_choice&amp;quot; you can also specify a list of allowed tools from the list of tools provided to the model: {&amp;quot;type&amp;quot;: &amp;quot;allowed_tools&amp;quot;, &amp;quot;mode&amp;quot;: &amp;quot;auto&amp;quot;, &amp;quot;tools&amp;quot;: []}.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tool preambles:&lt;/strong&gt; New feature that makes the models explain the rationale behind why they are invoking a function. This provides transparency and better understanding on the model&#39;s process. By default, this feature is not enabled. To enable it, you have to include a system message like &amp;quot;Before you call a tool, explain why you are calling it.&amp;quot;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Custom tools:&lt;/strong&gt; This feature allows to define functions that allow unstructured, free-form text as input, which frees the model from using a structured JSON object to call the tool. This might improve the ability of the model to call these tools. This can be even more powerful when paired with Context-Free Grammar.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Context-Free Grammar:&lt;/strong&gt; This feature allows to set grammar rules for the free-form text, to make them follow a set of rules. You can define this rules using Lark or a regular expression.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The GPT-5 models are now available both in ChatGPT and in the OpenAI API, give them a try!&lt;/p&gt;
</description>
      <pubDate>Thu, 07 Aug 2025 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/links/gpt-5/</guid>
    </item>
    <item>
      <title>[Quote] GPT-5 variants</title>
      <link>https://ruxu.dev/links/gpt-5-variants/</link>
      <description>&lt;p&gt;It&#39;s not at all straightforward to understand the variants of the GPT-5 model released today. The API docs describe four models: gpt-5, gpt-5-mini, gpt-5-nano and gpt-5-chat. However, the system card describes 6 models to replace older models, and none of the names match with the API:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It can be helpful to think of the GPT-5 models as successors to previous models:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Table 1: Model progressions&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;/thead&gt;&lt;td&gt;Previous model&lt;/td&gt;&lt;td&gt;GPT-5 model&lt;/td&gt;

&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;GPT-4o&lt;/td&gt;&lt;td&gt;gpt-5-main&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;GPT-4o-mini&lt;/td&gt;&lt;td&gt;gpt-5-main-mini&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;OpenAI o3&lt;/td&gt;&lt;td&gt;gpt-5-thinking&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;OpenAI o4-mini&lt;/td&gt;&lt;td&gt;gpt-5-thinking-mini&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;GPT-4.1-nano&lt;/td&gt;&lt;td&gt;gpt-5-thinking-nano&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;OpenAI o3 Pro&lt;/td&gt;&lt;td&gt;gpt-5-thinking-pro&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br /&gt;
The answer is that the gpt-5 model is composed of the gpt-5-main model, the gpt-5-thinking model and a router that selects the model to send the prompt to:
&lt;blockquote&gt;
&lt;p&gt;GPT-5 is a unified system with a smart and fast model that answers most questions, a deeper reasoning model for harder problems, and a real-time router that quickly decides which model to use...&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The same applies to the mini model. Gpt-5-mini is made of a gpt-5-main-mini model, a gpt-5-thinking-mini model and a router. The nano model only seems to have a thinking variant, not a main, but this makes sense as a single model without a router will allow the model to be faster. This leaves only the gpt-5-thinking-pro model, which &lt;strong&gt;cannot&lt;/strong&gt; be used via API, only via ChatGPT, with a Pro subscription:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In the API, we provide direct access to the thinking model, its mini version, and an even smaller and faster nano version of the thinking model, made for developers (gpt-5-thinking-nano). In ChatGPT, we also provide access to gpt-5-thinking using a setting that makes use of parallel test time compute; we refer to this as gpt-5-thinking-pro.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
      <pubDate>Thu, 07 Aug 2025 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/links/gpt-5-variants/</guid>
    </item>
    <item>
      <title>[Link] GPT-OSS</title>
      <link>https://ruxu.dev/links/gpt-oss/</link>
      <description>&lt;p&gt;Just like Sam Altman hinted at a while ago, OpenAI just released two open-weight models trying to appease the common criticism of being a company with &amp;quot;Open&amp;quot; in the name that hasn&#39;t released any open language models in a long while (since GPT-2!).&lt;/p&gt;
&lt;p&gt;The new open-weights models (not open-source like the name seems to imply) are Mixture-of-experts models with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;116.83 billion parameters&lt;/strong&gt; with &lt;strong&gt;5.13 billion active parameters&lt;/strong&gt;. It has &lt;strong&gt;128 experts&lt;/strong&gt; and activates 4 experts for each token.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;20.91 billion parameters&lt;/strong&gt; with &lt;strong&gt;3.61 billion active parameters&lt;/strong&gt;. It has &lt;strong&gt;32 experts&lt;/strong&gt; and activates 4 experts for each token.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both models are &lt;strong&gt;reasoning models&lt;/strong&gt; and therefore OpenAI compares them to their own o3 and o4 models. It seems like the 120b version is comparable to o4-mini and the 20b version is comparable to o3-mini. The new models have been throughoutly trained for agentic tasks as in the post-training stage, they were trained specifically to use a &lt;strong&gt;browser tool&lt;/strong&gt; and a &lt;strong&gt;python code execution tool&lt;/strong&gt;, as well as other generic tools.&lt;/p&gt;
&lt;p&gt;OpenAI has also introduced a new tokenized specially for these new models called &lt;strong&gt;harmony&lt;/strong&gt;. What stands out about this tokenizer from others is that it introduces a &lt;strong&gt;&amp;quot;channels&amp;quot;&lt;/strong&gt; concept that allows the model to separate the output between user-facing text and internal-facing outputs. Another interesting concept that it introduces is the &lt;strong&gt;&amp;quot;system message&amp;quot;&lt;/strong&gt;, which differs from the already known &amp;quot;system prompt&amp;quot;. The system message allows for &lt;strong&gt;configuration of dates&lt;/strong&gt; like: &amp;quot;Knowledge cutoff: 2024-06&amp;quot;, &amp;quot;Current date: 2025-06-28&amp;quot;. It also allows to &lt;strong&gt;set the reasoning effort&lt;/strong&gt; with &amp;quot;Reasoning: high&amp;quot;. Finally, it also allows the &lt;strong&gt;configuration of channels&lt;/strong&gt; and what are they used for and &lt;strong&gt;tools that the model can use&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;A great feature of these models is that it seems that OpenAI has optimized them to be able to easily fit in &lt;strong&gt;a single H100 80GB GPU&lt;/strong&gt; for the largest model and in &lt;strong&gt;a 16GB consumer GPU&lt;/strong&gt; for the small one. This was achieved using &lt;strong&gt;MXFP4 quantization&lt;/strong&gt; after training to 4.25 bits per parameter, which very significantly reduces the model size. While it is possible to natively train models in this quantization to reduce model quality degradation, it looks that in this case the quantization was applied after training.&lt;/p&gt;
&lt;p&gt;You can easily start using these models locally using Ollama. I recommend downloading the 20b model that fits in a consumer GPU. It runs really fast in my Macbook!&lt;/p&gt;
</description>
      <pubDate>Wed, 06 Aug 2025 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/links/gpt-oss/</guid>
    </item>
    <item>
      <title>[Quote] How we built our multi-agent research system</title>
      <link>https://ruxu.dev/links/anthropic-multiagent-research-system/</link>
      <description>&lt;p&gt;While reading Anthropic&#39;s great article &amp;quot;&lt;a href=&quot;https://www.anthropic.com/engineering/built-multi-agent-research-system&quot;&gt;How we built our multi-agent research system&lt;/a&gt;&amp;quot;, I stumbled upon this quote where Anthropic researchers present the results where they found that multi-agent systems outperform single-agents for complex tasks:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For example, when asked to identify all the board members of the companies in the Information Technology S&amp;amp;P 500, the multi-agent system found the correct answers by decomposing this into tasks for subagents, while the single agent system failed to find the answer with slow, sequential searches.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This makes a ton of sense to me. We know that LLMs do their best when the scope of the task they are given is as narrow as possible and when they have as much relevant context as possible. By using an orchestrator agent to decompose tasks and give them to sub-agents, we are effectively narrowing down the scope of the task, as well as slimming down the amount of context not relevant to the specific subtask that the sub-agent will do.&lt;/p&gt;
&lt;p&gt;Another interesting finding from this article is that Anthropic claims that 80% of the variance of results in the BrowseComp benchmark can be explained by more token usage:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In our analysis, three factors explained 95% of the performance variance in the BrowseComp evaluation (which tests the ability of browsing agents to locate hard-to-find information). We found that token usage by itself explains 80% of the variance, with the number of tool calls and the model choice as the two other explanatory factors.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This also makes using multiple agents more optimal, because they can use more tokens (because they do so in parallel) more efficiently (because agents are less likely to hit a context window limit where the performance starts to degrade if the context is separated for each subtask). It is also in the best interest of Anthropic that you burn tokens at 15x (according to them) the token rate with multi-agent architectures, so they get paid more. So take this with a grain of salt.&lt;/p&gt;
&lt;p&gt;I encourage you to read the whole article, as there are many very interesting tips for designing multi-agent applications.&lt;/p&gt;
</description>
      <pubDate>Sun, 15 Jun 2025 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/links/anthropic-multiagent-research-system/</guid>
    </item>
    <item>
      <title>[Link] Artificial Intelligence 3E: Foundations of computational agents</title>
      <link>https://ruxu.dev/links/what-is-an-agent/</link>
      <description>&lt;blockquote&gt;
&lt;p&gt;An agent is something that acts in an environment; it does something. Agents include worms, dogs, thermostats, airplanes, robots, humans, companies, and countries.
&lt;em&gt;Artificial Intelligence: Foundations of Computational Agents, 3rd edition by David L. Poole and Alan K. Mackworth, Cambridge University Press 2023&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is the definition I personally like the best for what agents are in the context of AI. Since the overuse of this word has left some of us confused on what it actually means, I would say that any application that uses AI and has the ability to act on its environment, through tools or function calling, is an agent.&lt;/p&gt;
</description>
      <pubDate>Sat, 07 Jun 2025 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/links/what-is-an-agent/</guid>
    </item>
    <item>
      <title>[Link] AGI is not multimodal</title>
      <link>https://ruxu.dev/links/agi-is-not-multimodal/</link>
      <description>&lt;blockquote&gt;
&lt;p&gt;A true AGI must be general across all domains. Any complete definition must at least include the ability to solve problems that originate in physical reality, e.g. repairing a car, untying a knot, preparing food, etc.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In this excellent article, Benjamin Spiegel argues that our current approach to building LLMs cannot lead to an AGI. While the current next-token prediction approach is really good at reflecting human-understanding of the world, not everything in this world can be expressed with language and not all valid language constructs are consistent with the world. Therefore, they are not actually learning world models, but just the minimum language patterns that are useful in our written mediums.&lt;/p&gt;
&lt;p&gt;Multimodal models can be seen as solving this problem, since they unite multiple ways to see the world in a single embedding space. However, in multimodal models different modalities are unnaturally separated in the training process. Instead of learning about something by interacting with it via different modalities, two models are separately trained for each modality and then artificially sewn together in the same embedding space.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Instead of pre-supposing structure in individual modalities, we should design a setting in which modality-specific processing emerges naturally.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In conclusion, while LLMs are still getting more capable, those gains are already diminishing and might hit a wall soon. To build a general model that is not constrained by the limitations of human language we should go back to the drawing board and come up with a perception system that can seamlessly unite all modalities.&lt;/p&gt;
&lt;p&gt;This article has also made me think about AI capabilities that are thriving today because they might not need to unite multiple modalities to form an understanding of that world. For example, programming. Software is built and executed in a digital environment and ruleset that can be easily encoded into plain text. I&#39;m genuinely curious if you need to know about anything about how the world works, apart from just how programming languages can be used (and maybe architecture of the computer and networks), to be a good programmer.&lt;/p&gt;
</description>
      <pubDate>Thu, 05 Jun 2025 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/links/agi-is-not-multimodal/</guid>
    </item>
    <item>
      <title>[Quote] Hype Coding - Steve Krouse</title>
      <link>https://ruxu.dev/links/hype-coding/</link>
      <description>&lt;blockquote&gt;
&lt;p&gt;There&#39;s a new kind of coding I call &amp;quot;hype coding&amp;quot; where you fully give into the hype, and what&#39;s coming right around the corner, that you lose sight of whats&#39; possible today. Everything is changing so fast that nobody has time to learn any tool, but we should aim to use as many as possible. Any limitation in the technology can be chalked up to a &#39;skill issue&#39; or that it&#39;ll be solved in the next AI release next week. Thinking is dead. Turn off your brain and let the computer think for you. Scroll on tiktok while the armies of agents code for you. If it isn&#39;t right, tell it to try again. Don&#39;t read. Feed outputs back in until it works. If you can&#39;t get it to work, wait for the next model or tool release. Maybe you didn&#39;t use enough MCP servers? Don&#39;t forget to add to the hype cycle by aggrandizing all your successes. Don&#39;t read this whole tweet, because it&#39;s too long. Get an AI to summarize it for you. Then call it &amp;quot;cope&amp;quot;. Most importantly, immediately mischaracterize &amp;quot;hype coding&amp;quot; to mean something different than this definition. Oh the irony! The people who don&#39;t care about details don&#39;t read the details about not reading the details&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I would summarize this sarcastic piece by Steve Krouse by reminding everyone that, while it&#39;s fun to try new technologies, it&#39;s important not to fall victim of the hype and always use the latest, shiniest, new thing for everything. Instead of choosing a tool based on the hype around it, and what people say can do or will be able to do, assess the tool objectively in your workflow. If it makes YOU more productive, by all means, use it. If it doesn&#39;t, don&#39;t worry, the fad will die down eventually.&lt;/p&gt;
</description>
      <pubDate>Wed, 04 Jun 2025 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/links/hype-coding/</guid>
    </item>
    <item>
      <title>[Link] OpenAI Codex CLI</title>
      <link>https://ruxu.dev/links/codex/</link>
      <description>&lt;p&gt;Together with the &lt;a href=&quot;https://openai.com/index/introducing-o3-and-o4-mini/&quot; target=&quot;_blank&quot;&gt;launch of the o3 and o4-mini reasoning models&lt;/a&gt;, OpenAI has released a coding assitant for the terminal: Codex.&lt;/p&gt;
&lt;p&gt;Codex is meant to be used with OpenAI models. You can use it to create new projects, make changes to existing projects or ask the model to explain code to you, all in the terminal. It can use multimodal input (e.g. screenshots). It also allows sandboxing your development environment to secure your computer. It also allows the use of context files, &lt;code&gt;~/.codex/instructions.md&lt;/code&gt; for global instructions for Codex and &lt;code&gt;codex.md&lt;/code&gt; in the project root for project-specific context.&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;Full-auto&lt;/code&gt; mode, Codex can not only read and write files, but also run shell commands in an environment confined around the current directory and with network disabled. However, OpenAI suggests that in the future, you will be able to whitelist some shell commands to run with network enabled, once they have polished some security concerns.&lt;/p&gt;
&lt;p&gt;You can install codex via npm:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; @openai/codex&lt;/code&gt;&lt;/pre&gt;
</description>
      <pubDate>Wed, 16 Apr 2025 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/links/codex/</guid>
    </item>
    <item>
      <title>[Link] GPT 4.1</title>
      <link>https://ruxu.dev/links/gpt-4-1/</link>
      <description>&lt;p&gt;After the unimpressive release of GPT-4.5 a month and a half ago, OpenAI is now releasing a new version - backwards. Today, they released three new models, exclusive to the API: &lt;code&gt;GPT-4.1&lt;/code&gt;, &lt;code&gt;GPT-4.1 mini&lt;/code&gt; and &lt;code&gt;GPT-4.1 nano&lt;/code&gt;. In the benchmarks, GPT-4.1 easily beats GPT-4.5 at a lower price and higher speed. For this reason, OpenAI has said they will be deprecating GPT-4.5 in 3 months time.&lt;/p&gt;
&lt;p&gt;While this is a good step ahead for OpenAI, they are still a bit behind Claude and Gemini in some key benchmarks. In SWE-bench, GPT-4.1 gets a 55%, against 70% for Claude 3.7 Sonnet and 64% for Gemini 2.5 Pro. In Aider Polyglot, GPT-4.1 gets 53%, while Claude 3.7 Sonnet gets 65% and Gemini 2.5 Pro gets 69%.&lt;/p&gt;
&lt;p&gt;On the other hand, GPT-4.1 nano offers a similar price and latency as Gemini Flash 2.0. If the performance of this small model is comparable to Gemini Flash, it can be a great option for simple tasks.&lt;/p&gt;
</description>
      <pubDate>Mon, 14 Apr 2025 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/links/gpt-4-1/</guid>
    </item>
    <item>
      <title>[Link] The Agent2Agent Protocol</title>
      <link>https://ruxu.dev/links/a2a/</link>
      <description>&lt;p&gt;Just in the middle of the year of agents, Google has released two great tools for building agents: the &lt;a href=&quot;https://google.github.io/A2A/&quot; target=&quot;_blank&quot;&gt;Agent2Agent (A2A)&lt;/a&gt; protocol and the &lt;a href=&quot;https://google.github.io/adk-docs/&quot; target=&quot;_blank&quot;&gt;Agent Development Kit (ADK)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The Agent2Agent Protocol is based on &lt;a href=&quot;https://www.jsonrpc.org/specification&quot; target=&quot;_blank&quot;&gt;JSON RPC&lt;/a&gt;, working both over plain HTTP and &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events&quot; target=&quot;_blank&quot;&gt;SSE&lt;/a&gt;. It is also built with security in mind, it implements the &lt;a href=&quot;https://swagger.io/docs/specification/v3_0/authentication/&quot; target=&quot;_blank&quot;&gt;OpenAPI Authentication Specification&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The agents published using this protocol will advertise themselves to other agents via the Agent Card, which by default can be found at the path &lt;code&gt;https://agent_url/.well-known/agent.json&lt;/code&gt;. The Agent Card will include information about the agent&#39;s capabilities and requirements, which will help other agents decide to ask it for help or not.&lt;/p&gt;
&lt;p&gt;The specification includes definitions for these concepts, which agents can use to exchange between themselves: Task, Artifact, Message, Part and Push Notification.&lt;/p&gt;
&lt;p&gt;This new protocol is not meant to replace &lt;a href=&quot;https://modelcontextprotocol.io/introduction&quot; target=&quot;_blank&quot;&gt;Anthropic&#39;s Model Context Protocol&lt;/a&gt;. They are actually meant to work together. While MCP allows agents to have access to external tools and data sources, A2A allows agents to communicate and work together.&lt;/p&gt;
</description>
      <pubDate>Sat, 12 Apr 2025 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/links/a2a/</guid>
    </item>
    <item>
      <title>[Quote] LMArena on X</title>
      <link>https://ruxu.dev/links/lmarena-llama4/</link>
      <description>&lt;blockquote&gt;
&lt;p&gt;Meta should have made it clearer that “Llama-4-Maverick-03-26-Experimental” was a customized model to optimize for human preference. As a result of that we are updating our leaderboard policies to reinforce our commitment to fair, reproducible evaluations so this confusion doesn’t occur in the future.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We now have acknowledgement from LMArena of what we already knew: AI labs are cheating to get their models as high as possible in the LMArena leaderboard / benchmarks.&lt;/p&gt;
&lt;p&gt;This is inevitable, all of them want to win the AI race at any cost. If you don&#39;t want to be fooled by ever-slightly-increasing benchmarks, you should set up your own benchmarks that measure their performance on your own use cases.&lt;/p&gt;
</description>
      <pubDate>Tue, 08 Apr 2025 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/links/lmarena-llama4/</guid>
    </item>
    <item>
      <title>[Link] The Llama 4 herd</title>
      <link>https://ruxu.dev/links/llama4/</link>
      <description>&lt;p&gt;Meta has finally released the Llama 4 family of models that Zuckerberg hyped up so much. The Llama 4 models are open-source, multi-modal, mixture-of-experts models. First impression, these models are massive. None of these models will be able to run in the average computer with a decent GPU or any single Mac Mini. This is what we have:&lt;/p&gt;
&lt;h3 id=&quot;llama-4-scout&quot; tabindex=&quot;-1&quot;&gt;Llama 4 Scout&lt;/h3&gt;
&lt;p&gt;The small model in the family. A mixture-of-experts with 16 experts, totaling 109B parameters. According to Meta, after an int-4 quantization, it fits in an H100 GPU, which is 80GB of VRAM. It&#39;s officially the model with the largest context window ever, with a supported 10M context window. However, a large context window takes a big toll on the already high VRAM requirements, so you might want to keep the context window contained. As they &lt;a href=&quot;https://github.com/meta-llama/llama-cookbook/blob/main/getting-started/build_with_llama_4.ipynb&quot; target=&quot;_blank&quot;&gt;themselves write in their new cookbook example notebook for Llama 4&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Scout supports up to 10M context. On 8xH100, in bf16 you can get upto 1.4M tokens.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;llama-4-maverick&quot; tabindex=&quot;-1&quot;&gt;Llama 4 Maverick&lt;/h3&gt;
&lt;p&gt;The mid-sized model. This one has 128 experts, totaling 400B parameters. This one &amp;quot;only&amp;quot; features a 1M context window, due to its larger size. Maverick, as of today, has reached the second place in &lt;a href=&quot;https://lmarena.ai/?leaderboard&quot; target=&quot;_blank&quot;&gt;LMArena&lt;/a&gt; with 1417 ELO, only surpassed by Gemini 2.5 Pro. Which is scary, knowing this is not even the best model in the family.&lt;/p&gt;
&lt;h3 id=&quot;llama-4-behemoth&quot; tabindex=&quot;-1&quot;&gt;Llama 4 Behemoth&lt;/h3&gt;
&lt;p&gt;The big brother in the family. 16 experts, 2 &lt;strong&gt;TRILLION&lt;/strong&gt; parameters. Easily surpasses Llama 3.1 405B, which was the largest Llama model until today. This model has not yet been released, as according to Meta is still training, so we don&#39;t know anything about its capabilities.&lt;/p&gt;
&lt;h3 id=&quot;llama-4-reasoning&quot; tabindex=&quot;-1&quot;&gt;Llama 4 Reasoning&lt;/h3&gt;
&lt;p&gt;We have no details on what it&#39;s going to be, just the announcement that &lt;a href=&quot;https://www.llama.com/llama4-reasoning-is-coming/&quot; target=&quot;_blank&quot;&gt;it&#39;s coming soon&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Overall, these look like very capable frontier models that can compete with OpenAI, Anthropic and Google while at the same time being open-source, which is a huge win. Check out Meta&#39;s &lt;a href=&quot;https://ai.meta.com/blog/llama-4-multimodal-intelligence/&quot; target=&quot;_blank&quot;&gt;post on the models&#39; architecture and benchmarks&lt;/a&gt; and also check the models on &lt;a href=&quot;https://huggingface.co/collections/meta-llama/llama-4-67f0c30d9fe03840bc9d0164&quot; target=&quot;_blank&quot;&gt;HuggingFace&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Sun, 06 Apr 2025 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/links/llama4/</guid>
    </item>
    <item>
      <title>[Link] Circuit Tracing: Revealing Computational Graphs in Language Models</title>
      <link>https://ruxu.dev/links/transformer-circuits/</link>
      <description>&lt;p&gt;A group of Anthropic-affiliated scientists has released a paper where they study how human concepts are represented across Claude 3.5 Haiku&#39;s neurons and how these features interact to produce model outputs.&lt;/p&gt;
&lt;p&gt;This is a specially difficult task since these concepts are not contained within a single neuron. Neurons are &lt;code&gt;polysemantic&lt;/code&gt;, meaning that they encode multiple unrelated concepts in its representation. To make matters worse, &lt;code&gt;superposition&lt;/code&gt; makes it so the representation of features are built from a combination of multiple neurons, not just one.&lt;/p&gt;
&lt;p&gt;In this paper, the researches build a Local Replacement Model, where they replace the neural network&#39;s components with a simpler, interpretable function that mimics its behavior. Also, for each prompt, they show many Attribution Graph that help visualize how the model processes information and how the features smeared across the model&#39;s neurons influence its outputs.&lt;/p&gt;
&lt;p&gt;Also check out the companion paper: &lt;a href=&quot;https://transformer-circuits.pub/2025/attribution-graphs/biology.html&quot; target=&quot;_blank&quot;&gt;On the Biology of a Large Language Model&lt;/a&gt;. In this paper the researchers also use interactive Attribution Graphs to study how models can think ahead of time to perform complex text generations that require the model to think through many steps to answer.&lt;/p&gt;
</description>
      <pubDate>Sun, 30 Mar 2025 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/links/transformer-circuits/</guid>
    </item>
    <item>
      <title>How to Write a Good index.html File</title>
      <link>https://ruxu.dev/articles/web/html-starter-template/</link>
      <description>&lt;p&gt;Every web developer has been there: you&#39;re starting a new project and staring at an empty file called &lt;code&gt;index.html&lt;/code&gt;. You try to remember, which tags were meant to go in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; again? Which are the meta tags that are best practice and which ones are deprecated?&lt;/p&gt;
&lt;p&gt;Recently, I found myself in this exact situation. My first instinct was to copy the head section from a previous project, but as I reviewed the code, I realized some tags were outdated or simply didn&#39;t apply to my new project. What followed was a deep dive into HTML head tags – which ones are essential, which are optional, and which are just cluttering my code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If you&#39;re in a hurry and just want the template:&lt;/strong&gt; You can find my complete starter template on &lt;a href=&quot;https://github.com/rogiia/html-starter-template&quot;&gt;GitHub&lt;/a&gt;. The repository contains two main files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;index.html&lt;/code&gt;: A clean, minimalist template with just what you need and no unnecessary extras.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;index-commented.html&lt;/code&gt;: The same template but with detailed comments explaining how and why you should use each tag.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This article is essentially a deep dive into the comments from the &lt;code&gt;index-commented.html&lt;/code&gt; file, providing more context and explanations for each decision made in the template.&lt;/p&gt;
&lt;p&gt;This template represents my opinionated approach after researching current best practices. It aims to be a solid foundation for most web projects while maintaining good performance, accessibility, and search engine optimization.&lt;/p&gt;
&lt;p&gt;Let&#39;s dive into the essential components of a well-structured HTML head.&lt;/p&gt;
&lt;h3 id=&quot;the-tags-you-must-include&quot; tabindex=&quot;-1&quot;&gt;The tags you must include&lt;/h3&gt;
&lt;p&gt;These tags should be present in virtually every HTML document you create. They&#39;re essential for proper rendering, SEO, and accessibility.&lt;/p&gt;
&lt;h4 id=&quot;doctype-html-and-lang-en-setting-the-document-type-and-language&quot; tabindex=&quot;-1&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/code&gt; and &lt;code&gt;lang=&amp;quot;en&amp;quot;&lt;/code&gt;: Setting the document type and language&lt;/h4&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token doctype&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;!&lt;/span&gt;&lt;span class=&quot;token doctype-tag&quot;&gt;DOCTYPE&lt;/span&gt; &lt;span class=&quot;token name&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;en&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Always begin your HTML document with the doctype declaration. This tells browsers which version of HTML you&#39;re using (in this case, HTML5) and helps ensure consistent rendering. The &lt;code&gt;lang&lt;/code&gt; attribute on the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; tag specifies the language of your page - this is crucial for screen readers, search engines, and browsers. If your content is in a different language, change the code accordingly (e.g., &lt;code&gt;lang=&amp;quot;es&amp;quot;&lt;/code&gt; for Spanish).&lt;/p&gt;
&lt;h4 id=&quot;title-the-page-title&quot; tabindex=&quot;-1&quot;&gt;&lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt;: The page title&lt;/h4&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Hello world!&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Every HTML document must have a title tag. This text appears in browser tabs, bookmarks, and search engine results. Make your titles descriptive yet concise, ideally under 60 characters. A good title both informs users about your page content and includes relevant keywords for SEO.&lt;/p&gt;
&lt;h4 id=&quot;meta-name-viewport-configuring-viewport-for-responsive-design&quot; tabindex=&quot;-1&quot;&gt;&lt;code&gt;&amp;lt;meta name=&amp;quot;viewport&amp;quot;&amp;gt;&lt;/code&gt;: Configuring viewport for responsive design&lt;/h4&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;viewport&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In today&#39;s mobile-first world, this meta tag is non-negotiable. It tells mobile browsers how to control the page&#39;s dimensions and scaling. Let&#39;s break down what each parameter does:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;viewport-fit=cover&lt;/code&gt;: Ensures content extends to the edge of the display (especially important for notched phones)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;width=device-width&lt;/code&gt;: Sets the width of the page to follow the screen width of the device&lt;/li&gt;
&lt;li&gt;&lt;code&gt;initial-scale=1.0&lt;/code&gt;: Sets the initial zoom level when the page is first loaded&lt;/li&gt;
&lt;li&gt;&lt;code&gt;minimum-scale=1.0&lt;/code&gt;: Prevents users from zooming out too much&lt;/li&gt;
&lt;li&gt;&lt;code&gt;maximum-scale=5.0&lt;/code&gt;: Allows users to zoom in up to 5x (limiting this completely would harm accessibility)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Without this tag, mobile devices will render pages at a typical desktop screen width and then scale them down, resulting in tiny, unreadable text and forcing users to zoom and pan.&lt;/p&gt;
&lt;h4 id=&quot;meta-name-description-meta-name-keywords-meta-name-author-essential-meta-information&quot; tabindex=&quot;-1&quot;&gt;&lt;code&gt;&amp;lt;meta name=&amp;quot;description&amp;quot;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;meta name=&amp;quot;keywords&amp;quot;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;meta name=&amp;quot;author&amp;quot;&amp;gt;&lt;/code&gt;: Essential meta information&lt;/h4&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;description&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;keywords&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;author&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These meta tags provide important information about your page:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;description&lt;/code&gt;: A concise summary of your page content (ideally 150-160 characters). This often appears in search engine results below your title.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;keywords&lt;/code&gt;: Relevant keywords for your page content. While less important for Google these days, other search engines and crawlers may still use this information.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;author&lt;/code&gt;: The name of the individual or organization that created the page.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While these tags don&#39;t directly affect page rendering, they&#39;re valuable for SEO and content categorization.&lt;/p&gt;
&lt;h4 id=&quot;link-rel-canonical-avoiding-duplicate-indexation&quot; tabindex=&quot;-1&quot;&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;canonical&amp;quot;&amp;gt;&lt;/code&gt;: Avoiding duplicate indexation&lt;/h4&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;canonical&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This tag helps search engines avoid indexing the same content multiple times when it&#39;s accessible via different URLs. For example, if your page is accessible via multiple URLs (like &lt;code&gt;example.com/page&lt;/code&gt; and &lt;code&gt;example.com/page/index.html&lt;/code&gt;), the canonical tag tells search engines which URL is the &amp;quot;official&amp;quot; version to index, preventing duplicate indexation which can harm your search rankings.&lt;/p&gt;
&lt;p&gt;Fill in the &lt;code&gt;href&lt;/code&gt; attribute with the primary URL you want search engines to associate with this content.&lt;/p&gt;
&lt;h4 id=&quot;css-loading-strategies-critical-inline-css-vs-external-stylesheets&quot; tabindex=&quot;-1&quot;&gt;CSS loading strategies: Critical inline CSS vs. external stylesheets&lt;/h4&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token style&quot;&gt;&lt;span class=&quot;token language-css&quot;&gt;
  &lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #fefefe&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #222&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Roboto&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sans-serif&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;line-height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1.8&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;preload&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;main.css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;onload&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token value javascript language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;onload&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rel&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;stylesheet&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;noscript&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;main.css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;noscript&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This strategy for CSS loading optimizes performance in two ways:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Inline critical CSS&lt;/strong&gt;: By embedding essential styles directly in the HTML document, you avoid making an additional network request that would block rendering. This makes critical styles load blazingly fast and prevents the Flash of Unstyled Content (FOUC) that can occur when styles load after content.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Asynchronous loading for non-critical CSS&lt;/strong&gt;: The preload technique with the onload handler allows the main stylesheet to load without blocking rendering. This means your page can start displaying while the rest of the styles are still loading, creating a better user experience. The noscript tag provides a fallback for users with JavaScript disabled.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Alternatively, if your site doesn&#39;t have significant styling needs above the fold, you can use a simpler approach:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;main.css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is more straightforward but can slow initial rendering as the browser must download and parse the CSS before displaying content.&lt;/p&gt;
&lt;h4 id=&quot;script-script-loading-best-practices&quot; tabindex=&quot;-1&quot;&gt;&lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;: Script loading best practices&lt;/h4&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;module&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;app.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For JavaScript, the &lt;code&gt;type=&amp;quot;module&amp;quot;&lt;/code&gt; attribute offers several advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Automatically defers script loading until the DOM is ready&lt;/li&gt;
&lt;li&gt;Enables ECMAScript modules for better code organization&lt;/li&gt;
&lt;li&gt;Runs in strict mode by default&lt;/li&gt;
&lt;li&gt;Allows for cleaner dependency management&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For scripts that don&#39;t depend on DOM elements and should run as soon as possible, consider adding the &lt;code&gt;async&lt;/code&gt; attribute:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;module&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;analytics.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Additionally, it&#39;s good practice to register a service worker for offline capabilities:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;serviceWorker&#39;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;load&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;serviceWorker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/service-worker.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This script is placed without &lt;code&gt;defer&lt;/code&gt; or &lt;code&gt;async&lt;/code&gt; attributes so it loads and executes as soon as possible, enabling offline capabilities early in the page load process. The service worker runs in the background, independent of your web page, allowing it to handle network requests and caching even when the user navigates away from your site.&lt;/p&gt;
&lt;h3 id=&quot;the-tags-you-maybe-should-include&quot; tabindex=&quot;-1&quot;&gt;The tags you maybe should include&lt;/h3&gt;
&lt;p&gt;These tags aren&#39;t necessary for every project but can be valuable in specific situations. Include them based on your project&#39;s needs.&lt;/p&gt;
&lt;h4 id=&quot;meta-charset-utf-8-character-encoding&quot; tabindex=&quot;-1&quot;&gt;&lt;code&gt;&amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;/code&gt;: Character encoding&lt;/h4&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;utf-8&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This meta tag specifies the character encoding for your HTML document. UTF-8 is already the default character encoding in HTML5, so this tag isn&#39;t strictly necessary in many cases. However, including it explicitly ensures consistency across all browsers and prevents potential character rendering issues, especially with special characters or non-Latin alphabets.&lt;/p&gt;
&lt;h4 id=&quot;base-href-defining-a-base-url&quot; tabindex=&quot;-1&quot;&gt;&lt;code&gt;&amp;lt;base href=&amp;quot;/&amp;quot;&amp;gt;&lt;/code&gt;: Defining a base URL&lt;/h4&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;base&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The base tag specifies the base URL for all relative URLs in a document. If all your site&#39;s URLs are already relative to the root path (&amp;quot;/&amp;quot;), you don&#39;t need to include this tag. It&#39;s primarily useful when your site is hosted in a subdirectory but you want paths to be relative to the domain root, or when developing single-page applications with client-side routing.&lt;/p&gt;
&lt;h4 id=&quot;meta-name-application-name-application-details&quot; tabindex=&quot;-1&quot;&gt;&lt;code&gt;&amp;lt;meta name=&amp;quot;application-name&amp;quot;&amp;gt;&lt;/code&gt;: Application details&lt;/h4&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;application-name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If your Progressive Web App (PWA) should have a different name than what&#39;s specified in your title tag, use this meta tag. It defines the name that will appear when your web application is installed on a device or pinned to a user&#39;s start menu or taskbar.&lt;/p&gt;
&lt;h4 id=&quot;meta-name-theme-color-browser-ui-theme-color&quot; tabindex=&quot;-1&quot;&gt;&lt;code&gt;&amp;lt;meta name=&amp;quot;theme-color&amp;quot;&amp;gt;&lt;/code&gt;: Browser UI theme color&lt;/h4&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;theme-color&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;#33d&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This meta tag defines the color used by the user agent in the UI elements around your page, such as the browser&#39;s address bar in mobile browsers or the title bar in some desktop browsers. Choose a color that reflects your brand identity to create a more integrated visual experience.&lt;/p&gt;
&lt;h4 id=&quot;meta-name-color-scheme-light-and-dark-mode-support&quot; tabindex=&quot;-1&quot;&gt;&lt;code&gt;&amp;lt;meta name=&amp;quot;color-scheme&amp;quot;&amp;gt;&lt;/code&gt;: Light and dark mode support&lt;/h4&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;color-scheme&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;light dark&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This tag informs the browser if your site supports light mode, dark mode, or both. The value &lt;code&gt;&amp;quot;light dark&amp;quot;&lt;/code&gt; means that both schemes are supported, with light being preferred. This helps browsers render form controls, scrollbars, and other UI elements in the appropriate color scheme, creating a better user experience that respects system preferences.&lt;/p&gt;
&lt;h4 id=&quot;meta-property-og-social-media-integration-with-open-graph&quot; tabindex=&quot;-1&quot;&gt;&lt;code&gt;&amp;lt;meta property=&amp;quot;og:&amp;quot;&amp;gt;&lt;/code&gt;: Social media integration with Open Graph&lt;/h4&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:title&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:type&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;website&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:url&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Open Graph meta tags optimize how your content appears when shared on social media platforms like Facebook, LinkedIn, and X (formerly Twitter). While not essential for basic functionality, they significantly improve the appearance and engagement of your content when shared.&lt;/p&gt;
&lt;p&gt;Key Open Graph tags include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;og:title&lt;/code&gt;: The title of your page/content (can differ from your HTML title)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;og:type&lt;/code&gt;: The type of content (website, article, product, etc.)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;og:url&lt;/code&gt;: The canonical URL of your page&lt;/li&gt;
&lt;li&gt;&lt;code&gt;og:image&lt;/code&gt;: The URL to an image representing your content&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If your site&#39;s content is likely to be shared on social platforms, filling these tags with appropriate values can dramatically improve click-through rates and engagement.&lt;/p&gt;
&lt;h4 id=&quot;link-rel-manifest-and-link-rel-icon-pwa-support-and-favicons&quot; tabindex=&quot;-1&quot;&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;manifest&amp;quot;&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;link rel=&amp;quot;icon&amp;quot;&amp;gt;&lt;/code&gt;: PWA support and favicons&lt;/h4&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;manifest&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;manifest.json&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;icon&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/favicon.ico&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;image/x-icon&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For Progressive Web Apps, use the manifest link to point to a JSON file that contains your app&#39;s metadata, including icons. The manifest should include your app&#39;s icons in various sizes for different devices and contexts.&lt;/p&gt;
&lt;p&gt;For regular websites that aren&#39;t PWAs, use the icon link to define your site&#39;s favicon. While technically optional, a favicon helps with brand recognition and user experience, so most sites should include one.&lt;/p&gt;
&lt;h4 id=&quot;link-rel-alternate-alternate-content-types-for-your-site&quot; tabindex=&quot;-1&quot;&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;alternate&amp;quot;&amp;gt;&lt;/code&gt;: Alternate Content Types for your site&lt;/h4&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;alternate&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;application/rss+xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/feed.xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;alternate&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text/markdown&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/llms.txt&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This link tag serves multiple purposes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;It helps RSS readers and other feed aggregators discover your site&#39;s RSS feed. Include it if your site provides an RSS feed (common for blogs, news sites, or regularly updated content collections).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It can also be used to specify an &lt;code&gt;llms.txt&lt;/code&gt; file for your site as a &lt;code&gt;type=&amp;quot;text/markdown&amp;quot;&lt;/code&gt; alternate link. This file provides your site&#39;s content in an easy to digest format for Large Language Models scanning your site. &lt;strong&gt;Note:&lt;/strong&gt; I stole that idea from &lt;a href=&quot;https://www.gilesthomas.com/2025/03/llmstxt&quot;&gt;Giles Thomas&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If your site doesn&#39;t offer these features, you can safely omit these tags.&lt;/p&gt;
&lt;h4 id=&quot;link-rel-preload-link-rel-preconnect-link-rel-prefetch-resource-optimization&quot; tabindex=&quot;-1&quot;&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;preload&amp;quot;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;link rel=&amp;quot;preconnect&amp;quot;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;link rel=&amp;quot;prefetch&amp;quot;&amp;gt;&lt;/code&gt;: Resource optimization&lt;/h4&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;preload&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&amp;amp;display=swap&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;onload&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token value javascript language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;onload&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rel&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;stylesheet&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;preconnect&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://fonts.gstatic.com&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;prefetch&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/next-page.html&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These link tags help optimize resource loading:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;preload&lt;/code&gt;: Tells the browser to download and cache a resource as soon as possible. Useful for critical resources needed early in the rendering process, like fonts or important images.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;preconnect&lt;/code&gt;: Establishes an early connection to external domains from which you&#39;ll fetch resources later. This saves time by having the connection ready when needed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prefetch&lt;/code&gt;: Suggests to the browser that a resource might be needed for future navigation. The browser will download it when idle, making subsequent page loads faster.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Use these selectively based on your performance needs. Over-using them can waste bandwidth, so focus on truly critical resources.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;This template gives you a solid starting point for any web project. Of course, this template is completely opinionated and the best setup for your needs may vary. If I left out some common tags from the template, it&#39;s probably because they are not needed, at least for most cases.&lt;/p&gt;
&lt;p&gt;I welcome your feedback! If you think I&#39;ve missed something important, please open an issue or submit a pull request on the &lt;a href=&quot;https://github.com/rogiia/html-starter-template&quot;&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Also, if you want a starter template that goes further than just the index.html file, you might want to check out &lt;a href=&quot;https://html5boilerplate.com/&quot;&gt;HTML5 Boilerplate&lt;/a&gt;. It&#39;s a great resource to get up an running really fast when building a Progressive Web App.&lt;/p&gt;
&lt;h3 id=&quot;resources&quot; tabindex=&quot;-1&quot;&gt;Resources&lt;/h3&gt;
&lt;p&gt;If you want to read more about HTML head tags, I suggest starting here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Structuring_content/Webpage_metadata&quot;&gt;Mozilla Web Documentation: Metadata in HTML&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/learn/html/metadata&quot;&gt;web.dev by Google&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ogp.me/&quot;&gt;The Open Graph Protocol&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://w3c.github.io/manifest/&quot;&gt;Web App Manifest specification&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And once more, you can find the my index.html template on &lt;a href=&quot;https://github.com/rogiia/html-starter-template&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Sun, 23 Mar 2025 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/articles/web/html-starter-template/</guid>
    </item>
    <item>
      <title>HTML Starter Template</title>
      <link>https://ruxu.dev/projects/html-starter-template/</link>
      <description>&lt;h2 id=&quot;motivation&quot; tabindex=&quot;-1&quot;&gt;Motivation&lt;/h2&gt;
&lt;p&gt;For all of us how can&#39;t remember any of the tags we should/shouldn&#39;t include in the HTML head or which ones are now deprecated because they used to be a hack for IE6.&lt;/p&gt;
&lt;h2 id=&quot;what-is-it&quot; tabindex=&quot;-1&quot;&gt;What is it?&lt;/h2&gt;
&lt;p&gt;There are two index.html files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A regular index.html with just what you need to have and no bullshit.&lt;/li&gt;
&lt;li&gt;An index-commented.html with comments explaining how and why you should use each tag.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The commented version includes two types of comments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ALWAYS&lt;/strong&gt;: In my opinion, you should always use those tags.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MAYBE&lt;/strong&gt;: You should or shouldn&#39;t use those tags in certain situations or are a matter of preference.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;contributing&quot; tabindex=&quot;-1&quot;&gt;Contributing&lt;/h2&gt;
&lt;p&gt;Feel free to open an Issue or PR if you think I missed anything.&lt;/p&gt;
&lt;h2 id=&quot;license&quot; tabindex=&quot;-1&quot;&gt;License&lt;/h2&gt;
&lt;p&gt;CC0: This work has been marked as dedicated to the public domain.&lt;/p&gt;
</description>
      <pubDate>Sat, 22 Mar 2025 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/projects/html-starter-template/</guid>
    </item>
    <item>
      <title>[Link] Claude Think Tool</title>
      <link>https://ruxu.dev/links/think-tool/</link>
      <description>&lt;p&gt;The Anthropic team has discovered an interesting approach to LLM thinking capabilities. Instead of making the model think deeply before answering or taking an action, they experimented with giving the model a &lt;strong&gt;think tool&lt;/strong&gt;. The think tool does nothing but register a thought in the state. However, it does allow the model to decide when it&#39;s appropriate to stop and think more carefully about the current state and the best approach to move forward.&lt;/p&gt;
&lt;p&gt;The thinking done using the think tool will not be as deep and it will be more focused on newly obtained information. Therefore, the think tool is specially useful when the model has to carefully analyze the outputs of complex tools and act on them thoughtfully.&lt;/p&gt;
</description>
      <pubDate>Sat, 22 Mar 2025 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/links/think-tool/</guid>
    </item>
    <item>
      <title>[Quote] 🔭 The Einstein AI model</title>
      <link>https://ruxu.dev/links/the-einstein-ai-model/</link>
      <description>&lt;blockquote&gt;
&lt;p&gt;These benchmarks test if AI models can find the right answers to a set of questions we already know the answer to.
However, real scientific breakthroughs will come not from answering known questions, but from asking challenging new questions and questioning common conceptions and previous ideas.
&lt;strong&gt;- Thomas Wolf&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Interesting reflection from Thomas from HuggingFace. Current LLMs have limited potential to make breakthroughs since they cannot &amp;quot;think out-of-the-box&amp;quot; from their training data. We might be able to give the LLMs the ability to explore outside their known world by mechanisms like reinforcement learning + live environment feedback, or other mechanisms that we haven&#39;t thought about yet. Still, significant breakthroughs will be hard for LLMs since the real breakthroughs that make a huge impact are usually very far away from established knowledge - very far from the AI model&#39;s current probability space.&lt;/p&gt;
</description>
      <pubDate>Wed, 12 Mar 2025 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/links/the-einstein-ai-model/</guid>
    </item>
    <item>
      <title>About the Dead Internet Theory and AI</title>
      <link>https://ruxu.dev/articles/ai/dead-internet-theory/</link>
      <description>&lt;figure&gt;
&lt;img style=&quot;width: auto&quot; alt=&quot;Peter Steiner&#39;s 1993 cartoon, as published in The New Yorker&quot; src=&quot;https://ruxu.dev/articles/ai/dead-internet-theory/assets/images/dead-internet-theory/Internet_dog.jpg&quot; /&gt;
&lt;figcaption&gt;On the Internet nobody knows you are a dog... or an LLM&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The Dead Internet Theory is a thought that has gained a lot of traction recently. I have to admit, the first time it was explained to me, I felt an eerie realization. Like I had already been experiencing it, but I hadn&#39;t paid too much attention to it. The first moment, I felt scared for the future and nostalgic for the past. But that&#39;s an old man&#39;s attitude, to be so resistant of change. After that moment, I started reflecting. How did we get here? And how can we prevent the Internet from continuing down this concerning path?&lt;/p&gt;
&lt;h3 id=&quot;what-is-the-dead-internet-theory&quot; tabindex=&quot;-1&quot;&gt;What Is The &amp;quot;Dead Internet Theory&amp;quot;?&lt;/h3&gt;
&lt;p&gt;The main premise of the Dead Internet Theory is an outrageous statement that challenges our view of the state of the Internet:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The Internet feels empty and devoid of people.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This theory originated in a &lt;a href=&quot;https://i.4pcdn.org/x/1587947548944.png&quot;&gt;4chan post&lt;/a&gt; around 2019. This 4chan anonymous user writes his recent experience on the current state of the Internet. While his tone is pretty outrageous and paranoid (as is expected of a 4chan board), he raises some valid concerns that resonate with many other Internet users. This has led to this hypothesis gaining a lot of traction online and others sharing their own experiences and thoughts on it on other Internet boards.&lt;/p&gt;
&lt;p&gt;So what do they mean by empty and devoid of people? There&#39;s plenty of people on the Internet, right? I believe there&#39;s two factors to it.&lt;/p&gt;
&lt;p&gt;First, we are &lt;strong&gt;increasingly interacting less directly with other humans&lt;/strong&gt;. Now we are talking to an &amp;quot;audience&amp;quot;. But really we are talking to the recommendation algorithm, our god, so it graces our posts with engagement. When we post on &lt;em&gt;social&lt;/em&gt; networks, we don&#39;t expect our friends and relatives to see and interact with it. We expect strangers we don&#39;t know or care about to like it. This impersonal relationship is making the Internet less social and more of a hustle.&lt;/p&gt;
&lt;p&gt;Second, an &lt;strong&gt;increasing amount of users of the Internet are not people&lt;/strong&gt;. They are bots. Fake profiles that algorithmically play the viral content game to gain influence on the social platforms. Advertisement and/or scam e-mails, messages or even calls massively horizontally scaled thanks to bots. &lt;a href=&quot;https://hallofdreams.org/posts/physicsforums/&quot;&gt;Generative AI answering questions on behalf of actual people on PhysicsForums&lt;/a&gt; and other forums like StackOverflow.&lt;/p&gt;
&lt;p&gt;The Internet was supposed to connect people all around the world. And it did that, beautifully. But for the last years, it&#39;s been going in the opposite direction. It&#39;s driving us apart, isolating us from other people and keeping us content with experiencing an Internet massivelly filled with content, without the need to interact with other people.&lt;/p&gt;
&lt;h3 id=&quot;is-it-really-that-bad&quot; tabindex=&quot;-1&quot;&gt;Is It Really That Bad?&lt;/h3&gt;
&lt;p&gt;To be fair, it&#39;s not like nobody uses the Internet to communicate with anyone anymore. Messaging apps are very prevalent and the users of these apps are mostly human. We talk with our friends, make plans, catch up with people that are not as much in our lives as they used to. But this is a &lt;strong&gt;private&lt;/strong&gt; Internet, not an open Internet. A private chat is not meant to be shared, discovered by people interested on what you are talking about or build a little garden in a corner of the Internet that&#39;s just yours.&lt;/p&gt;
&lt;p&gt;Also, &lt;strong&gt;people are not interacting with the Internet like they used to&lt;/strong&gt;. I believe the rise of smartphones has contributed to that greatly. Smartphones have been very optimized for consuming content, and especially for &lt;strong&gt;infinite, mindless scrolling&lt;/strong&gt;. It&#39;s much more lucrative for your app to have your users trapped in an infinite scroll, consuming content (and ads) by the ton, than to have them create and share. And to achieve that, they provide (impose on) you an amazing recommendation algorithm that will play your psychology to keep you engaged. But if people are only consuming, they are not interacting, discussing, or building. You see a lot of people on your feed, sure, but in such large numbers and impersonal style that it doesn&#39;t feel like there&#39;s people on the other side.&lt;/p&gt;
&lt;p&gt;Paradoxically, recommendation algorithms also make us more likely to interact with content that arouses anger in us than we agree with, since this drives more &lt;strong&gt;engagement&lt;/strong&gt;. &lt;a href=&quot;https://www.youtube.com/watch?v=fuFlMtZmvY0&quot;&gt;This amazing video by Kurzgesagt&lt;/a&gt; talks about the psychology of social interactions in an open, algorithmic internet. It comes to the conclusion that small, year 2000 forum-like communities on the Internet were the most similar to the social mechanisms our brains are accustomed to and thrive in.&lt;/p&gt;
&lt;p&gt;And it has gotten worse recently, thanks to Generative AI and Large Language Models. Bots were already popping up everywhere, but with the power of recent Generative AI models, they have gotten so much better at &lt;strong&gt;deceiving people&lt;/strong&gt;. And some content posted by people is not actually thought about and written by those people. They just asked an LLM to write it for them and copy-pasted the output into their post. A lot of news, or articles like this one, are written almost instantly (and without any thought behind) thanks to Generative AI. Yes, I have also used it to write, but I try to keep it just as a proofreading/editing/brainstorming/idea drafting aid. I don&#39;t post anything I haven&#39;t thought about deeply and didn&#39;t originate from me.&lt;/p&gt;
&lt;p&gt;StackOverflow is a board for asking and answering programming-related questions. Since ChatGPT, it has seen a lot of answers generated by LLMs. I would argue that if you post a question there, you would like an answer from a person that has experience in that topic. If you wanted an answer from ChatGPT you would ask it yourself. And sometimes you might want to, but ChatGPT generally will not be able to solve problems it has never seen like an expert would, but it will still be happy to answer. And this makes a lot of the answers confidently wrong and void of human expertise. This is why StackOverflow has decided to &lt;a href=&quot;https://meta.stackoverflow.com/questions/421831/policy-generative-ai-e-g-chatgpt-is-banned&quot;&gt;ban all use of Generative AI in content posted to the platform&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The wave of content generated by AI and unapologetically non-reviewed by humans has been so strong that a term has been coined for it: &lt;strong&gt;&lt;a href=&quot;https://x.com/deepfates/status/1787472784106639418&quot;&gt;AI Slop&lt;/a&gt;&lt;/strong&gt;. &lt;a href=&quot;https://benjamincongdon.me/blog/2025/01/25/AI-Slop-Suspicion-and-Writing-Back/&quot;&gt;Slop is usually defined as spam, but for AI-generated content&lt;/a&gt;. I would define it as &lt;strong&gt;low-quality content created by a Generative AI model without any human review or even human thought behind it&lt;/strong&gt;. AI Slop threatens to flood the Internet with useless posts, algorithm-pleasing content, mass AI-generated pictures and videos at a pace unprecedented until now, thanks to no human being needed to create them.&lt;/p&gt;
&lt;p&gt;As if this wasn&#39;t bad enough, &lt;strong&gt;Meta is now experimenting with not only allowing AI bots on the platform, but using those bots themselves to drive up engagement&lt;/strong&gt;. In an &lt;a href=&quot;https://www.ft.com/content/91183cbb-50f9-464a-9d2e-96063825bfcf&quot;&gt;interview with the Financial Times&lt;/a&gt;, Connor Hayes said:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;They’ll have bios and profile pictures and be able to generate and share content powered by AI on the platform ... that’s where we see all of this going.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[...] make our apps more entertaining and engaging.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Basically, if you post something on Instagram and nobody likes it or comments it, it might dissuade you from interacting with the app. But if suddenly your post got a lot of likes, comments and messages, even if it&#39;s from AI profiles, you will spend more time on it. Never actually interacting with anyone.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If we continue down this path, soon 99% of all content on the Internet will be AI generated and the Internet will have converted from a place to share and communicate with other people to a place to consume endless slop. It will be lonelier than ever, an Internet without people.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;my-final-thoughts-possible-solutions&quot; tabindex=&quot;-1&quot;&gt;My Final Thoughts + Possible solutions&lt;/h3&gt;
&lt;p&gt;In my opinion, the epicenter of the problem is not AI as a whole but recommendation algorithms and infinite scrolling. The problem is a business model built on the need to drive up engagement and keeping users on the platform at any cost. And it&#39;s a titanic problem to tackle, since the whole modern Internet is built around this concept.&lt;/p&gt;
&lt;p&gt;AI-generated content can also be a problem, but I believe it&#39;s more of a &lt;strong&gt;misuse problem&lt;/strong&gt; than a fundamental problem with the technology. Generative AI models should be our helpers and assistants, but not take over our personas.&lt;/p&gt;
&lt;p&gt;Some people advocate on making AI-generated content easier to spot by &lt;strong&gt;watermarking&lt;/strong&gt;. I don&#39;t believe this is the way not only because it&#39;s difficult to do so with all the kinds of output LLMs can produce, but also because it&#39;s impossible to enforce.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://simonwillison.net/2023/Aug/27/wordcamp-llms/#personal-ai-ethics&quot;&gt;Simon Willson has a great oath on Personal AI ethics&lt;/a&gt;. While he admits to using AI as his writing assistant, he promises to not post anything that takes longer to read than it took him to write. &lt;strong&gt;And I promise to do the same as well&lt;/strong&gt;. Because, just like Simon, I think it&#39;s rude to publish text that you haven&#39;t even read yourself.&lt;/p&gt;
&lt;p&gt;As for possible solutions to make the Internet &lt;em&gt;less dead&lt;/em&gt;, and taking into account that deleting the Internet and starting from scratch is not possible, I&#39;ve come up with a few actions that I will be applying:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Build social circles in online social vehicles that don&#39;t feature recommendation algorithms / infinite scrolling and have a limited number of people.&lt;/strong&gt; Think Discord/Slack groups or online forums. The lack of recommendation algorithms will allow you to more directly explore the content and people you are interested in. The lack of infinite scrolling will keep you from endlessly consuming content and encourage you to interact / build more. And the limited number of people will allow for easier connection building with other members.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Also interact outside that circle&lt;/strong&gt; to get content and world views from outside your circle, but be very critical of what you read and see. Take into account that what you read and see might very well be AI generated. Don&#39;t let that take most of your time.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Favor subscription feeds like RSS to algorithmic recommendation apps and web pages.&lt;/strong&gt; Subscribe to your favorite blogs (wink), newsletters and podcasts via an RSS reader or similar. Explore the personal pages of other people. If you are looking for content you consume, this is the one you are most likely to enjoy and won&#39;t keep you stuck infinitely scrolling. When you are done, you are done.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the end, to make your Internet less dead, the goal is to not spend as much time on the Internet, but to be better connected to the things that matter to you.&lt;/p&gt;
</description>
      <pubDate>Sun, 23 Feb 2025 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/articles/ai/dead-internet-theory/</guid>
    </item>
    <item>
      <title>The Rise Of Reasoner Models: Scaling Test-Time Compute</title>
      <link>https://ruxu.dev/articles/ai/test-time-compute/</link>
      <description>&lt;figure&gt;
&lt;img style=&quot;aspect-ratio: 897/467&quot; alt=&quot;Le Penseur statue&quot; src=&quot;https://ruxu.dev/articles/ai/test-time-compute/assets/images/test-time-compute/thethinker-sm.jpg&quot; /&gt;
&lt;figcaption&gt;Le Penseur (1904) in the Musée Rodin in Paris. Picture by CrisNYCa - Wikipedia.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;A new kind of LLM has recently been popping out everywhere: Reasoner models. Kickstarted by OpenAI&#39;s o1 and o3, these models are a bit different from the rest. These models particularly shine when dealing with mathematical problems and coding challenges, where success depends on following precise, logical steps to reach a correct solution. On the other hand, these models take much longer to answer than any conventional model.&lt;/p&gt;
&lt;p&gt;The approach to problem-solving used by these models mirrors a well-known distinction in human cognition: System 1 versus System 2 thinking. Traditional LLMs operate much like System 1 thinking - quick, intuitive, and based on pattern recognition. They generate responses rapidly based on their trained neural networks. In contrast, Reasoner models embody System 2 thinking - deliberate, methodical, and self-correcting. They can pause, reflect on their reasoning, and even backtrack when they detect potential errors in their logic.&lt;/p&gt;
&lt;p&gt;The key innovation enabling these capabilities isn&#39;t found in revolutionary architectures or training methods, but rather in a different approach to computation: scaling test-time compute.&lt;/p&gt;
&lt;h2 id=&quot;what-is-test-time-compute&quot; tabindex=&quot;-1&quot;&gt;What is Test-time Compute?&lt;/h2&gt;
&lt;p&gt;At its core, test-time compute represents a fundamental shift in how we allocate computational resources in AI systems. While traditional models focus on scaling training time and data (train-time compute) to improve, Reasoner models invest those computational resources during the actual problem-solving phase (test-time compute). This approach essentially gives the model more time to &amp;quot;think&amp;quot; about its answers.&lt;/p&gt;
&lt;p&gt;The concept of &amp;quot;thinking longer&amp;quot; might seem similar to existing techniques like Chain-of-Thought (CoT) prompting, but there&#39;s a crucial difference. CoT prompting encourages models to spell out its reasoning and train of thought, but the intermediate steps are not validated or weighted against alternatives. Therefore, even if most steps are spot on, any error in the intermediate reasoning steps will compound, leading to incorrect final answers. Test-time compute solves this by enabling models to actively verify and correct their reasoning process.&lt;/p&gt;
&lt;h2 id=&quot;how-does-test-time-compute-work&quot; tabindex=&quot;-1&quot;&gt;How Does Test-time Compute Work?&lt;/h2&gt;
&lt;p&gt;The simplest method to implement test-time compute is &lt;strong&gt;iterative self-refinement&lt;/strong&gt;. In this method, the model outputs its reasoning and thoughts to solve a problem. Then, all the previous model outputs are passed through the same model again, making it pay attention to its reasoning and try to find errors and correct them. After sufficient iterations, the quality of the response should be much higher than the first output. This is however a naïve approach, that doesn’t allow the model to be creative to find the right solution.&lt;/p&gt;
&lt;p&gt;A better approach is &lt;strong&gt;Verifier-guided search&lt;/strong&gt;. In this approach, the model generates multiple different answers and a verifier selects the best one. A high temperature is often used to encourage the model to be creative and explore many different solutions. The same model used to generate can be the verifier, however, it’s a much better approach to train a smaller, separate model for that role.&lt;/p&gt;
&lt;p&gt;The verifier can score the correctness of the overall solution (&lt;strong&gt;ORM - Outcome Reward Model&lt;/strong&gt;) or it can score each of the steps of the solution separately (&lt;strong&gt;PRM - Process Reward Model&lt;/strong&gt;). A PRM is much more expensive to run on all the steps than an ORM, however it is a better approach since ORM will mark a solution with all correct steps except one as incorrect. PRM, on the other hand, will mark all correct steps as correct and will encourage the model to rethink the only incorrect step to get to the correct solution.&lt;/p&gt;
&lt;p&gt;Since the PRM will need to evaluate many different approaches to the solution, which branch for each different step proposed, we need efficient search strategies to find the path to the correct solution. The following are few different search strategies to find the correct solution path:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Best of N&lt;/strong&gt;: Generate N independent solutions and score each step using the reward model. Select the solution with the highest score in all its steps.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best of N Weighted&lt;/strong&gt;: The implementation is the same as Best of N, however, identical responses are aggregated together. Therefore, the most common solutions will have higher scores.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Beam Search&lt;/strong&gt;: Generate N solutions for the first step. All generated solutions are scored and the top N/M will be selected for further investigation. For each of the top solutions, M different possible next steps will be generated, and therefore, N steps will be graded for the next step. This continues until getting to the final solution.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DVTS (Diverse Verifier Tree Search)&lt;/strong&gt;: Very similar to Beam Search, but we start with N/M different subtrees and we select only the best step for each of them. Then, for each of the best steps, we generate M new next steps and we score and select the best of them until we get to the final answer.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lookahead search&lt;/strong&gt;: Also similar to Beam Search, but in order to grade each step, we generate the next step for that path and we also grade that next step. We use the score from the next step to score the previous step. Using this information, we end up selecting the paths that will be further explored and the ones that will be discarded. This method is also similar to the Monte Carlo Tree Search algorithm.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, which of these strategies is the best? It depends. For simpler problems and lower compute iteration budget, Best of N weighted seems to be best. But for harder problems and higher compute budgets, Beam Search and its derivatives are definitely better. To achieve the best performance for both simple and complex problems, a &lt;strong&gt;“compute-optimal”&lt;/strong&gt; strategy can be chosen. This strategy will estimate the difficulty of the problem using a model and choose the search strategy accordingly.&lt;/p&gt;
&lt;p&gt;When correct solutions to hard problems are finally found using search, the data from the reasoning of the whole solution can then be used to further improve both the reasoning model and the reward model using reinforcement learning. This further improves the model on its reasoning abilities and makes it able to get to the correct answer faster in subsequent iterations.&lt;/p&gt;
&lt;h2 id=&quot;performance-improvements-through-test-time-compute&quot; tabindex=&quot;-1&quot;&gt;Performance Improvements Through Test-time Compute&lt;/h2&gt;
&lt;p&gt;When we evaluate models that use test-time compute using math and coding benchmarks we find remarkable improvements. In an article from HuggingFace, &lt;em&gt;“Scaling Test-time Compute with Open Models”&lt;/em&gt;, Llama-3.2 3B using 256-iteration test-time compute was found to be better than Llama-3.1 70B, &lt;strong&gt;a model over 20 times larger&lt;/strong&gt;. The paper &lt;em&gt;“Scaling LLM Test-Time Compute Optimally can be More Effective than Scaling Model Parameters”&lt;/em&gt; also finds that a PaLM 2-S small model can &lt;strong&gt;outperform a 14 times larger&lt;/strong&gt; model using test-time compute.&lt;/p&gt;
&lt;p&gt;These findings suggest that some problems, especially reasoning-heavy ones like math and coding, can be solved not by using bigger models, but by making the model “think longer”.&lt;/p&gt;
&lt;h2 id=&quot;limitations-of-test-time-compute&quot; tabindex=&quot;-1&quot;&gt;Limitations of Test-time Compute&lt;/h2&gt;
&lt;p&gt;Does the improvement that reasoning models show mean that, to get better models, we should always let them “think for longer” instead of pretraining bigger models with more data? The already mentioned paper &lt;em&gt;“Scaling Test-time Compute with Open Models”&lt;/em&gt; shows that this does not seem to be the case. The authors of the paper tested which was more effective for solving harder problems; pretraining or scaling test-time compute, and their conclusion is the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;​​Test-time and pretraining compute are not 1-to-1 “exchangeable”. On easy and medium questions, which are within a model’s capabilities, or in settings with small inference requirement, test-time compute can easily cover up for additional pretraining. However, on challenging questions which are outside a given base model’s capabilities or under higher inference requirement, pretraining is likely more effective for improving performance.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Therefore, although scaling test-time compute can help models get to the correct answer even if they struggle to get it right, for test-time to work, the solution has to be in the models capabilities and knowledge to begin with. Scaling test-time compute is not a solution that can solve any problem just by giving it more time.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Reasoner models like o1 and o3 are indeed impressive, and this leads many people to wonder if they are close to achieving Artificial General Intelligence (AGI). Of course, reasoning through test-time compute is not AGI at all. Test-time compute, while powerful, is not sufficient on its own to bridge the gap to AGI and, as we have established, has many shortcomings. Plus it only seems to work well on tasks that have steps that have to be objectively correct to get to the right solution, namely math and coding tasks.&lt;/p&gt;
&lt;p&gt;However, this step to achieve strong reasoning with smaller models does seem to fit with OpenAI’s 5 step plan to AGI. Step 1 is conversational AI and step 2 is reasoning AI, which seems to have been achieved. The third step will be autonomous AI, which is already in the crosshair of many agentic models and agentic systems that are currently being developed.&lt;/p&gt;
&lt;p&gt;So, should you use Reasoner models instead of regular ones? The decision should depend on your specific use case. These models excel at tasks requiring careful reasoning and verification, particularly in domains like mathematics, coding, and logical problem-solving. However, for tasks that require quick responses or deal with more subjective matters, traditional LLMs might still be the better choice.&lt;/p&gt;
&lt;h2 id=&quot;references&quot; tabindex=&quot;-1&quot;&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Scaling Test-Time Compute with Open Models. Edward Beeching, Lewis Tunstall, Sasha Rush (HuggingFace). URL: &lt;a href=&quot;https://huggingface.co/spaces/HuggingFaceH4/blogpost-scaling-test-time-compute&quot;&gt;https://huggingface.co/spaces/HuggingFaceH4/blogpost-scaling-test-time-compute&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Scaling of Search and Learning: A Roadmap to Reproduce o1 from Reinforcement Learning Perspective. Zhiyuan Zeng, Qinyuan Cheng, Zhangyue Yin, Bo Wang, Shimin Li, Yunhua Zhou, Qipeng Guo, Xuanjing Huang, Xipeng Qiu. URL: &lt;a href=&quot;https://arxiv.org/abs/2412.14135&quot;&gt;https://arxiv.org/abs/2412.14135&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Scaling LLM Test-Time Compute Optimally can be More Effective than Scaling Model Parameters. Charlie Snell, Jaehoon Lee, Kelvin Xu, Aviral Kumar. URL: &lt;a href=&quot;https://huggingface.co/papers/2408.03314&quot;&gt;https://huggingface.co/papers/2408.03314&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Sat, 11 Jan 2025 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/articles/ai/test-time-compute/</guid>
    </item>
    <item>
      <title>AI in 2024: Year in Review and Predictions for 2025</title>
      <link>https://ruxu.dev/articles/ai/2024-ai-review/</link>
      <description>&lt;figure&gt;
&lt;img style=&quot;aspect-ratio: 897/467&quot; alt=&quot;Person Holding Firecracker at Night&quot; src=&quot;https://ruxu.dev/articles/ai/2024-ai-review/assets/images/2024-ai-review/firecracker.jpg&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;The past year has been transformative for artificial intelligence, marked by breakthrough innovations, emerging regulations, and a shift toward practical AI tools that enhance productivity. As we look ahead to 2025, let&#39;s review the major developments of 2024 and explore what the future might hold.&lt;/p&gt;
&lt;h2 id=&quot;part-i-2024-year-in-review&quot; tabindex=&quot;-1&quot;&gt;Part I: 2024 Year in Review&lt;/h2&gt;
&lt;h3 id=&quot;openai-in-the-front&quot; tabindex=&quot;-1&quot;&gt;OpenAI in the front&lt;/h3&gt;
&lt;p&gt;OpenAI maintained its position at the forefront of AI innovation in 2024. The release of GPT-4o in May marked a significant milestone as the first frontier multimodal model, capable of understanding and generating content across different forms of media. This was followed by o1 in September, along with its lighter counterpart o1-mini, and the announcement of o3 in December.&lt;/p&gt;
&lt;p&gt;Perhaps most notably, OpenAI&#39;s Sora project revolutionized video generation. Announced in February and enhanced with Sora Turbo in December, this technology demonstrated unprecedented capabilities in creating realistic video content from text descriptions.&lt;/p&gt;
&lt;h3 id=&quot;agentic-ai-and-ai-assistants&quot; tabindex=&quot;-1&quot;&gt;Agentic AI and AI Assistants&lt;/h3&gt;
&lt;p&gt;Rather than replacing jobs, AI in 2024 focused on enhancing human productivity through innovative tools and assistants. Google introduced several groundbreaking projects: Astra, an AI assistant for phones and smart glasses, and Mariner, a Chrome extension that enables Gemini to interact with your browser. These tools represent a shift from simple chat interfaces to interactive agents that can understand and manipulate our digital environment.&lt;/p&gt;
&lt;p&gt;Anthropic joined this trend by enabling Claude to use computers the way humans do—viewing screens, moving cursors, and interacting with interfaces. This development opened new possibilities for AI assistance in everyday computer tasks.&lt;/p&gt;
&lt;p&gt;The developer community saw particularly exciting advances. Github&#39;s Copilot and Cursor AI have been very well received by the developer community. On the other hand, autonomous coding agents like Devin and Github Workspace are still rough around the edges. These tools aren&#39;t replacing developers; instead, they&#39;re supercharging their productivity by handling routine tasks and suggesting improvements.&lt;/p&gt;
&lt;h3 id=&quot;ai-regulation&quot; tabindex=&quot;-1&quot;&gt;AI Regulation&lt;/h3&gt;
&lt;p&gt;2024 saw significant progress in AI regulation, particularly with the EU AI Act. This groundbreaking legislation set the first comprehensive framework for AI regulation, establishing rules for AI system development and deployment while balancing innovation with safety and ethical concerns.&lt;/p&gt;
&lt;h2 id=&quot;part-ii-looking-ahead-to-2025&quot; tabindex=&quot;-1&quot;&gt;Part II: Looking Ahead to 2025&lt;/h2&gt;
&lt;h3 id=&quot;small-specialized-models&quot; tabindex=&quot;-1&quot;&gt;Small, specialized models&lt;/h3&gt;
&lt;p&gt;While decoder-only models like GPT and Claude have dominated headlines, in 2025 encoder-only models are still an important piece in AI applications. Just one week before ending the year, ModernBERT was released, representing a significant advance in this space that was long overdue. These models are particularly crucial for Retrieval-Augmented Generation (RAG) setups, where they excel at information retrieval and classification at a significantly lower cost to run.&lt;/p&gt;
&lt;p&gt;In a similar fashion, the current trend of agentic systems will favor small, specialized models. These models will be fine-tuned to be as good as frontier models in really specific tasks, but used in conjunction in an agentic workflow, will allow for really powerful and resource efficient AI systems.&lt;/p&gt;
&lt;h3 id=&quot;multimodal-models-and-test-time-compute&quot; tabindex=&quot;-1&quot;&gt;Multimodal models and Test-time compute&lt;/h3&gt;
&lt;p&gt;We can expect significant advances in multimodal capabilities, with AI systems becoming more natural at processing and responding to various forms of input—text, voice, images, and video—simultaneously. These improvements will make AI interactions feel more natural and contextually aware.&lt;/p&gt;
&lt;p&gt;The concept of &amp;quot;test-time compute&amp;quot;—giving models more time to think—emerged as a game-changer in 2024 and will likely become more prominent in 2025. Frontier models like OpenAI’s o3 are crushing reasoning, math and coding benchmarks. They are consistently beating humans at really complex, deep reasoning tasks, making us wonder how far Artificial General Intelligence really is.&lt;/p&gt;
&lt;p&gt;Test-time compute is not only showing remarkable results for frontier models. Used in small edge models, they are surpassing the performance of much larger models when given more processing time. For instance, Llama 3.2 3B outperformed Llama 3.1 70B in the Math-500 benchmark using a test-time compute strategy of 256 iterations.&lt;/p&gt;
&lt;h3 id=&quot;the-evolution-of-ai-regulation&quot; tabindex=&quot;-1&quot;&gt;The evolution of AI regulation&lt;/h3&gt;
&lt;p&gt;Following the EU&#39;s lead, we&#39;re likely to see more regions implement AI regulations in 2025. Interestingly, major tech companies are actively calling for regulation, potentially as a strategy to shape the regulatory environment and raise barriers to entry for competitors.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;2024 has been a year of remarkable progress in AI. We have seen many new ways to use AI in our day-to-day lives, as well as new methods to improve models that are making giant strides closer to AGI. As we move into 2025, the focus appears to be shifting toward more specialized and efficient AI systems, improved reasoning capabilities through techniques like test-time compute, and a focus on AI tools to improve productivity.&lt;/p&gt;
</description>
      <pubDate>Mon, 23 Dec 2024 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/articles/ai/2024-ai-review/</guid>
    </item>
    <item>
      <title>Is the EU Falling Behind in the AI Race?</title>
      <link>https://ruxu.dev/articles/ai/eu-ai/</link>
      <description>&lt;figure&gt;
&lt;img style=&quot;aspect-ratio: 897/467&quot; alt=&quot;Library&quot; src=&quot;https://ruxu.dev/articles/ai/eu-ai/assets/images/eu-ai/eu-flag.jpg&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;The recent announcement that Meta&#39;s &lt;strong&gt;Llama 3.2 Vision models&lt;/strong&gt; won&#39;t be available in the European Union has reignited discussions about the impact of EU regulations on AI innovation and accessibility. This development joins a growing list of AI technologies from major tech companies that are currently unavailable to EU users, including &lt;strong&gt;ChatGPT&#39;s Advanced Voice mode&lt;/strong&gt; and &lt;strong&gt;Apple Intelligence&lt;/strong&gt;, raising concerns about whether the EU might be falling behind in the global AI race.&lt;/p&gt;
&lt;h3 id=&quot;the-eu-ai-act-and-its-impact&quot; tabindex=&quot;-1&quot;&gt;The EU AI Act and Its Impact&lt;/h3&gt;
&lt;p&gt;In April 2021, the European Commission proposed the &lt;strong&gt;EU AI Act&lt;/strong&gt;. This act classifies AI systems according to the risk they pose to users. The different risk levels mean more or less regulation. Furthermore, it sets some rules for &lt;strong&gt;General Purpose AI systems&lt;/strong&gt;, like Meta’s Llama or ChatGPT. Model developers must provide technical documentation, instructions, comply with the Copyright Directive, and publish a summary about the content used for training. If the model is open, like Llama, and it presents a &lt;strong&gt;systemic risk&lt;/strong&gt;, which Llama does, it must also conduct model evaluations, adversarial testing, track and report serious incidents and ensure cybersecurity protections.&lt;/p&gt;
&lt;p&gt;According to the study by Stanford University “Do Foundation Model Providers Comply with the Draft EU AI Act?”, as of June 2023, &lt;strong&gt;no foundation models fully comply with the EU AI Act&#39;s requirements&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;meta-and-eu-regulation&quot; tabindex=&quot;-1&quot;&gt;Meta and EU regulation&lt;/h3&gt;
&lt;p&gt;The situation becomes more complex when examining Meta&#39;s challenges with training their models in the EU. In June 2024, Meta faced a setback when the &lt;strong&gt;Irish Data Protection Commission&lt;/strong&gt; requested a delay in training their large language models using &lt;strong&gt;public content from adult Facebook and Instagram users in the EU&lt;/strong&gt;. Meta expressed disappointment with this decision, arguing it would hinder European innovation.&lt;/p&gt;
&lt;p&gt;It seems like these requirements influenced Meta&#39;s decision not to release Llama 3.2 Vision models in the EU. However, this also looks like a retaliation tactic to pressure the EU to let Meta use private user data to train its models.&lt;/p&gt;
&lt;p&gt;As a side note, according to Llama 3.2’s Use Policy, the restriction of use of these models specifically applies to companies and individuals based in the EU who wish to use and build services using these models directly - end users in Europe that use services built on these models are not affected.&lt;/p&gt;
&lt;h3 id=&quot;eu-needs-ai&quot; tabindex=&quot;-1&quot;&gt;EU Needs AI&lt;/h3&gt;
&lt;p&gt;A significant countermovement has emerged in response to these regulatory challenges. The &lt;strong&gt;&amp;quot;EU Needs AI&amp;quot;&lt;/strong&gt; initiative, supported by prominent figures including &lt;strong&gt;Meta&#39;s Chief AI Scientist Yann LeCun&lt;/strong&gt;, argues that fragmented regulation threatens Europe&#39;s competitive position in AI development. Their position statement emphasizes that &amp;quot;Europe has become less competitive and less innovative compared to other regions and it now risks falling further behind in the AI era due to inconsistent regulatory decision making.&amp;quot;&lt;/p&gt;
&lt;h3 id=&quot;what-does-the-future-hold-for-ai-in-the-eu&quot; tabindex=&quot;-1&quot;&gt;What Does the Future Hold for AI in the EU?&lt;/h3&gt;
&lt;p&gt;In my opinion, probably the pushback in regulation is overblown. I believe that, even with these regulations in place, the EU will still have access to some amazing models, and its citizens will enjoy more ethical AI practices.&lt;/p&gt;
&lt;p&gt;While companies from Europe will need to comply with many more requirements as companies from the rest of the world, those requirements are not out of place or unnecessary. Many of the requirements for General Purpose AI systems, systemic risk or not, described in the EU AI Act, are from practices that are already widely in place and considered good practices from reliable models. Also, citizens in the EU will be able to enjoy more privacy and security than any other citizen in the world. Their private data, including pictures, won’t be used for training models. Abusive AI systems like social scoring and manipulative AI won’t be a problem for them.&lt;/p&gt;
&lt;p&gt;In conclusion, the EU will not be falling behind in the AI race. It will keep being competitive, in part thanks to its more ethical practices. And AI regulation is not only not a blocker, but also a necessity, and more countries should follow suit.&lt;/p&gt;
</description>
      <pubDate>Fri, 29 Nov 2024 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/articles/ai/eu-ai/</guid>
    </item>
    <item>
      <title>Build an Advanced RAG App: Query Routing</title>
      <link>https://ruxu.dev/articles/ai/query-routing/</link>
      <description>&lt;figure&gt;
&lt;img style=&quot;aspect-ratio: 897/467&quot; alt=&quot;Library&quot; src=&quot;https://ruxu.dev/articles/ai/query-routing/assets/images/query-routing/query-routing-cover.png&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;In previous articles, we built a basic RAG application. We also learned to introduce more advanced techniques to improve a RAG application. Today, we will explore how to tie those advanced techniques together. Those techniques might do different, sometimes opposite, things. Still, sometimes we need to use all of them, to cover all possibilities. So let&#39;s see how we can link different techniques together. In this article we will take a look at a technique called Query Routing.&lt;/p&gt;
&lt;h3 id=&quot;the-problem-with-advanced-rag-applications&quot; tabindex=&quot;-1&quot;&gt;The problem with Advanced RAG Applications&lt;/h3&gt;
&lt;p&gt;When our Generative AI application receives a query, we have to decide what to do with it. For simple Generative AI applications, we send the query directly to the LLM. For simple RAG applications, we use the query to retrieve context from a single data source and then query the LLM. But, if our case is more complex, we can have multiple data sources, or different queries need different types of context. So do we build a one-size-fits-all solution, or do we make the application adapt to take different actions depending on the query?&lt;/p&gt;
&lt;h3 id=&quot;what-is-query-routing&quot; tabindex=&quot;-1&quot;&gt;What is Query Routing?&lt;/h3&gt;
&lt;p&gt;Query Routing is about giving our RAG app the power of decision-making. Query Routing is a technique that takes the query from the user and uses it to make a decision on the next action to take, from a list of predefined choices.&lt;/p&gt;
&lt;p&gt;Query Routing is a module in our Advanced RAG architecture. It is usually found after any query rewriting or guardrails. It analyses the input query and it decides the best tool to use from a list of predefined actions. The actions are usually retrieving context from one or many data sources. It could also decide to use a different index for a data source (like parent-child retrieval). Or it could even decide to search for context on the Internet.&lt;/p&gt;
&lt;h3 id=&quot;which-are-the-choices-for-the-query-router&quot; tabindex=&quot;-1&quot;&gt;Which are the choices for the Query Router?&lt;/h3&gt;
&lt;p&gt;We have to define the choices that the Query Router can take beforehand. We must first implement each of the different strategies, and accompany each one with a nice description. It is very important that the description explains in detail what each strategy does, since this description will be what our router will base its decision on.&lt;/p&gt;
&lt;p&gt;The choices a Query Router takes can be the following:&lt;/p&gt;
&lt;h4 id=&quot;retrieval-from-different-data-sources&quot; tabindex=&quot;-1&quot;&gt;Retrieval from different data sources&lt;/h4&gt;
&lt;p&gt;We can catalog multiple data sources that contain information on different topics. We might have a data source that contains information about a product that the user has questions about. And another data source with information about our return policies, etc. Instead of looking for the answers for the user’s questions in all data sources, the query router can decide which data source to use based on the user query and the data source description.&lt;/p&gt;
&lt;p&gt;Data sources can be text stored in vector databases, regular databases, graph databases, etc.&lt;/p&gt;
&lt;h4 id=&quot;retrieval-from-different-indexes&quot; tabindex=&quot;-1&quot;&gt;Retrieval from different indexes&lt;/h4&gt;
&lt;p&gt;Query Routers can also choose to use a different index for the same data source.&lt;/p&gt;
&lt;p&gt;For example, we could have an index for keyword based search and another for semantic search using vector embeddings. The Query Router can decide which of the two is best for getting the relevant context for answering the question, or maybe use both of them at the same time and combine the contexts from both.&lt;/p&gt;
&lt;p&gt;We could also have different indexes for different retrieval strategies. For example, we could have a retrieval strategy based on summaries, or a sentence window retrieval strategy, or a parent-child retrieval strategy. The Query Router can analyze the specificity of the question and decide which strategy is best to use to get the best context.&lt;/p&gt;
&lt;h4 id=&quot;other-data-sources&quot; tabindex=&quot;-1&quot;&gt;Other data sources&lt;/h4&gt;
&lt;p&gt;The decision that the Query Router takes is not limited to databases and indexes. It can also decide to use a tool to look for the information elsewhere. For example, it can decide to use a tool to look for the answer online using a search engine. Or it can also use an API from a specific service (for example, weather forecasting) to get the data it needs to get the relevant context.&lt;/p&gt;
&lt;h3 id=&quot;types-of-query-routers&quot; tabindex=&quot;-1&quot;&gt;Types of Query Routers&lt;/h3&gt;
&lt;p&gt;An important part of our Query Router is how it makes the decision to choose one or another path. The decision can vary depending on each of the different types of Query Routers. The following are a few of the most used Query Router types:&lt;/p&gt;
&lt;h4 id=&quot;llm-selector-router&quot; tabindex=&quot;-1&quot;&gt;LLM Selector Router&lt;/h4&gt;
&lt;p&gt;This solution gives a prompt to an LLM. The LLM completes the prompt with the solution, which is the selection of the right choice. The prompt includes all the different choices, each with its description, as well as the input query to base its decision on. The response of this query will be used to programmatically decide which path to take.&lt;/p&gt;
&lt;h4 id=&quot;llm-function-calling-router&quot; tabindex=&quot;-1&quot;&gt;LLM Function Calling Router&lt;/h4&gt;
&lt;p&gt;This solution leverages the function calling capabilities (or tool using capabilities) of LLMs. Some LLMs have been trained to be able to decide to use some tools to get to an answer if they are provided for them in the prompt. Using this capability, each of the different choices is phrased like a tool in the prompt, prompting the LLM to choose which one of the tools provided is best to solve the problem of retrieving the right context for answering the query.&lt;/p&gt;
&lt;h4 id=&quot;semantic-router&quot; tabindex=&quot;-1&quot;&gt;Semantic Router&lt;/h4&gt;
&lt;p&gt;This solution uses similarity search on the vector embedding representation of the user query. For each choice, we will have to write a few examples of a query that would be routed to this path. When a user query arrives, an embeddings model converts it to a vector representation and it is compared to the example queries for each router choice. The example with the nearest vector representation to the user query is chosen as the path the router must route to.&lt;/p&gt;
&lt;h4 id=&quot;zero-shot-classification-router&quot; tabindex=&quot;-1&quot;&gt;Zero-shot classification Router&lt;/h4&gt;
&lt;p&gt;For this type of router, a small LLM is selected to act as a router. This LLM will be finetuned using a dataset of examples of user queries and the correct routing for each of them. The finetuned LLM’s sole purpose will become to classify user queries. Small LLMs are more cost-effective and more than good enough for a simple classification task.&lt;/p&gt;
&lt;h4 id=&quot;language-classification-router&quot; tabindex=&quot;-1&quot;&gt;Language Classification Router&lt;/h4&gt;
&lt;p&gt;In some cases, the purpose of the Query Router will be to redirect the query to a specific database or model depending on the language the user wrote the query in. Language can be detected in many ways, like using a ML classification model or a Generative AI LLM with a specific prompt.&lt;/p&gt;
&lt;h4 id=&quot;keyword-router&quot; tabindex=&quot;-1&quot;&gt;Keyword router&lt;/h4&gt;
&lt;p&gt;Sometimes the use case is extremely simple. In this case, the solution could be to route one way or another depending on if some keywords are present in the user query. For example, if the query contains the word “return” we could use a data source with information useful about how to return a product. For this solution, a simple code implementation is enough, and therefore, no expensive model is needed.&lt;/p&gt;
&lt;h3 id=&quot;single-choice-routing-vs-multiple-choice-routing&quot; tabindex=&quot;-1&quot;&gt;Single choice routing vs Multiple choice routing&lt;/h3&gt;
&lt;p&gt;Depending on the use case, it will make sense for the router to just choose one path and run it. However, in some cases it also can make sense to use more than one choice for answering the same query. To answer a question that spans many topics, the application needs to retrieve information from many data sources. Or the response might be different based on each data source. Then, we can use all of them to answer the question and consolidate them in a single final answer.&lt;/p&gt;
&lt;p&gt;We have to design the router taking these possibilities into account.&lt;/p&gt;
&lt;h3 id=&quot;example-implementation-of-a-query-router&quot; tabindex=&quot;-1&quot;&gt;Example implementation of a Query Router&lt;/h3&gt;
&lt;p&gt;Let’s get into the implementation of a Query Router within a RAG application. You can follow the implementation step by step and run it yourself in the &lt;a href=&quot;https://colab.research.google.com/drive/1B1rGvGriKIVe7PMClrMC0z3wMBbsLIYW?usp=sharing&quot;&gt;Google Colab notebook&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For this example, we will showcase a RAG application with a query router. The application can decide to answer questions based on two documents. The first document is a paper about RAG and the second a recipe for chicken gyros. Also, the application can decide to answer based on a Google search. We will implement a single-source Query Router using an LLM function calling router.&lt;/p&gt;
&lt;h4 id=&quot;load-the-paper&quot; tabindex=&quot;-1&quot;&gt;Load the paper&lt;/h4&gt;
&lt;p&gt;First, we will prepare the two documents for retrieval. Let&#39;s first load the paper about RAG:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Load RAG paper&quot; src=&quot;https://ruxu.dev/articles/ai/query-routing/assets/images/query-routing/load-rag-paper.png&quot; /&gt;
&lt;/figure&gt;
&lt;h4 id=&quot;load-the-recipe&quot; tabindex=&quot;-1&quot;&gt;Load the recipe&lt;/h4&gt;
&lt;p&gt;We will also load the recipe for chicken gyros. This recipe from Mike Price is hosted in &lt;a href=&quot;http://tasty.co/&quot;&gt;tasty.co&lt;/a&gt;. We will use a simple web page reader to read the page and store it as text.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Load chicken gyros recipe&quot; src=&quot;https://ruxu.dev/articles/ai/query-routing/assets/images/query-routing/load-recipe.png&quot; /&gt;
&lt;/figure&gt;
&lt;h4 id=&quot;save-the-documents-in-a-vector-store&quot; tabindex=&quot;-1&quot;&gt;Save the documents in a vector store&lt;/h4&gt;
&lt;p&gt;After getting the two documents we will use for our RAG application, we will split them into chunks and we will convert them to embeddings using BGE small, an open-source embeddings model. We will store those embeddings in two vector stores, ready to be questioned.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Create Vector Stores&quot; src=&quot;https://ruxu.dev/articles/ai/query-routing/assets/images/query-routing/create-vector-stores.png&quot; /&gt;
&lt;/figure&gt;
&lt;h4 id=&quot;search-engine-tool&quot; tabindex=&quot;-1&quot;&gt;Search engine tool&lt;/h4&gt;
&lt;p&gt;Besides the two documents, the third option for our router will be to search for information using a Google Search. For this example I have created my own Google Search API keys. If you want this part to work, you should use your own API keys.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Define Google Search Tool&quot; src=&quot;https://ruxu.dev/articles/ai/query-routing/assets/images/query-routing/google-search-tool.png&quot; /&gt;
&lt;/figure&gt;
&lt;h4 id=&quot;create-the-query-router&quot; tabindex=&quot;-1&quot;&gt;Create the Query Router&lt;/h4&gt;
&lt;p&gt;Next, using the LlamaIndex library, we create a Query Engine Tool for each of the three options that the router will choose between. We provide a description for each of the tools, explaining what it is useful for. This description is very important, since it will be the basis on which the Query Router decide which path it chooses.&lt;/p&gt;
&lt;p&gt;Finally, we create a Router Query Engine, also with Llama. We give the three query engine tools to this router. Also, we define the selector. This is the component that will make the choice of which tool to use. For this example, we are using an LLM Selector. It&#39;s also a single selector, meaning it will only choose one tool, never more than one, to answer the query.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Create the query router&quot; src=&quot;https://ruxu.dev/articles/ai/query-routing/assets/images/query-routing/create-query-router.png&quot; /&gt;
&lt;/figure&gt;
&lt;h4 id=&quot;run-our-rag-application&quot; tabindex=&quot;-1&quot;&gt;Run our RAG application!&lt;/h4&gt;
&lt;p&gt;Our Query Router is now ready. Let&#39;s test it with a question about RAG. We provided a vector store loaded with information from a paper on RAG techniques. The Query Router should choose to retrieve context from that vector store in order to answer the question. Let&#39;s see what happens:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Question the app about RAG&quot; src=&quot;https://ruxu.dev/articles/ai/query-routing/assets/images/query-routing/rag-question.png&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Our RAG application answers correctly. Along with the answer, we can see that it provides the sources from where it got the information from. As we expected, it used the vector store with the RAG paper.&lt;/p&gt;
&lt;p&gt;We can also see an attribute &amp;quot;selector_result&amp;quot; in the result. In this attribute we can inspect which one of the tools the Query Router chose, as well as the reason that the LLM gave to choose that option.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Selector result for the RAG question&quot; src=&quot;https://ruxu.dev/articles/ai/query-routing/assets/images/query-routing/rag-selection-reason.png&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Now let&#39;s ask it a culinary question. The recipe used to create the second vector store is for chicken gyros. Our application should be able to answer which are the ingredients needed for that recipe based on that source.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Question the app about the recipe&quot; src=&quot;https://ruxu.dev/articles/ai/query-routing/assets/images/query-routing/recipe-question.png&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;As we can see, the chicken gyros recipe vector store was correctly chosen to answer that question.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Selector result for the recipe question&quot; src=&quot;https://ruxu.dev/articles/ai/query-routing/assets/images/query-routing/recipe-selection-reason.png&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Finally, let&#39;s ask it a question that can be answered with a Google Search.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Question for Google Search&quot; src=&quot;https://ruxu.dev/articles/ai/query-routing/assets/images/query-routing/google-question.png&quot; /&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;In conclusion, Query Routing is a great step towards a more advanced RAG application. It allows to set up a base for a more complex system, where our app can better plan how to best answer questions. Also, Query Routing can be the glue that ties together other advanced techniques for your RAG application and makes them work together as a whole system.&lt;/p&gt;
&lt;p&gt;However, the complexity for better RAG systems doesn&#39;t end with Query Routing. Query Routing is just the first stepping stone for orchestration within RAG applications. The next stepping stone for making our RAG applications better reason, decide and take actions based on the needs of the users are Agents. In later articles, we will be diving deeper on how Agents work within RAG and Generative AI applications in general.&lt;/p&gt;
</description>
      <pubDate>Thu, 12 Sep 2024 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/articles/ai/query-routing/</guid>
    </item>
    <item>
      <title>Build an Advanced RAG App: Query Rewriting</title>
      <link>https://ruxu.dev/articles/ai/query-rewriting/</link>
      <description>&lt;figure&gt;
&lt;img style=&quot;aspect-ratio: 897/467&quot; alt=&quot;Library&quot; src=&quot;https://ruxu.dev/articles/ai/query-rewriting/assets/images/query-rewriting/query-rewriting-cover.jpg&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;In the last article, I established the basic architecture for a basic RAG app. In case you missed that, I recommend to first read that article over here. That will set the base from which we can improve our RAG system. Also in that last article, I listed some common pitfalls that RAG applications tend to fail on. We will be tackling some of them with some advanced techniques in this article.&lt;/p&gt;
&lt;p&gt;To recap, a basic RAG app uses a separate knowledge base that aids the LLM to answer the user’s questions by providing it with more context. This is also called a retrieve-then-read approach.&lt;/p&gt;
&lt;h3 id=&quot;the-problem&quot; tabindex=&quot;-1&quot;&gt;The problem&lt;/h3&gt;
&lt;p&gt;To answer the user’s question, our RAG app will retrieve appropriate based on the query itself. It will find chunks of text on the vector DB with similar content to whatever the user is asking. Other knowledge bases (search engine, etc.) also apply.
The problem is, the chunk of information where the answer lies, might not be similar to what the user is asking. The question can be badly written, or expressed differently to what we expect. And, if our RAG app can’t find the information needed to answer the question, it won’t answer correctly.&lt;/p&gt;
&lt;p&gt;There are many ways to solve this problem, but for this article, we will look at query rewriting.&lt;/p&gt;
&lt;h3 id=&quot;what-is-query-rewriting&quot; tabindex=&quot;-1&quot;&gt;What is Query Rewriting?&lt;/h3&gt;
&lt;p&gt;Simply put, query rewriting means we will rewrite the user query in our own words, that our RAG app will know best how to answer. Instead of just doing retrieve-then-read, our app will do a rewrite-retrieve-read approach.&lt;/p&gt;
&lt;p&gt;We use a Generative AI model to rewrite the question. This model be a large model, like (or the same as) the one we use to answer the question in the final step. Or it can also be a smaller model, specially trained to perform this task.&lt;/p&gt;
&lt;p&gt;Also, query rewriting can take many different forms depending on the needs of the app. Most of the time, basic query rewriting will be enough. But, depending on the complexity of the questions we need to answer, we might need more advanced techniques like HyDE, multi-querying or step-back questions. More information on those in the following section.&lt;/p&gt;
&lt;h3 id=&quot;why-does-it-work&quot; tabindex=&quot;-1&quot;&gt;Why does it work?&lt;/h3&gt;
&lt;p&gt;Query Rewriting usually gives better performance in any RAG app that is knowledge intensive. This is because RAG applications are sensitive to the phrasing and specific keywords of the query. Paraphrasing this query is helpful in the following scenarios:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It restructures oddly written questions so they can be better understood by our system.&lt;/li&gt;
&lt;li&gt;It erases context given by the user which is irrelevant to the query.&lt;/li&gt;
&lt;li&gt;It can introduce common keywords, which will give it a better chance of matching up with the correct context.&lt;/li&gt;
&lt;li&gt;It can split complex questions into different sub.questions, which can be more easily responded separately, each with their corresponding context.&lt;/li&gt;
&lt;li&gt;It can answer question that require multiple levels of thinking by generating a step-back question, which is a higher-level concept question to the one from the user. It then uses both the original and the step-back question to retrieve context.&lt;/li&gt;
&lt;li&gt;It can use more advanced query rewriting techniques like HyDE to generate hypothetical documents to answer the question. These hypothetical documents will better capture the intent of the question and match up with the embeddings that contain the answer in the vector DB.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;how-to-implement-query-rewriting&quot; tabindex=&quot;-1&quot;&gt;How to implement Query Rewriting&lt;/h3&gt;
&lt;p&gt;We have stablished that there are different strategies of Query Rewriting depending on the complexity of the questions. We will briefly visit how to implement each of them. After, we will see a real example to compare the result of a basic RAG app versus a RAG app with Query Rewriting. You can also follow all the examples in &lt;a href=&quot;https://colab.research.google.com/drive/1-NT0_mmyoSnaDQJ1Zuo0XX613TG5lzjZ?usp=sharing&quot; target=&quot;_blank&quot;&gt;the article’s Google Colab notebook&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;zero-shot-query-rewriting&quot; tabindex=&quot;-1&quot;&gt;Zero-shot Query Rewriting&lt;/h4&gt;
&lt;p&gt;This is simple query rewriting. Zero-shot refers to the prompt engineering technique of giving examples of the task to the LLM, which in this case we give none.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Zero-shot Query Rewriting&quot; src=&quot;https://ruxu.dev/articles/ai/query-rewriting/assets/images/query-rewriting/zero-shot.png&quot; /&gt;
&lt;/figure&gt;
&lt;h4 id=&quot;few-shot-query-rewriting&quot; tabindex=&quot;-1&quot;&gt;Few-shot Query Rewriting&lt;/h4&gt;
&lt;p&gt;For a slightly better result at the cost of using a few more tokens per rewrite, we can give some examples of how we want the rewrite to be done.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Few-shot Query Rewriting&quot; src=&quot;https://ruxu.dev/articles/ai/query-rewriting/assets/images/query-rewriting/few-shot.png&quot; /&gt;
&lt;/figure&gt;
&lt;h4 id=&quot;trainable-rewriter&quot; tabindex=&quot;-1&quot;&gt;Trainable rewriter&lt;/h4&gt;
&lt;p&gt;We can fine-tune a pre-trained model to perform the query rewriting task. Instead of relying on examples, we can teach it how query rewriting should be done to achieve the best results in context retrieving. Also, we can further train it using Reinforcement Learning so it can learn to recognize problematic queries and avoid toxic and harmful phrases.
Or we can also use an open-source model that has already been trained by somebody else on the task of query rewriting.&lt;/p&gt;
&lt;h4 id=&quot;sub-queries&quot; tabindex=&quot;-1&quot;&gt;Sub-queries&lt;/h4&gt;
&lt;p&gt;If the user query contains multiple questions, this can make context retrieval tricky. Each question probably needs different information, and we are not going to get all of it using all the questions as basis for information retrieval. To solve this problem, we can decompose the input into multiple sub-queries, and perform retrieval for each of the sub-queries.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Sub-queries Query Rewriting&quot; src=&quot;https://ruxu.dev/articles/ai/query-rewriting/assets/images/query-rewriting/subqueries.png&quot; /&gt;
&lt;/figure&gt;
&lt;h4 id=&quot;step-back-prompt&quot; tabindex=&quot;-1&quot;&gt;Step-back prompt&lt;/h4&gt;
&lt;p&gt;Many questions can be a bit too complex for the RAG pipeline’s retrieval to grasp the multiple levels of information needed to answer them. For these cases, it can be helpful to generate multiple additional queries to use for retrieval. These queries will be more generic than the original query. This will enable the RAG pipeline to retrieve relevant information on multiple levels.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Step-back prompt Query Rewriting&quot; src=&quot;https://ruxu.dev/articles/ai/query-rewriting/assets/images/query-rewriting/step-back.png&quot; /&gt;
&lt;/figure&gt;
&lt;h4 id=&quot;hyde&quot; tabindex=&quot;-1&quot;&gt;HyDE&lt;/h4&gt;
&lt;p&gt;Another method to improve how queries are matched with contexts chunks are Hypothetical Document Embeddings or HyDE. Sometimes, questions and answers are not that semantically similar, which can cause the RAG pipeline to miss critical context chunks in the retrieval stage. However, even if the query is semantically different, a response to the query should be semantically similar to another response to the same query. The HyDE method consists of creating hypothetical context chunks that answer the query and using them to match the real context that will help the LLM answer.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;HyDE Query Rewriting&quot; src=&quot;https://ruxu.dev/articles/ai/query-rewriting/assets/images/query-rewriting/hyde1.png&quot; /&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img alt=&quot;HyDE Query Rewriting comparison&quot; src=&quot;https://ruxu.dev/articles/ai/query-rewriting/assets/images/query-rewriting/hyde2.png&quot; /&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;example-rag-with-vs-without-query-rewriting&quot; tabindex=&quot;-1&quot;&gt;Example: RAG with vs without Query Rewriting&lt;/h3&gt;
&lt;p&gt;Taking the RAG pipeline from the last article, “How to build a basic RAG app”, we will introduce Query Rewriting into it. We will ask it a question a bit more advanced than last time and observe whether the response improves with Query Rewriting over without it. First, let’s build the same RAG pipeline. Only this time, I’ll only use the top document returned from the vector database to be less forgiving to missed documents.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Example without Query Rewriting&quot; src=&quot;https://ruxu.dev/articles/ai/query-rewriting/assets/images/query-rewriting/example-woqr.png&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;The response is good and based on the context, but it got caught up in me asking about evaluation and missed that I was specifically asking for tools. Therefore, the context used does have information on some benchmarks, but it misses the next chunk of information that talks about tools.&lt;/p&gt;
&lt;p&gt;Now, let’s implement the same RAG pipeline but now with Query Rewriting. As well as the query rewriting prompts, we have already seen in the previous examples, I’ll be using a Pydantic parser to extract and iterate over the generated alternative queries.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Example with Query Rewriting&quot; src=&quot;https://ruxu.dev/articles/ai/query-rewriting/assets/images/query-rewriting/example-wqr.png&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;The new query now matches with the chunk of information I wanted to get my answer from, giving the LLM a better chance of answering a much better response for my question.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;We have taken our first step out of basic RAG pipelines and into Advanced RAG. Query Rewriting is a very simple Advanced RAG technique but a powerful one for improving the results of a RAG pipeline. We have gone over different ways to implement it depending on what kind of questions we need to improve. In future articles we will go over other Advanced RAG techniques that can tackle different RAG issues than those seen in this article.&lt;/p&gt;
</description>
      <pubDate>Sun, 30 Jun 2024 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/articles/ai/query-rewriting/</guid>
    </item>
    <item>
      <title>How to build a basic RAG app</title>
      <link>https://ruxu.dev/articles/ai/build-a-basic-rag/</link>
      <description>&lt;figure&gt;
&lt;img style=&quot;aspect-ratio: 897/467&quot; alt=&quot;Library&quot; src=&quot;https://ruxu.dev/articles/ai/build-a-basic-rag/assets/images/basic-rag/library.jpg&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;The dawn of Generative AI makes possible new kinds of capabilities for the applications we build.  LLMs can answer the user’s questions with an incredible skill. So, why not use them as part of our systems. If the user needs help getting around the app, we can put a chat function where the LLM will answer all the user’s questions. If our app has blog posts explaining important concepts, instead of making the user read all of them to get the knowledge it needs, it could just ask and get an immediate response.&lt;/p&gt;
&lt;h3 id=&quot;why-rag&quot; tabindex=&quot;-1&quot;&gt;Why RAG?&lt;/h3&gt;
&lt;p&gt;We decide to integrate a LLM into our app to bring these features to our users. However, we soon find that the model can’t answer the user’s questions. It doesn’t have any information about our application! If the information needed to answer is not in the LLM’s training data, it can’t answer. Even worse, if it doesn’t know the answer, it might hallucinate a completely wrong fact! This is bad, so how do we fix this? LLMs with the Transformer architecture have shown great in-context learning capabilities. So, we just have to pass all the facts that it needs in the prompt, together with the question! Uh oh, it will definitely be expensive to stuff all the data in every prompt. So, how do we do it?&lt;/p&gt;
&lt;h3 id=&quot;what-is-rag&quot; tabindex=&quot;-1&quot;&gt;What is RAG?&lt;/h3&gt;
&lt;p&gt;RAG stands for &lt;strong&gt;Retrieval Augmented Generation&lt;/strong&gt;. RAG was born together with Transformers. Initially, it was used to augment the pre-training data of LLMs with additional facts. Once Transformers’ in-context learning capabilities became obvious, it became a common practice also during inference, to augment the prompt.&lt;/p&gt;
&lt;p&gt;A basic RAG pipeline consists of three steps: &lt;strong&gt;indexing, retrieval and generation&lt;/strong&gt;. All the information that the LLM needs to answer is indexed in a vector database. When the user asks a question, we can retrieve the relevant parts of the information from that vector database. Finally, together with just the relevant information and the user’s question, we can prompt the LLM to give an answer based on the information we give it as a context. Let’s look in more detail how to achieve this.&lt;/p&gt;
&lt;h4 id=&quot;indexing&quot; tabindex=&quot;-1&quot;&gt;Indexing&lt;/h4&gt;
&lt;p&gt;First, we &lt;strong&gt;extract the information&lt;/strong&gt; that the model needs from wherever it is. Generative models work with plain text (some models can also work with images or other formats, which can also be indexed, but this is a topic for another time). If the information is already in plain text, we are in luck. But it might also be in PDF documents, Word documents, Excel, Markdown, etc. We must &lt;strong&gt;convert this data to plain text and clean it&lt;/strong&gt; so it can be usable for the model.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Indexing process&quot; src=&quot;https://ruxu.dev/articles/ai/build-a-basic-rag/assets/images/basic-rag/indexing.png&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Once the information is in text format, we can &lt;strong&gt;store it in a vector database&lt;/strong&gt;. The vector database will store the embeddings representation of that text. That will allow us to search for parts of the text that have a similar embedding representation as another text, therefore they are about a similar concept. We will &lt;strong&gt;divide the whole text into smaller parts or chunks&lt;/strong&gt;, calculate the &lt;strong&gt;embeddings representation&lt;/strong&gt; for each of them, and finally &lt;strong&gt;store them in the vector database&lt;/strong&gt;.&lt;/p&gt;
&lt;h4 id=&quot;retrieval&quot; tabindex=&quot;-1&quot;&gt;Retrieval&lt;/h4&gt;
&lt;p&gt;When the user asks us a question, we can &lt;strong&gt;convert that question into a vector representation&lt;/strong&gt;, using the same embeddings model we used to index the data. With that vector representation, we will &lt;strong&gt;calculate the similarity factor between the question and each one of the chunks&lt;/strong&gt; stored in the vector database. We will select the top K chunks that are the most similar to the query, and therefore their contents are about the same concept as the question (and therefore they might contain the answer).&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Retrieval process&quot; src=&quot;https://ruxu.dev/articles/ai/build-a-basic-rag/assets/images/basic-rag/retrieval_diagram.png&quot; /&gt;
&lt;/figure&gt;
&lt;h4 id=&quot;generation&quot; tabindex=&quot;-1&quot;&gt;Generation&lt;/h4&gt;
&lt;p&gt;A &lt;strong&gt;prompt&lt;/strong&gt; is built, putting together the &lt;strong&gt;user’s question and the relevant contexts&lt;/strong&gt; to help the LLM answer. We might also include previous messages from the conversation between the user and the AI assistant. The LLM generates an answer for the user based on the context, instead of its previously learned pre-training data.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Retrieval process&quot; src=&quot;https://ruxu.dev/articles/ai/build-a-basic-rag/assets/images/basic-rag/generation_diagram.png&quot; /&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;example&quot; tabindex=&quot;-1&quot;&gt;Example&lt;/h3&gt;
&lt;p&gt;For this example, we will ingest a paper called “Retrieval-Augmented Generation for Lange Language Models: A Survey”. We will query the LLM using the information contained in this paper, so it can answer the user’s questions on its contents. You can follow this example in the &lt;a href=&quot;https://colab.research.google.com/drive/1mFmPN0GBHpS-kMDMuU8EDrWu1KENy69e?usp=sharing&quot; target=&quot;_blank&quot;&gt;Google Colab notebook provided for this article&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First, we will load the PDF document and parse it using LangChain’s PyPDF connector.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Load document using pypdf&quot; src=&quot;https://ruxu.dev/articles/ai/build-a-basic-rag/assets/images/basic-rag/load_doc.png&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Once we have the text from the document, we have to split it into smaller chunks. We can use LangChain’s available splitters, like RecursiveCharacterSplitter in this case:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Split document into chunks&quot; src=&quot;https://ruxu.dev/articles/ai/build-a-basic-rag/assets/images/basic-rag/split_doc.png&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;We will be using BGE-small, an opensource embeddings model. We will download it from HuggingFace Hub and run it on all chunks to calculate their vector representations.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Calculate embeddings&quot; src=&quot;https://ruxu.dev/articles/ai/build-a-basic-rag/assets/images/basic-rag/embeddings.png&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Once we have the vector representations for all chunks, we can create an in-memory vector database and store all vectors in it. For this example, we will be using a FAISS database.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Load embeddings into the vector db&quot; src=&quot;https://ruxu.dev/articles/ai/build-a-basic-rag/assets/images/basic-rag/vectordb.png&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;The database is now set up. Now, we will be taking queries from the user on this information. In this case, the user asks which are the drawbacks of Naive RAG. We encode this query using the same embeddings model as before. Then, we retrieve the top 5 most similar chunks to that query.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Retrieve documents similar to the query from the vectordb&quot; src=&quot;https://ruxu.dev/articles/ai/build-a-basic-rag/assets/images/basic-rag/retrieval.png&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;After retrieving the relevant context, we build a prompt using this information and the user’s original query. We will use Claude’s Haiku as a LLM for this example:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Use the context and the query to generate an answer&quot; src=&quot;https://ruxu.dev/articles/ai/build-a-basic-rag/assets/images/basic-rag/generation.png&quot; /&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;common-problems-and-pitfalls&quot; tabindex=&quot;-1&quot;&gt;Common problems and pitfalls&lt;/h3&gt;
&lt;p&gt;As the title implies, this solution is a basic or naïve RAG implementation. It will empower your application to make the most out of the LLM it’s using and your data. But it won’t work for all cases. These are just some of the most common problems with RAG:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Retrieve irrelevant information.&lt;/strong&gt; If the retriever gets data from the vector database that is not relevant to the question, it will confuse the model trying to answer the question. This might lead to either not using the context to answer the question, or answering something different than what was asked.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Miss important information.&lt;/strong&gt; Maybe the information it needs to answer the question is not in the database. Maybe the retrieval mechanism fails to find the relevant chunks. We must find ways to help the retriever find the information it needs easily and more reliably.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Generate responses not supported by the context.&lt;/strong&gt; If the context has the information the model needs, but it doesn’t use it and instead relies on its own pre-training data, all this was for nothing. The information from the pre-training data might be outdated or wrong. We must favor the model to always use the context to answer, or answer “I don’t know” if it can’t answer from the context.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Irrelevant response to the query.&lt;/strong&gt; The LLM might use all the information that you give it to generate a response, but that doesn’t mean that it answers the user’s question. It’s important that the model sticks to the user’s original question, instead on getting lost in a ton of information.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Redundant response caused by similar contexts.&lt;/strong&gt; When we ingest multiple documents with similar information, there’s a chance that the retriever will get multiple chunks of information that say almost the same. This might cause the LLM to repeat the same information more than one time in its response.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;how-to-avoid-these-problems&quot; tabindex=&quot;-1&quot;&gt;How to avoid these problems?&lt;/h3&gt;
&lt;p&gt;To avoid these problems, a naïve RAG pipeline might not be enough. We will need to set up a more advanced and complex RAG system. There exist tested techniques to solve the problems we have laid out. We can incorporate them into our RAG pipeline to improve the RAG application’s performance.&lt;/p&gt;
&lt;p&gt;Another important point to address is that, to improve your RAG application, you will need to be able to measure and evaluate the whole process. You can’t improve what you can’t measure. Plus, when you evaluate you might find that a basic RAG setup is enough for your use case, and you don’t need to overcomplicate it. After all, even a very basic RAG implementation can improve your LLM powered application enormously.&lt;/p&gt;
&lt;p&gt;In future articles, I will explain in more detail the advanced RAG techniques that will help us avoid common problems and bring our RAG applications to the next level.&lt;/p&gt;
</description>
      <pubDate>Wed, 29 May 2024 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/articles/ai/build-a-basic-rag/</guid>
    </item>
    <item>
      <title>How to use LLMs: Summarize long documents</title>
      <link>https://ruxu.dev/articles/ai/summarize-long-documents/</link>
      <description>&lt;figure&gt;
&lt;img style=&quot;aspect-ratio: 897/467&quot; alt=&quot;Collaboration&quot; src=&quot;https://ruxu.dev/articles/ai/summarize-long-documents/assets/images/summarize-long-doc/written_text.jpg&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;One of the tasks Generative AI models are good at is summarizing texts. However, if you want to summarize a text, you need the whole text to fit in the context window, plus the command to summarize it. The following is an example prompt (you can test it yourself using the &lt;a href=&quot;https://colab.research.google.com/drive/1z5wwBLOag7TK5ylimSuosEQQdjkBswYu?usp=sharing&quot; target=&quot;_blank&quot;&gt;Google Colab notebook for this article&lt;/a&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Write a concise summary of the following text:
The Turing test, originally called the imitation game by Alan Turing in 1950, is a test of a machine&#39;s ability to exhibit intelligent behaviour equivalent to, or indistinguishable from, that of a human. Turing proposed that a human evaluator would judge natural language conversations between a human and a machine designed to generate human-like responses. The evaluator would be aware that one of the two partners in conversation was a machine, and all participants would be separated from one another. The conversation would be limited to a text-only channel, such as a computer keyboard and screen, so the result would not depend on the machine&#39;s ability to render words as speech. If the evaluator could not reliably tell the machine from the human, the machine would be said to have passed the test. The test results would not depend on the machine&#39;s ability to give correct answers to questions, only on how closely its answers resembled those a human would give. Since the Turing test is a test of indistinguishability in performance capacity, the verbal version generalizes naturally to all of human performance capacity, verbal as well as nonverbal (robotic).

Summary: 
&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;
&lt;img alt=&quot;Summarization with direct use&quot; src=&quot;https://ruxu.dev/articles/ai/summarize-long-documents/assets/images/summarize-long-doc/direct-use.png&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;This might get tricky if the text to summarize is too long. There exist LLMs with very large window contexts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GPT-4 has a variant with a context window of 32k tokens.&lt;/li&gt;
&lt;li&gt;Claude 3 Opus has a context window of 200k tokens.&lt;/li&gt;
&lt;li&gt;Gemini 1.5 Pro can have a context window of up to 1 million tokens.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, sometimes using a LLM with such a large context window is off the table. There are many factors that can make this the case:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Those models might be too expensive.&lt;/li&gt;
&lt;li&gt;Models sometimes have a hard time using all the information in very long prompts.&lt;/li&gt;
&lt;li&gt;All the models with large context windows might be off the table because of restrictions like only being able to use open-source models.&lt;/li&gt;
&lt;li&gt;Your text might be longer that all available models (yes even with 1M context windows).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Luckily, there exists a technique that can get an LLM to summarize a document longer than its context window size. The technique is called MapReduce. It’s based on dividing the text in a collection of smaller texts that do fit in the context window and then summarizing each part separately. The steps to perform a MapReduce summary are the following (Again, you can execute and see for yourself all the process in the &lt;a href=&quot;https://colab.research.google.com/drive/1z5wwBLOag7TK5ylimSuosEQQdjkBswYu?usp=sharing&quot; target=&quot;_blank&quot;&gt;Google Colab notebook for this article&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First, the long document is divided into chunks using a text splitter. The strategy we use to divide the text can be different depending on the type of document.
&lt;ul&gt;
&lt;li&gt;If the text has sections and all sections are smaller than the context window, we could divide it by those sections.&lt;/li&gt;
&lt;li&gt;If the text has no clear sections or the sections are too large, the text can be divided in equal sized chunks character-wise. This last approach has the problem of separating related sentences in different chunks. To avoid this problem, we can have an overlap between chunks. With this solution, the last N characters of a chunk will be repeated as the first N characters of the next chunk, so context is not lost.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img alt=&quot;Summarization with direct use&quot; src=&quot;https://ruxu.dev/articles/ai/summarize-long-documents/assets/images/summarize-long-doc/chunks.png&quot; /&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;Second, all chunks are summarized separately using the LLM. Remember to tune your summarize prompt to help understand the model what kind of document it is and how to summarize it properly. For example, you might want the summary to be a bullet point list of the main points of the text or you might want the summary to be just a few sentences.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img alt=&quot;Map: Summarization of all chunks&quot; src=&quot;https://ruxu.dev/articles/ai/summarize-long-documents/assets/images/summarize-long-doc/map.png&quot; /&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;The third step is optional. If the combination of all summaries does not fit into the context window, we won’t be able to ask for a consolidated summary. Instead, we need to make the combination of all summaries smaller.
&lt;ul&gt;
&lt;li&gt;We will group the summaries in groups that fit into the context window.&lt;/li&gt;
&lt;li&gt;Then, we will write a prompt that combines all the summaries to a single summary with the key ideas.&lt;/li&gt;
&lt;li&gt;After reducing all the summary groups, if the resulting combined summaries still don&#39;t fit in the context window, this process is executed again.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img alt=&quot;Combine: Consolidate summaries&quot; src=&quot;https://ruxu.dev/articles/ai/summarize-long-documents/assets/images/summarize-long-doc/combine.png&quot; /&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;Lastly, when all summaries fit into the context window, we can finally combine or reduce them into the final summary.
&lt;ul&gt;
&lt;li&gt;We will write a prompt that combines all the summaries into a single final summary with all the key ideas. This prompt is usually the same as the one in step 3 since the idea is basically the same; combine a list of summaries into one shorter summary. However, you might need the freedom to diverge the two prompts to accommodate specific needs for special kinds of documents or special summaries.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img alt=&quot;Reduce: consolidate all summaries into a single final summary&quot; src=&quot;https://ruxu.dev/articles/ai/summarize-long-documents/assets/images/summarize-long-doc/reduce.png&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;And that’s it! You now have a short summary of the most important points of a large document. But before you start processing your whole documentation, there are a few important notes you need to consider:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This MapReduce method might not be less expensive than using an LLM with a large context window, especially if your cost is per token (as it is in all Model-as-a-service LLMs). Using this method, you will still use all the tokens in the document, plus the tokens of the intermediate summaries (as output and then as input of intermediate prompts). I recommend you study first which method will be more costly for your use case.&lt;/li&gt;
&lt;li&gt;While better models will produce better summaries, the summarization capabilities of not-so-good models will be good enough for most cases. The result after many layers of summarization will be of similar quality, so you might be able to get away with using cheaper models if you decide to use this method.&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Mon, 29 Apr 2024 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/articles/ai/summarize-long-documents/</guid>
    </item>
    <item>
      <title>Understanding LLMs: Mixture of Experts</title>
      <link>https://ruxu.dev/articles/ai/mixture-of-experts/</link>
      <description>&lt;figure&gt;
&lt;img style=&quot;aspect-ratio: 897/467&quot; alt=&quot;Collaboration&quot; src=&quot;https://ruxu.dev/articles/ai/mixture-of-experts/assets/images/collaboration.jpg&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Unlike the Transformers architecture, Mixture of Experts is not a new idea. Still, it is the latest hot topic in Large Language Model architecture. This architecture has been rumored to power OpenAI&#39;s GPT-4 (and maybe GPT3.5-turbo) and is the backbone of Mistral&#39;s Mixtral 8x7B, Grok-1 and Databricks&#39; DBRX, which rival or even surpass GPT 3.5 with a relatively smaller size. Follow along to learn more about how this kind of architecture works and why does it lead to such great results for LLMs.&lt;/p&gt;
&lt;h3 id=&quot;architecture&quot; tabindex=&quot;-1&quot;&gt;Architecture&lt;/h3&gt;
&lt;p&gt;A Mixture of Experts is a model with a sparse layer and a router. The experts reside in the sparse layer, and they are models unconnected between them. Each expert specializes in a specific task. The router is a gating mechanism that learns and decides which experts is best equipped to deal with the input. The simplicity of this concept allows this architecture to work with any type of model. In this article we will focus on Transformers where the experts are feed-forward networks, but they might as well be RNNs, SVMs or even Linear Regression models. Another possibility is Hierarchical experts, which use multiple routers at different levels.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Mixture of Experts Architecture&quot; height=&quot;600&quot; src=&quot;https://ruxu.dev/articles/ai/mixture-of-experts/assets/images/moe.svg&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;The big advantage of this kind of architecture is conditional computation. Every single inference doesn’t need to use all the model’s weights. The gating mechanism is trained to choose the top k experts and route the input only to those. This choice also has a degree of random noise, which prevents overloading the most popular experts and ensures that other experts are also trained on all kinds of data.&lt;/p&gt;
&lt;h3 id=&quot;history&quot; tabindex=&quot;-1&quot;&gt;History&lt;/h3&gt;
&lt;p&gt;The first sentence of this article stated that Mixture of Experts is not a recent idea. In fact, it was first proposed in 1991 in the paper Adaptive Mixture of Local Experts. In this article, the authors proposed that when the model had to perform different tasks, it was beneficial to have different experts with decoupled weights that weren’t affected by other experts fitting their weights to their own task.&lt;/p&gt;
&lt;p&gt;Even though the idea is old, the Mixture of Experts architecture benefits a lot of today’s computing power and horizontal scaling. MoE models can easily be distributed between multiple devices. Since not all weights of the model activate on each inference, each expert can be located to a different device, which frees up the devices with other experts to handle other tasks in parallel.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Mixture of Experts Communication Example&quot; src=&quot;https://ruxu.dev/articles/ai/mixture-of-experts/assets/images/moe-comm.svg&quot; /&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;how-many-experts-should-a-model-have&quot; tabindex=&quot;-1&quot;&gt;How many experts should a model have?&lt;/h3&gt;
&lt;p&gt;When we train a Mixture of Experts model, we expect each expert to learn and be proficient with specific tasks. Experts do seem to specialize in handling specific inputs. For example, for a language model experts tend divide their expertise in handling nouns, verbs, punctuation, numbers and counting, etc. However, they don’t specialize in other tasks that we would consider obvious to divide. When we train a MoE model in a multilingual corpus, different experts don’t learn different languages, they all seem to try to learn all of them.&lt;/p&gt;
&lt;p&gt;A crucial decision when designing a Mixture of Experts model is the number of experts it will have. Normally, more experts mean more efficiency, since a smaller part of the whole model will need to be used for each inference. However, there are some caveats. The advantages of adding another expert diminish the more experts we have; 4 to 16 experts seem to be a sweet spot. Also, even though it doesn’t use all weights for every inference, reducing computing time, it still must always hold all the weights in VRAM. Looking at some popular models, DBRX has 16 experts (4 activate at any inference), while Mixtral and Grok have 8 (2 activate).&lt;/p&gt;
&lt;h3 id=&quot;fine-tuning-moe&quot; tabindex=&quot;-1&quot;&gt;Fine-tuning MoE&lt;/h3&gt;
&lt;p&gt;A particular problem with Mixture of Experts is that they are hard to fine-tune. MoEs are very prone to overfitting. After fine tuning, they are bad at reasoning tasks, but still good at knowledge tasks. A way to mitigate this is to reduce the number of experts, as fewer experts lead to better fine tuning. Also, a recent study has shed some hope for MoE fine tuning. It had great success at finetuning a Flan MoE, suggesting that Moe&#39;s might benefit from instruction fine tuning.&lt;/p&gt;
&lt;h3 id=&quot;scaling-moe&quot; tabindex=&quot;-1&quot;&gt;Scaling MoE&lt;/h3&gt;
&lt;p&gt;In the other hand, Mixture of Experts are great for high-throughput scenarios, as opposed to dense models. MoEs can be scaled with many techniques.&lt;/p&gt;
&lt;p&gt;A paper by Google named GShard explored solving device underutilization to successfully scale a MoE horizontally across many devices. They replicated all non-MoE layers between all devices, but MoE layers had a different expert for each device. They also introduced the concept of expert capacity, which is the maximum number of tokens an expert can take before it is considered overflowed, after when the next expert in line would take over.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Mixture of Experts Capacity Factor Example&quot; src=&quot;https://ruxu.dev/articles/ai/mixture-of-experts/assets/images/moe_capacity_factor.svg&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Another paper, named Switch Transformers, looked at techniques to reduce communication costs between devices and reduce training instabilities. To optimize parallelism, they proposed to use a single expert approach and reduce the capacity factor to almost all tokens being equally divided between the experts (with some small wiggle room for over choosing a specific expert). Switch Transformers also proposed to only use bfloat16 precision for expert layers and use full precision for other layers. This stabilizes training, as other layers like the router need better precision due to an exponentiating function, while still reducing communication costs between experts.&lt;/p&gt;
&lt;h3 id=&quot;optimizing-moe&quot; tabindex=&quot;-1&quot;&gt;Optimizing MoE&lt;/h3&gt;
&lt;p&gt;Mixture of Expert models can also be optimized through different means. Distillation of a sparse model into a dense model keeps 30% of sparsity gains while being much smaller in total model size. Another technique is Aggregation of MoE, which merges weights of all experts into one, which still performs very good on all tasks. Also, QMoE is a quantization technique that can store 1.6 trillion parameters in less than 160GB (0.8 bits per parameter!).&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;In conclusion, given that there’s a need today for models that perform a multitude of different tasks for a group of millions of people (think ChatGPT or similar products), MoE’s excellence in high-throughput, distributed scenarios shines. Being training and inference efficient will also mean lower costs and faster innovation. Of course, not everything is great, there are some drawbacks. Being hard to fine tune is a problem, as needing a lot of VRAM to operate. What is certain is that in the future we will keep seeing better techniques to optimize sparse models and it will lead to better LLMs.&lt;/p&gt;
</description>
      <pubDate>Sat, 30 Mar 2024 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/articles/ai/mixture-of-experts/</guid>
    </item>
    <item>
      <title>What to Expect for AI in 2024?</title>
      <link>https://ruxu.dev/articles/ai/what-to-expect-ai-2024/</link>
      <description>&lt;figure&gt;
&lt;img style=&quot;aspect-ratio: 897/467&quot; alt=&quot;AI&quot; src=&quot;https://ruxu.dev/articles/ai/what-to-expect-ai-2024/assets/images/ai.jpg&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;2023 was a great year for AI. Large Language Models were already in the spotlight for both users and businesses. ChatGPT had been just released in late 2022 and was taking the world by storm. Still, 2023 has brought more rapid change in the field than we could have imagined. This last year we got the newest version of OpenAI’s model, GPT-4. We also got a ton of open-source models competing with OpenAI, like LLaMa, Falcon, and Mistral. Google didn’t want to miss the party and stepped up its game unveiling Gemini, the successor to Google’s earlier model, PaLM. Anthropic launched Claude, AI21 Labs launched Jurassic-2 and Amazon announced its Generative AI service, Bedrock, as well as their own LLM, Titan. Some LLMs gained a ton of new functionality by going multimodal, as well as embracing agents, which allow them to have up-to-date information and interact with the world around them.&lt;/p&gt;
&lt;p&gt;Also, regulators are beginning to catch up to the rapid evolution of this new technology. The United States of America passed an Executive Order on the Safe, Secure, and Trustworthy Development and Use of Artificial Intelligence, and the European Union approved the EU AI Act, the first actual regulation on artificial intelligence.&lt;/p&gt;
&lt;p&gt;So, what’s next for 2024? Given the unpredictably fast rise of new AI technology in the last 14 months, any prediction that we make on its evolution in the future will probably be ridiculed by reality. However, an educated guess can be made given the current direction of AI. I invite you to hear about my take on AI in 2024 and of course, take it with a grain of salt.&lt;/p&gt;
&lt;h3 id=&quot;agi&quot; tabindex=&quot;-1&quot;&gt;AGI&lt;/h3&gt;
&lt;p&gt;As new LLMs begin to approach the trillion parameters mark, new architecture ideas improve on the transformer architecture, and AI’s reasoning abilities continue to improve, I predict that we will begin to hear some Artificial General Intelligence claims. Artificial General Intelligence is the highly anticipated milestone when AI will be able to perform any intellectual task that a human could do. While this kind of artificial intelligence is still very far from being a reality, it seems like it will be inevitable. With current AIs improving exponentially, it&#39;s just a matter of time until we begin to hear claims that a top LLM has reached AGI level. While this does not mean that we are there yet, it’s a clear step that we are on the path to that very realistic future.&lt;/p&gt;
&lt;h3 id=&quot;open-source-models&quot; tabindex=&quot;-1&quot;&gt;Open-source models&lt;/h3&gt;
&lt;p&gt;HuggingFace is a platform that makes it easy to share and contribute to models and datasets. It’s an incredible resource for anyone who wants to start using AI models right away, without having to invest time and money in training their own model from scratch. HuggingFace also provides a ton of resources for working with models and easily fine-tuning them to adapt any model to the user’s needs. In my opinion, these kinds of resources are priceless to both individuals and enterprises that want to get into using AI. And given the fact that every day more and more individuals and businesses introduce AI as a part of their workflows and products, it is likely that this kind of platform will explode further that it already has, providing tons of new open-source models and AI resources.&lt;/p&gt;
&lt;h3 id=&quot;multimodality&quot; tabindex=&quot;-1&quot;&gt;Multimodality&lt;/h3&gt;
&lt;p&gt;Some LLMs like ChatGPT and Google’s Gemini have already unveiled multimodal capabilities. Multimodal models are Large Language Models that can understand and interact with a combination of different types of inputs, like text, audio, images, and video. Since LLMs convert text and images to a vector representation to interpret them correctly, it&#39;s quite challenging to find a vector representation that works for both text and images, so this is an incredible feat. LLMs having multimodal capabilities broaden the list of tasks they can perform by a large margin. This year, I expect even more models embracing multimodality and the capabilities of AI agents to increase significantly.&lt;/p&gt;
&lt;h3 id=&quot;responsible-ai&quot; tabindex=&quot;-1&quot;&gt;Responsible AI&lt;/h3&gt;
&lt;p&gt;As regulators start to intensify legislation on artificial intelligence, Responsible AI will not just be a choice in developing new AI models, but a must. Responsible AI is an approach to training AI models with ethics and safety in mind. Generative AI models should be trained to be fair and unbiased, as well as to avoid harmful responses and avoid endangering human life, property, or the environment. I expect not only to see an improvement in Responsible AI frameworks and expectations but also to witness the first legal consequences for enterprises not following those new rulings.&lt;/p&gt;
&lt;h3 id=&quot;ai-use-in-enterprises&quot; tabindex=&quot;-1&quot;&gt;AI use in enterprises&lt;/h3&gt;
&lt;p&gt;As using LLMs becomes easier and more democratized, the barrier of entry for tons of enterprises that are not primarily technologically focused will begin to fall. More and more kinds of companies will begin to use AI to aid in their daily operations. We will see more AI B2B products to address these new necessities. Some companies may just start using AI for the hype of it but will fail to implement it in a meaningful manner for their bottom line. On the other hand, companies that succeed in introducing AI in their daily operations will see an unprecedented boost in productivity. Sadly, this also might mean that we will see some companies lay off an important part of their workforce, as employees are quickly replaced by AI systems.&lt;/p&gt;
&lt;h3 id=&quot;ai-race&quot; tabindex=&quot;-1&quot;&gt;AI race&lt;/h3&gt;
&lt;p&gt;The potential of artificial intelligence is no longer a secret. Many countries around the world will not only begin to legislate for AI but also invest heavily in it, as being at the forefront of AI innovation can give them an edge in many areas, including military, scientific, economic, and informational. Even if one specific part of the world advocates for AI ethics and halts AI progress to ensure it not being a threat to humanity, other parts of the world might take this opportunity to put themselves at the front of innovation, which will inevitably make the former’s efforts worthless. We might begin to witness a new AI “space race”, as countries put pressure on each other to never stop investing resources in developing new AI, under the threat of falling behind in the new future that AI is shaping.&lt;/p&gt;
&lt;p&gt;Even if my predictions don’t end up becoming a reality, what is certain is that AI will continue to be a major topic in 2024. I’m excited to see how AI will evolve during the following year and what new capabilities it will bring. Certainly, there are many concerns to be had with the rapid evolution of AI, but I’m hopeful that we will be responsible enough to address them before they do become a problem. As a personal note, this year I will be testing how to use AI in many of my daily activities to make them easier or even completely automate them.&lt;/p&gt;
</description>
      <pubDate>Mon, 29 Jan 2024 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/articles/ai/what-to-expect-ai-2024/</guid>
    </item>
    <item>
      <title>How to supercharge your LLM with Langchain Agents</title>
      <link>https://ruxu.dev/articles/ai/langchain-agents/</link>
      <description>&lt;figure&gt;
&lt;img style=&quot;aspect-ratio: 897/467&quot; alt=&quot;OpenAI&quot; src=&quot;https://ruxu.dev/articles/ai/langchain-agents/assets/images/parrot.jpg&quot; /&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;the-problem-with-llms&quot; tabindex=&quot;-1&quot;&gt;The problem with LLMs&lt;/h2&gt;
&lt;p&gt;LLMs are very capable to perform a lot of feats that seem incredible to us, but &lt;strong&gt;they are bound by the borders of what Generative AI was originally meant to do: generate text based on the data it has been trained on.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;They cannot access any services on the web to give us more accurate and recent answers and instead, they are meant to answer using the training data that their creators were able to gather many years ago. They cannot access tools as simple as a calculator that would help to give mathematical answers instead of having to memorize the result of every mathematical operation. They are reliant on us to perform the actions they suggest to do in the real world and we report back to them with the results.&lt;/p&gt;
&lt;p&gt;To give our LLMs the powers they are missing to be truly powerful for us, we can use &lt;strong&gt;Agents&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;what-are-agents&quot; tabindex=&quot;-1&quot;&gt;What are Agents?&lt;/h2&gt;
&lt;p&gt;Agents are an LLM that is being prompted to &lt;strong&gt;reason about the actions needed to complete a request&lt;/strong&gt;, using a set of &lt;strong&gt;tools&lt;/strong&gt; that it has been provided with. An agent can be used alongside &lt;strong&gt;any LLM&lt;/strong&gt;. It is only a layer on top of it that builds the prompts indicating to the Agent the &lt;strong&gt;context, its personality and the strategies it must use&lt;/strong&gt; to complete requests.&lt;/p&gt;
&lt;p&gt;Obviously, the Agent by itself is not enough. We also need to create/use tools for the Agent to be able to use. The &lt;strong&gt;Agent Executor&lt;/strong&gt; is the runtime that executes both the Agent and the tools that it uses. &lt;strong&gt;Tools&lt;/strong&gt; can just be standalone functions or they can come in collections of tools called &lt;strong&gt;toolkits&lt;/strong&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Agent Executor, Agents and Tools diagram&quot; src=&quot;https://ruxu.dev/articles/ai/langchain-agents/assets/images/LangChainAgents.svg&quot; /&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;tools-and-toolkits&quot; tabindex=&quot;-1&quot;&gt;Tools and toolkits&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Tools are functions&lt;/strong&gt; that will perform actions on behalf of the LLM. An agent gets a list of tools for it to use and it will request to use one, several, or none. The Agent Executor will execute the required tools and feed the result back to the Agent. An example of a tool is the Google Search function, which allows LLMs to check some information that they don&#39;t have using a Google search.&lt;/p&gt;
&lt;p&gt;For the Agent to be able to choose correctly which tools it needs, &lt;strong&gt;those tools have to exist, be correctly implemented for the purpose that the Agent needs them for, and be in the list of tools for the Agent&lt;/strong&gt;. But more importantly, these tools &lt;strong&gt;must be thoroughly described&lt;/strong&gt; so Agents can easily decide if they need them and what they will be helpful for.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Toolkits are just a set of tools&lt;/strong&gt; that are usually useful together. These tools might be useful to be used together for achieving a multi-step goal, or they might be grouped because they do similar actions or actions in the same domain. An example of a toolkit is the Gmail Toolkit, which allows LLMs to read emails, draft new emails and delete them.&lt;/p&gt;
&lt;h2 id=&quot;what-strategies-do-agents-use&quot; tabindex=&quot;-1&quot;&gt;What strategies do Agents use?&lt;/h2&gt;
&lt;p&gt;After a set of tools is provided to the Agent, how does it know which one to use? Agents can use a variety of prompt engineering strategies to make the LLM reason and decide about the actions it has to take. Some popular prompt engineering practices were discussed in the previous article: Prompt Engineering.&lt;/p&gt;
&lt;p&gt;The most popular strategy for agents is the &lt;strong&gt;ReAct&lt;/strong&gt; method. ReAct uses few-shot learning together with some Chain-of-Thought reasoning examples. These examples contain:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Thoughts&lt;/strong&gt; transcribed from the reasoning strategies.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Actions&lt;/strong&gt; that let the LLM interact with its environment in a verbal manner.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Observations&lt;/strong&gt; gained after taking the actions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The LLM then understands how to act in this manner and interact with its tools and can apply it to real interactions. An example of a ReAct prompt would be:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Question: What is the current temperature at the city where John Cena was born in Celcius?
Thought: I need to search for the city John Cena was born in, then find the current temperature for that city, then convert the temperature to Celsius.
Action: Search[City where John cena was born]
Observation: Cena was born in West Newbury, Massachusetts.
Thought: I have to find the current temperature in West Newbury, Massachusetts.
Action: WeatherLookup[West Newbury, Massachusetts]
Observation: 81°F. Sunshine to start, then a few afternoon clouds. High 81F. Winds WNW at 5 to 10 mph. 45% humidity.
Thought: I have to convert 81°F to Celsius.
Action: UnitConversion[FahrenheitToCelcius, 81]
Observation: 27.2
Thought: The answer is 27.2 degrees Celsius.
Action: Finish[27.2 degrees Celsius]
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;how-to-use-langchain-agents&quot; tabindex=&quot;-1&quot;&gt;How to use Langchain Agents&lt;/h2&gt;
&lt;p&gt;Langchain is a Python library (as well as JS/TS) that is very useful for rapidly getting started on integrating LLMs in your applications. It has many prompting strategies available out of the box and also many Agents.&lt;/p&gt;
&lt;p&gt;You can get started writing tools of your own using Langchain’s tools, like this (&lt;strong&gt;VERY IMPORTANT: give the function a docstring description, this will be used by the agent to choose what tool to use&lt;/strong&gt;):&lt;/p&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; langchain&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;agents &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; tool

&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@tool&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;unit_conversion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;units&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;Converts a given unit to another unit. To convert from Fahrenfeit to Celcius, give FahrenheitToCelcius as first parameter, then the value as second parameter&quot;&quot;&quot;&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; units &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;FahrenheitToCelcius&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; Exception&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Invalid type of unit conversion&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Afterwards, use this tool along with your agent of choice, also with Langchain:&lt;/p&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; langchain&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;llms &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; OpenAI
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; langchain&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;agents &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; initialize_agent&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; AgentType

&lt;span class=&quot;token comment&quot;&gt;# We will use OpenAI&#39;s GPT as the LLM&lt;/span&gt;
llm &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; OpenAI&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;temperature&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# We will create the Agent&lt;/span&gt;
agent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; initialize_agent&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;unit_conversion&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; llm&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; agent&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;AgentType&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ZERO_SHOT_REACT_DESCRIPTION&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; verbose&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

agent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;run&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;What is 81 degrees Fahrenheit in Celsius?&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can learn more about Langchain and its tools by visiting &lt;a href=&quot;https://python.langchain.com/docs/get_started&quot;&gt;its documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It looks like Agents are going to bring a lot more capabilities to LLMs in the recent future. As these new capabilities roll out to applications and tools, more outstanding things will be possible. I’m very curious and looking forward to the new possibilities.&lt;/p&gt;
</description>
      <pubDate>Sun, 06 Aug 2023 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/articles/ai/langchain-agents/</guid>
    </item>
    <item>
      <title>Maximizing the Potential of LLMs: Using Vector Databases</title>
      <link>https://ruxu.dev/articles/ai/vector-stores/</link>
      <description>&lt;figure&gt;
&lt;img style=&quot;aspect-ratio: 897/467&quot; alt=&quot;OpenAI&quot; src=&quot;https://ruxu.dev/articles/ai/vector-stores/assets/images/openai.png&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;LLMs do Natural Language Processing (NLP) to represent the meaning of text as a vector. This representation of the words of the text is an embedding.&lt;/p&gt;
&lt;h2 id=&quot;the-token-limit-the-llm-prompting-biggest-problem&quot; tabindex=&quot;-1&quot;&gt;The token limit: the LLM prompting biggest problem&lt;/h2&gt;
&lt;p&gt;Currently, one of the biggest problems with LLM prompting is the &lt;em&gt;token limit&lt;/em&gt;. When GPT-3 was released, the limit for both the prompt and the output combined was 2,048 tokens. With GPT-3.5 this limit increased to 4,096 tokens. Now, GPT-4 comes in two variants. One with a limit of 8,192 tokens and another with a limit of 32,768 tokens, around 50 pages of text.&lt;/p&gt;
&lt;p&gt;So, what can you do when you might want to do a prompt with a context larger than this limit? Of course, the only solution is to make the context shorter. But how can you make it shorter and at the same time have all the relevant information? The solution: &lt;strong&gt;store the context in a vector database and find the relevant context with a similarity search query.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-are-vector-embeddings&quot; tabindex=&quot;-1&quot;&gt;What are vector embeddings?&lt;/h2&gt;
&lt;p&gt;Let&#39;s start by explaining what vector embeddings are. &lt;a href=&quot;https://roycoding.com/blog/2022/embeddings.html&quot;&gt;Roy Keynes&#39; definition&lt;/a&gt; is: &amp;quot;Embeddings are learned transformations to make data more useful&amp;quot;. A neural network learns to transform text to a vector space that contains their actual meaning. This is more useful because it can find synonyms and the syntactical and semantical relationships between words. This visual helps understand how those vectors can encode meaning:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Word2Vec representation of Queen = King - Man + Woman&quot; src=&quot;https://ruxu.dev/articles/ai/vector-stores/assets/images/word2vec-king.png&quot; /&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;what-do-vector-databases-do&quot; tabindex=&quot;-1&quot;&gt;What do vector databases do?&lt;/h2&gt;
&lt;p&gt;A vector database stores and indexes vector embeddings. This is useful for fast retrieval of vectors and looking for similar vectors.&lt;/p&gt;
&lt;h3 id=&quot;similarity-search&quot; tabindex=&quot;-1&quot;&gt;Similarity search&lt;/h3&gt;
&lt;p&gt;We can find similarity of vectors by calculating a vector&#39;s distance to all other vectors. The nearest neighbors will be the most similar results to the query vector. This is how flat indexes in vector databases work. But this is not very efficient, in a large database this might take a very long time.&lt;/p&gt;
&lt;p&gt;To improve the search&#39;s performance, we can try to calculate the distance for only a subset of the vectors. This approach, called approximate nearest neighbors (ANN), improves speed but sacrifices quality of results. Some popular ANN indexes are Locally Sensitive Hashing (LSH), Hierarchical Navigable Small Worlds (HNSW) or Inverted File Index (IVF).&lt;/p&gt;
&lt;p&gt;&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display:block; text-align:center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-3558841073771468&quot; data-ad-slot=&quot;5616977890&quot;&gt;&lt;/ins&gt;&lt;/p&gt;
&lt;h2 id=&quot;integrating-vector-stores-and-llms&quot; tabindex=&quot;-1&quot;&gt;Integrating vector stores and LLMs&lt;/h2&gt;
&lt;p&gt;For this example, I downloaded the whole numpy documentation (with over 2000 pages) as a PDF from this URL: &lt;a href=&quot;https://numpy.org/doc/1.23/numpy-ref.pdf&quot;&gt;https://numpy.org/doc/1.23/numpy-ref.pdf&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We can write a Python code to transform the context document to embeddings and save them to a vector store. We will use LangChain to load the document and split it into chunks, and Faiss (Facebook AI Similarity Search) as a vector database.&lt;/p&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; langchain&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;embeddings&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;openai &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; OpenAIEmbeddings
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; langchain&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text_splitter &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; CharacterTextSplitter
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; langchain&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vectorstores &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; FAISS
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; langchain&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;document_loaders &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; PyPDFLoader

loader &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; PyPDFLoader&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;example_data/layout-parser-paper.pdf&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
pages &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; loader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;load_and_split&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

embeddings &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; OpenAIEmbeddings&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

db &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FAISS&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;from_documents&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pages&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; embeddings&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;save_local&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;numpy_faiss_index&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we can use this database to perform a similarity search query to find pages that might be related to our prompt. Then, we use the resulting chunks to fill the context of our prompt. We will use LangChain to make it easier:&lt;/p&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; langchain&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vectorstores &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; FAISS
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; langchain&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;chains&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;qa_with_sources &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; load_qa_with_sources_chain
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; langchain&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;llms &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; OpenAI

query &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;How to calculate the median of an array&quot;&lt;/span&gt;

db &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FAISS&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;load_local&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;numpy_faiss_index&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; embeddings&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
docs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;similarity_search&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;query&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

chain &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; load_qa_with_sources_chain&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;OpenAI&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;temperature&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; chain_type&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;stuff&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
chain&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;input_documents&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; docs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;question&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; query&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; return_only_outputs&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our question for the model is &amp;quot;How to calculate the median of an array&amp;quot;. Even though the context that we give it is way over the token limit, we have overcome this limitation and got an answer:&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;To calculate the median, you can use the numpy.median() function, which takes an input array or object that can be converted to an array and computes the median along the specified axis. The axis parameter specifies the axis or axes along which the medians are computed, and the default is to compute the median along a flattened version of the array. The function returns the median of the array elements.

For example, to calculate the median of an array &quot;arr&quot; along the first axis, you can use the following code:

import numpy as np
median = np.median(arr, axis=0)

This will compute the median of the array elements along the first axis, and return the result in the variable &quot;median&quot;.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is just one clever solution for a very new problem. As LLMs keep evolving, maybe problems like this will be solved without the need of these kinds of clever solutions. However, I&#39;m sure that this evolution will open the door for new capabilities that might need other new clever solutions for the challenges that they may bring.&lt;/p&gt;
</description>
      <pubDate>Sun, 16 Apr 2023 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/articles/ai/vector-stores/</guid>
    </item>
    <item>
      <title>Maximizing the Potential of LLMs: A Guide to Prompt Engineering</title>
      <link>https://ruxu.dev/articles/ai/maximizing-the-potential-of-llms/</link>
      <description>&lt;figure&gt;
&lt;img style=&quot;aspect-ratio: 897/467&quot; alt=&quot;OpenAI&quot; src=&quot;https://ruxu.dev/articles/ai/maximizing-the-potential-of-llms/assets/images/openai.png&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Language models have rapidly improved in recent years, with large language models (LLMs) such as GPT-3 and GPT-4 taking center stage. These models have become popular due to their ability to perform a great variety of tasks with incredible skill. Also, as the number of parameters of these models (in the billions!) has increased, these models have unpredictably gained new abilities.&lt;/p&gt;
&lt;p&gt;In this article, we will explore LLMs, the tasks they can perform, their shortcomings, and various prompt engineering strategies.&lt;/p&gt;
&lt;h3 id=&quot;what-are-llms&quot; tabindex=&quot;-1&quot;&gt;What are LLMs?&lt;/h3&gt;
&lt;p&gt;LLMs are neural networks that have been trained on vast amounts of text data. The training process allows the models to learn patterns in the text, including grammar, syntax, and word associations. The models use these learned patterns to generate human-like text, making them ideal for natural language processing (NLP) tasks.&lt;/p&gt;
&lt;h3 id=&quot;which-llms-are-available&quot; tabindex=&quot;-1&quot;&gt;Which LLMs are available?&lt;/h3&gt;
&lt;p&gt;There are several LLMs available, with GPT-4  being the most popular. Other models include LLaMA, PaLM, BERT, and T5. Each model has its strengths and weaknesses, some of them are open and others are closed and only usable via API.&lt;/p&gt;
&lt;h3 id=&quot;shortcomings-of-llms&quot; tabindex=&quot;-1&quot;&gt;Shortcomings of LLMs&lt;/h3&gt;
&lt;p&gt;Despite their impressive performance, LLMs have several limitations. One significant drawback is their inability to reason beyond the information provided in the prompt. Additionally, LLMs can generate biased text based on the data they were trained on. It is also challenging to control the output of LLMs, making it necessary to use prompt engineering strategies to achieve the desired output.&lt;/p&gt;
&lt;h2 id=&quot;which-tasks-can-you-perform&quot; tabindex=&quot;-1&quot;&gt;Which tasks can you perform?&lt;/h2&gt;
&lt;p&gt;We can direct LLMs to perform specific tasks for us by formatting the prompts for each case. Here&#39;s a list of those tasks and prompt templates and examples for each.&lt;/p&gt;
&lt;h3 id=&quot;text-summarization&quot; tabindex=&quot;-1&quot;&gt;Text Summarization&lt;/h3&gt;
&lt;p&gt;LLMs can generate summaries of long texts, making it easier to understand and digest the content. We can ask to summarize a text with the following prompt template:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Template&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;&amp;lt;Full text&gt;
Summarize the text above: / Explain the text above in &amp;lt;N&gt; sentences:&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For example, we can ask to summarize this text with the following prompt:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prompt&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;In a mechanical watch the watch&#39;s gears are turned by a spiral spring called a mainspring. In a manual watch energy is stored in the mainspring by turning a knob, the crown on the side of the watch. Then the energy from the mainspring powers the watch movement until it runs down, requiring the spring to be wound again.
A self-winding watch movement has a mechanism which winds the mainspring using the natural motions of the wearer&#39;s body. The watch contains an oscillating weight that turns on a pivot. The normal movements of the watch in the user&#39;s pocket (for a pocketwatch) or on the user&#39;s arm (for a wristwatch) cause the rotor to pivot on its staff, which is attached to a ratcheted winding mechanism. The motion of the watch is thereby translated into circular motion of the weight which, through a series of reverser and reducing gears, eventually winds the mainspring. There are many different designs for modern self-winding mechanisms. Some designs allow winding of the watch to take place while the weight swings in only one direction while other, more advanced, mechanisms have two ratchets and wind the mainspring during both clockwise and anti-clockwise weight motions.
Explain the text above in 2 sentences:&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which gives the following output:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Output&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;A mechanical watch uses a mainspring to power the movement of the watch&#39;s gears. In a manual watch, the mainspring is wound by turning a knob, while a self-winding watch uses the natural motion of the wearer&#39;s body to wind the mainspring through an oscillating weight and ratcheted winding mechanism.&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;information-extraction&quot; tabindex=&quot;-1&quot;&gt;Information Extraction&lt;/h3&gt;
&lt;p&gt;LLMs can identify and extract specific information from a large body of text. This is useful in fields such as journalism and business intelligence. The following template instructs the model to extract information:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Template&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;&amp;lt;Full text&gt;
Mention X in the text above: / List X in the text above:&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For example, we can ask to extract the names of places from the following text:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prompt&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;The earliest credible evidence for a successful design is the watch made by the Swiss watchmaker Abraham-Louis Perrelet, who lived in Le Locle. In late 1776 or early 1777, he invented a self-winding mechanism for pocket watches using an oscillating weight inside the watch that moved up and down. The Geneva Society of Arts, reporting on this watch in 1777, stated that 15 minutes walking was necessary to fully wind the watch.
List the names of places in the text above:&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the output is:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Output&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;Le Locle, Geneva.&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;question-answering&quot; tabindex=&quot;-1&quot;&gt;Question Answering&lt;/h3&gt;
&lt;p&gt;LLMs can also answer questions based on the information provided in the prompt. The following template can be used to direct the LLM to answer a question:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Template&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;Answer the question based on the context below. &amp;lt;Other instructions&gt;. Respond &quot;Not sure&quot; if not sure about the answer.
Context: &amp;lt;Context&gt;
Q: &amp;lt;Question&gt;
A:&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For example, with the following prompt:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prompt&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;Answer the question based on the context below. Answer in a single sentence. Respond &quot;Not sure&quot; if not sure about the answer.
Context: An automatic watch, also known as a self-winding watch or simply an automatic, is a mechanical watch where the natural motion of the wearer provides energy to wind the mainspring, making manual winding unnecessary if worn enough. It is distinguished from a manual watch in that a manual watch must have its mainspring wound by hand at regular intervals.
Q: Do automatic watches need to be manually wound?
A:&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And ChatGPT responds with:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Output&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;No, automatic watches do not need to be manually wound if worn enough because the natural motion of the wearer provides energy to wind the mainspring.&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;text-classification&quot; tabindex=&quot;-1&quot;&gt;Text Classification&lt;/h3&gt;
&lt;p&gt;LLMs can classify text into predefined categories, such as sentiment analysis or spam detection. You can format a text classification instruction as follows:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Template&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;Classify the text into &amp;lt;List of choices&gt;:
Text: &amp;lt;Full text&gt;
Classification:&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For example, we can try to classify a text for whether its sentiment is positive, neutral or negative:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prompt&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;Classify the text into positive, neutral or negative:
Text: That shot selection was awful
Classification:&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Output&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;Negative&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display:block; text-align:center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-3558841073771468&quot; data-ad-slot=&quot;5616977890&quot;&gt;&lt;/ins&gt;&lt;/p&gt;
&lt;h3 id=&quot;conversation&quot; tabindex=&quot;-1&quot;&gt;Conversation&lt;/h3&gt;
&lt;p&gt;LLMs can generate human-like conversation, making them useful in chatbots and customer service applications. We can instruct the LLM to follow the conversation acting in a specific manner.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Template&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;The following is a conversation with &amp;lt;Actor&gt;. The &amp;lt;Actor&gt; should answer &amp;lt;Further instructions&gt;.
Person: &amp;lt;Conversation&gt;
&amp;lt;Actor&gt;: &amp;lt;Response&gt;
Person: &amp;lt;Conversation&gt;
&amp;lt;Actor&gt;:&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The LLM will fill in the response of the type of actor we instructed it to, and we can continue the conversation by passing the whole conversation with the new responses to it again. For example:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prompt&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;The following is a conversation with a lawyer. The lawyer should answer simply and in layman terms.
Person: Hello, I would like to know how to dispute a parking ticket
Lawyer:&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Output&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;Sure, I can help. The first step is to check the ticket for any errors or mistakes. If you find any, you can use those as grounds to dispute the ticket. If there are no mistakes, you can still dispute the ticket by providing evidence to support your case, such as photos or witness statements. You can also request a hearing to present your case in person.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Prompt&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;The following is a conversation with a lawyer. The lawyer should answer simply and in layman terms.
Person: Hello, I would like to know how to dispute a parking ticket
Lawyer: Sure, I can help. The first step is to check the ticket for any errors or mistakes. If you find any, you can use those as grounds to dispute the ticket. If there are no mistakes, you can still dispute the ticket by providing evidence to support your case, such as photos or witness statements. You can also request a hearing to present your case in person.
Person: How do I request a hearing?
Lawyer:&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Output&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;To request a hearing, you&#39;ll need to follow the instructions on the back of the ticket or on the website provided. Usually, you&#39;ll need to submit a written request within a certain timeframe, along with any evidence or supporting documents you have. Once your request is received, you&#39;ll be notified of the date, time, and location of your hearing.&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;code-generation&quot; tabindex=&quot;-1&quot;&gt;Code Generation&lt;/h3&gt;
&lt;p&gt;LLMs can generate code, making it easier for developers to create complex software programs. We can write a code comment describing what we wish the code to do and the LLM will be able to do it for us to the best of its effort. The more complex things we wish the code to do, the more specific and descriptive we will need to be in the prompt comment.&lt;/p&gt;
&lt;p&gt;The template may vary depending on the programming language we want to generate but I would advise to roughly follow this template:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Template&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;&amp;lt;Comment symbol of your language of choice (/* or &#39;&#39;&#39; or #)&gt;
Method: &amp;lt;Name of the method&gt;
Language: &amp;lt;Programming language&gt;
Description: &amp;lt;Description of what the method must do&gt;
Parameters: &amp;lt;Parameters that the method will receive&gt;
Context: &amp;lt;Further information needed to implement the method (URLs, databases, etc.)&gt;
Output: &amp;lt;Output of the method&gt;
&amp;lt;Comment symbol of your language of choice (/* or &#39;&#39;&#39; or #)&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For example, if we want to fetch an API with pagination we could write the following comment:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prompt&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;/* Method: fetchFirst5Pages
 * Language: Javascript
 * Description: Fetch the first 5 pages from this paginated API: http://example.com/pages/?n=x
 * Context: This API accepts the following URL parameters:
 *   n: the number of the page to fetch
 * Output: the content of the first 5 pages
 */&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Output&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;Here&#39;s an example implementation of the fetchFirst5Pages method in JavaScript, assuming the use of the fetch function:

async function fetchFirst5Pages() {
  const baseUrl = &#39;http://example.com/pages/?n=&#39;;
  const pages = [];

  for (let i = 1; i &amp;lt;= 5; i++) {
    const url = baseUrl + i;
    const response = await fetch(url);

    if (!response.ok) {
      throw new Error(`Error fetching page ${i}`);
    }

    const pageData = await response.json();
    pages.push(pageData);
  }

  return pages;
}

This function uses a loop to fetch the first 5 pages from the API by appending the page number to the base URL. It checks if the response from the server is okay and throws an error if it&#39;s not. Then, it parses the JSON data from the response and adds it to an array of pages. Finally, it returns the array of pages.&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;reasoning&quot; tabindex=&quot;-1&quot;&gt;Reasoning&lt;/h3&gt;
&lt;p&gt;LLMs can struggle with some basic tasks, such as arithmetic problems. However, if we ask the LLM to reason upon its response, we can help it get to the right answer. This is the template I recommend:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Template&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;Q: &amp;lt;Question&gt;
A: Let&#39;s work this out in a step by step way to be sure we have the right answer. First, &amp;lt;Instructions&gt;.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example we can see that a simple arithmetic question fails if we ask it without reasoning:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prompt&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;Answer the following question. Respond &quot;Not sure&quot; if not sure about the answer.
Q: The sum of prime numbers in the following list are a multiple of 3: [2, 4, 6, 7, 9, 14]
A: [Yes or No]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Output&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;No. The sum of prime numbers in the list [2, 4, 6, 7, 9, 14] is not a multiple of 3. Therefore, the answer is &quot;No&quot;.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, if we instruct the LLM to reason its answer, we get a very different result:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prompt&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;Q: The sum of prime numbers in the following list are a multiple of 3: [2, 4, 6, 7, 9, 14]
A: Let&#39;s work this out in a step by step way to be sure we have the right answer. First, we find the prime numbers in the list and add them together. Then we check whether the resulting number can be divided by 3.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Output&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;Sure, let&#39;s work this out step by step.

The prime numbers in the list are 2 and 7. So we can add them together:

2 + 7 = 9

The resulting number is 9. Now we need to check whether it is a multiple of 3. We can do this by checking if the remainder of 9 divided by 3 is equal to 0:

9 % 3 = 0

Since the remainder is 0, we know that 9 is indeed a multiple of 3.

Therefore, the answer is &quot;Yes&quot;, the sum of prime numbers in the list [2, 4, 6, 7, 9, 14] is a multiple of 3.&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;strategies&quot; tabindex=&quot;-1&quot;&gt;Strategies&lt;/h2&gt;
&lt;p&gt;While these templates will help you to squeeze the potential of LLMs for your needs, sometimes they can still struggle with certain complex tasks. A few techniques have been developed to help LLMs get to a satisfactory answer. Until now, we have only used zero-shot prompting, which we will now define. However, we can use more complex techniques.&lt;/p&gt;
&lt;h3 id=&quot;zero-shot-prompting&quot; tabindex=&quot;-1&quot;&gt;Zero-shot prompting&lt;/h3&gt;
&lt;p&gt;We have been using zero-shot prompting for all examples in this article. Zero-shot prompting means passing a prompt to the LLM with just the question we want it to answer, without any examples of how it should respond in other cases. For example, in an earlier example we did:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prompt&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;Classify the text into positive, neutral or negative:
Text: That shot selection was awful
Classification:&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Output&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;Negative&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This might not be enough context for the model to answer exactly how we want it to. Let&#39;s see what alternatives we have.&lt;/p&gt;
&lt;h3 id=&quot;few-shot-prompting&quot; tabindex=&quot;-1&quot;&gt;Few-shot prompting&lt;/h3&gt;
&lt;p&gt;As opposed to zero-shot prompting, with few-shot prompting we give the LLM a few examples of how it should respond before we ask the question. For example, let&#39;s say we want to classify the sentiment of a text like in the previous example. But we want it to give us the answer in a very specific format every time. We could give it a few examples beforehand like so:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prompt&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;Classify the text into positive, neutral or negative:
Text: Today the weather is fantastic
Classification: Pos
Text: The furniture is small.
Classification: Neu
Text: I don&#39;t like your attitude
Classification: Neg
Text: That shot selection was awful
Classification:&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Output&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;Neg&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;chain-of-thought-prompting&quot; tabindex=&quot;-1&quot;&gt;Chain of thought prompting&lt;/h3&gt;
&lt;p&gt;For even more complex tasks, we can combine few-shot prompting with making the model reason about its answer. We can use the same example as before to see how reasoning and few-shot prompting affect the result:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prompt&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;Q: The sum of prime numbers in the following list are a multiple of 3: [2, 4, 6, 7, 9, 14]
A: The prime numbers in the list are 2 and 7. Their sum is 9. 9 % 3 = 0. The answer is yes.
Q: The sum of prime numbers in the following list are a multiple of 3: [1, 2, 4, 7, 8, 10]
A: The prime numbers in the list are 1, 2 and 7. Their sum is 10. 10 % 3 = 1. The answer is no.
Q: The sum of prime numbers in the following list are a multiple of 3: [1, 2, 3, 4]
A: The prime numbers in the list are 1, 2 and 3. Their sum is 6. 6 % 3 = 0. The answer is yes.
Q: The sum of prime numbers in the following list are a multiple of 3: [5, 6, 7, 8]
A:&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Output&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;The prime numbers in the list are 5 and 7. Their sum is 12. 12 % 3 = 0. The answer is yes.&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;final-note&quot; tabindex=&quot;-1&quot;&gt;Final note&lt;/h2&gt;
&lt;p&gt;LLMs have revolutionized the field of natural language processing, but to maximize their potential, prompt engineering is essential. By understanding the tasks LLMs can perform, their shortcomings, and various prompt engineering strategies, developers can harness the power of LLMs to create innovative and effective solutions. More strategies and techniques will likely be developed in the close future so be tuned in to further advancements in this field to maximize LLM potential even more. Moreover, as LLMs continue to grow bigger with billions of additional parameters, it is probable that more tasks that we cannot even think of right now will be very possible. It&#39;s amazing to think of what will be possible using these new tools and which use cases will they serve us in the future.&lt;/p&gt;
</description>
      <pubDate>Sun, 09 Apr 2023 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/articles/ai/maximizing-the-potential-of-llms/</guid>
    </item>
    <item>
      <title>How to install (and keep) extensions in SageMaker Studio</title>
      <link>https://ruxu.dev/articles/mlops/install-extensions-studio/</link>
      <description>&lt;figure&gt;
&lt;img style=&quot;aspect-ratio: 3/2&quot; alt=&quot;Puzzle painting&quot; src=&quot;https://ruxu.dev/articles/mlops/install-extensions-studio/assets/images/puzzle.webp&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;If you have been using SageMaker Studio, you might have missed some features that other modern IDEs have. As you might know, SageMaker Studio is built on top of the JupyterLab IDE. It extends it, integrating with other SageMaker resources. But this doesn&#39;t include any features for developer experience.&lt;/p&gt;
&lt;p&gt;To enrich SageMaker Studio with the features that you need, you can install extensions to JupyterLab. You can do that using different methods.&lt;/p&gt;
&lt;p&gt;You can use the &lt;strong&gt;Extension Manager&lt;/strong&gt;, found in the menu on the left. It has a puzzle piece icon. Inside the Extension Manager, you can check the already installed extensions. You can also search for extensions if you write the name in the search bar. When you have found the extension you want to install, click the &amp;quot;Install&amp;quot; button. After installing all the needed extensions, restart the JupyterLab by refreshing the page. You should now be able to use them.&lt;/p&gt;
&lt;figure style=&quot;display: flex&quot;&gt;
&lt;img alt=&quot;SageMaker Studio Extension Manager&quot; src=&quot;https://ruxu.dev/articles/mlops/install-extensions-studio/assets/images/sagemaker_extensions.webp&quot; style=&quot;width: 450px; margin: 0 auto&quot; width=&quot;450&quot; height=&quot;750&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Another method to install extensions is using the &lt;strong&gt;Jupyter CLI tool&lt;/strong&gt;. For this method, you will need to know the name of the extension beforehand. Open a terminal inside the Studio and type the following commands:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;conda activate studio&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the package you are trying to install is in the &lt;strong&gt;NPM package registry&lt;/strong&gt;, you can install it using the Jupyter CLI:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;jupyter labextension &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; my-extension@1.2.3&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also install extensions that are in the &lt;strong&gt;pip package registry&lt;/strong&gt; with a pip command:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;pip &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; my-extension&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.2&lt;/span&gt;.3&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, execute the following command:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;restart-jupyter-lab&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and refresh the page.&lt;/p&gt;
&lt;p&gt;Installing extensions has a problem in SageMaker Studio. Every time your JupyterServer shuts down, &lt;strong&gt;it&#39;s going to lose all installed extensions and start from a clean state&lt;/strong&gt;. To keep all the installed extensions, you must create a &lt;strong&gt;Lifecycle Configuration&lt;/strong&gt;. This Lifecycle Configuration will install all the extensions on startup. The Lifecycle Configuration will execute a script when the JupyterServer starts. The content of the script will be:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;source&lt;/span&gt; activate studio
jupyter labextension &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; extension-foo
pip &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; extension-bar
restart-jupyter-server&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, in this script we activate the environment with &lt;code&gt;source activate studio&lt;/code&gt; instead of &lt;code&gt;conda activate studio&lt;/code&gt;, this is because conda cannot be used from the lifecycle configuration.&lt;/p&gt;
&lt;p&gt;There are many ways to create a Lifecycle configuration. You can do it via the Console, using a Cloudformation Stack, or via AWS CLI. Using the CLI you could do:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;aws sagemaker create-studio-lifecycle-config &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
&lt;span class=&quot;token parameter variable&quot;&gt;--region&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;your-region&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
--studio-lifecycle-config-name my-studio-lcc &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
--studio-lifecycle-config-content &lt;span class=&quot;token variable&quot;&gt;$LCC_CONTENT&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
--studio-lifecycle-config-app-type JupyterServer &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;$LCC_CONTENT is a string with the content of the script described before. Then, when you create a user profile in the SageMaker Domain, you can bind the Lifecycle Configuration to it:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;aws sagemaker create-user-profile --domain-id &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;DOMAIN-ID&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt; --user-profile-name &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token environment constant&quot;&gt;USER&lt;/span&gt;-PROFILE-NAME&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--region&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;REGION&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt; --user-settings &lt;span class=&quot;token string&quot;&gt;&#39;{ &quot;JupyterServerAppSettings&quot;: {   &quot;LifecycleConfigArns&quot;:     [&quot;&amp;lt;LIFECYCLE-CONFIGURATION-ARN-LIST&gt;&quot;]   } }&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From now on, when users start their instance of SageMaker Studio, they will always have the extensions installed. They will be able to use them from the get go. They will also be able to still install and uninstall extensions from the interface and the terminal, but those changes will only last for the duration of the Studio session.&lt;/p&gt;
</description>
      <pubDate>Sun, 07 Aug 2022 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/articles/mlops/install-extensions-studio/</guid>
    </item>
    <item>
      <title>How to disable the download button in SageMaker Studio</title>
      <link>https://ruxu.dev/articles/mlops/disable-download-button-sagemaker/</link>
      <description>&lt;figure&gt;
&lt;img style=&quot;aspect-ratio: 897/467&quot; alt=&quot;Painting desk&quot; src=&quot;https://ruxu.dev/articles/mlops/disable-download-button-sagemaker/assets/images/security.webp&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Many enterprises choose a cloud environment to power the work of their data science team. If you chose the AWS SageMaker Studio, this article might interest you. Having both the data lake and the data scientist environment makes it easy to integrate them. You can choose what data any given data scientist is able to see. You might want a data scientist only to be able to use this data inside the SageMaker Studio environment. However, SageMaker Studio has a download button that lets data scientists download any data they have been working on. Once they have downloaded data to their computers, they are free to share it anywhere and with anyone.&lt;/p&gt;
&lt;p&gt;Luckily, &lt;strong&gt;it is possible to disable this download button&lt;/strong&gt;. Recently, it was only possible to disable the download button in SageMaker Notebooks. &lt;a href=&quot;https://ujjwalbhardwaj.me/post/disable-download-button-on-the-sagemaker-jupyter-notebook/&quot;&gt;This article from Ujjwal Bhardwaj&lt;/a&gt; shows how to disable it in SageMaker Notebooks.&lt;/p&gt;
&lt;p&gt;But AWS updated SageMaker Studio and now it can also disable the download button. This update lets us configure Studio to use JupyterLab version 3. In this version, JupyterLab refactored some features, including the download button. Now, &lt;strong&gt;those features are plugins included by default by JupyterLab, instead of hardcoded in the JupyterLab core&lt;/strong&gt;. This means that it is now possible to disable these plugins and they won&#39;t show up in the UI.&lt;/p&gt;
&lt;p&gt;The plugins that include a download button in the JupyterLab UI are the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;@jupyterlab/docmanager-extension:download&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;@jupyterlab/filebrowser-extension:download&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are a couple of ways to disable those plugins. The most straightforward is to run these commands in a SageMaker Studio terminal:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;conda activate studio
jupyter labextension disable jupyterlab/docmanager-extension:download
jupyter labextension disable @jupyterlab/filebrowser-extension:download
restart-jupyter-server&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also use the JupyterLab configuration files. Edit the file &lt;code&gt;/opt/conda/envs/studio/etc/jupyter/labconfig/page_config.json&lt;/code&gt; with the following content:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;disabledExtensions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;@jupyterlab/docmanager-extension:download&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;@jupyterlab/filebrowser-extension:download&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and run the command:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;restart-jupyter-server&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You might also have to refresh the page to see the changes take place.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The problem with these approaches is that changes will only last for the duration of the session&lt;/strong&gt;. To make the changes permanent, you have to create a &lt;strong&gt;Studio Lifecycle Configuration&lt;/strong&gt;. The Lifecycle Configuration will execute a script when the JupyterServer starts. In this script, you will edit the file in the previous example.&lt;/p&gt;
&lt;p&gt;The content of the script will be:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; /opt/conda/envs/studio/etc/jupyter/labconfig/page_config.json
&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;  &lt;span class=&quot;token entity&quot; title=&quot;&#92;&#92;&quot;&gt;&#92;&#92;&lt;/span&gt;&quot;&lt;/span&gt;disabledExtensions&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;: {&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; /opt/conda/envs/studio/etc/jupyter/labconfig/page_config.json
&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;    &lt;span class=&quot;token entity&quot; title=&quot;&#92;&#92;&quot;&gt;&#92;&#92;&lt;/span&gt;&quot;&lt;/span&gt;@jupyterlab/docmanager-extension:download&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;: true,&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; /opt/conda/envs/studio/etc/jupyter/labconfig/page_config.json
&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;    &lt;span class=&quot;token entity&quot; title=&quot;&#92;&#92;&quot;&gt;&#92;&#92;&lt;/span&gt;&quot;&lt;/span&gt;@jupyterlab/filebrowser-extension:download&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;: true&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; /opt/conda/envs/studio/etc/jupyter/labconfig/page_config.json
&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;  }&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; /opt/conda/envs/studio/etc/jupyter/labconfig/page_config.json
&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;}&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; /opt/conda/envs/studio/etc/jupyter/labconfig/page_config.json
restart-jupyter-server&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are many ways to create a Lifecycle configuration. You can do it via the Console, using a Cloudformation Stack, or via AWS CLI. Using the CLI you could do:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;aws sagemaker create-studio-lifecycle-config &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
&lt;span class=&quot;token parameter variable&quot;&gt;--region&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;your-region&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
--studio-lifecycle-config-name my-studio-lcc &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
--studio-lifecycle-config-content &lt;span class=&quot;token variable&quot;&gt;$LCC_CONTENT&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
--studio-lifecycle-config-app-type JupyterServer &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;$LCC_CONTENT is a string with the content of the script described before. Then, when you create a user profile in the SageMaker Domain, you can bind the Lifecycle Configuration to it:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;aws sagemaker create-user-profile --domain-id &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;DOMAIN-ID&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt; --user-profile-name &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token environment constant&quot;&gt;USER&lt;/span&gt;-PROFILE-NAME&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--region&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;REGION&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt; --user-settings &lt;span class=&quot;token string&quot;&gt;&#39;{ &quot;JupyterServerAppSettings&quot;: {   &quot;LifecycleConfigArns&quot;:     [&quot;&amp;lt;LIFECYCLE-CONFIGURATION-ARN-LIST&gt;&quot;]   } }&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From now on, every time a data scientist opens their instance of SageMaker Studio, it should never display a download button. This efectively blocks them from downloading any files located in their Studio, as long as they are not able to revert these changes themselves from their terminal. Also, note that disabling the download plugin only removes all the download buttons from the interface. This does not mean that if there are other means of downloading files those are also blocked.&lt;/p&gt;
</description>
      <pubDate>Sat, 06 Aug 2022 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/articles/mlops/disable-download-button-sagemaker/</guid>
    </item>
    <item>
      <title>Feature Store - Why do you need one?</title>
      <link>https://ruxu.dev/articles/mlops/feature-stores/</link>
      <description>&lt;figure&gt;
&lt;img style=&quot;aspect-ratio: 3/2&quot; alt=&quot;Painting desk&quot; src=&quot;https://ruxu.dev/articles/mlops/feature-stores/assets/images/paint.jpg&quot; /&gt;
&lt;figcaption&gt;Painter photo created by rawpixel.com - www.freepik.com&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;A feature store is a storage system for features&lt;/strong&gt;. Features are properties of data calculated through an ETL process or feature pipeline. This pipeline takes raw data and calculates a property from it. This property - usually a numeric value - will be useful to a machine learning model. It is important to find adequate, correct, and quality features. The quality of those features is the most important contributor to a model&#39;s success.  The model will use the features either to train itself or to make predictions. A feature store will help to organize and use those features.&lt;/p&gt;
&lt;p&gt;At its core, &lt;strong&gt;a feature store is only a database&lt;/strong&gt;. More specifically, there are usually two databases. There is an &lt;strong&gt;offline store&lt;/strong&gt; equipped to store large sums of data, like an HBase or S3. There is also an &lt;strong&gt;online store&lt;/strong&gt; equipped for fast data serving, like Cassandra. Features are organized in feature groups, which can be thought of as tables. Features that are used together are stored in the same feature group so access to them is faster and without joins. There are many ETL processes (think Spark) that write to the offline store. Data from the offline store replicates to the online store to keep them consistent. Data streams can also write both to the online and offline stores, for fast real-time data access.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Architecture of Michelangelo Pallete feature store developed at Uber&quot; src=&quot;https://miro.medium.com/max/1400/0*F4gGPz8PukepaG5r.png&quot; /&gt;
&lt;figcaption&gt;Architecture of Michelangelo Pallete feature store developed at Uber&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;In this article, I will lay out the advantages of including a Feature Store in your data architecture. Prescribing solutions to all cases without further thought is definitely not the answer. But almost every Data Science team will benefit from having a feature store, even if it is small.&lt;/p&gt;
&lt;h3 id=&quot;reusable-features&quot; tabindex=&quot;-1&quot;&gt;Reusable features&lt;/h3&gt;
&lt;p&gt;The principal reason to be for a feature store is to empower data scientists to &lt;strong&gt;reuse features&lt;/strong&gt;. Building feature pipelines takes around 80% of data scientists&#39; time. Avoiding repeated feature engineering work will result in a faster work cycle. One example of feature reuse is for sharing features between training and inference. The features used for training are roughly the same as the features used for making a prediction. Another example of feature reuse is between teams or projects. Features related to core enterprise concepts are usually used throughout different ML projects. To encourage reuse, features must be discoverable through the feature store.&lt;/p&gt;
&lt;h3 id=&quot;feature-consistency&quot; tabindex=&quot;-1&quot;&gt;Feature consistency&lt;/h3&gt;
&lt;p&gt;Another benefit of centralizing features in a single feature store is &lt;strong&gt;feature consistency&lt;/strong&gt;. Different data science teams might calculate similar features slightly differently. Those features might be the same concept and data scientists will have to agree to unify them. Then, if the process to calculate the feature changes, it changes for all the projects that use it. Or they might be a different concept, and data scientists will have to categorize them according to their separate quirks.&lt;/p&gt;
&lt;h3 id=&quot;point-in-time-correctness&quot; tabindex=&quot;-1&quot;&gt;Point-in-time correctness&lt;/h3&gt;
&lt;p&gt;Feature stores also enable point-in-time correctness. The online store will always have the latest value for a feature. The offline store will store all historical values the feature had at any point. This enables data scientists to work with old values, aggregate time ranges, and so on. It also ensures the &lt;strong&gt;reproducibility&lt;/strong&gt; of a model. At any point, we can recover the data used in a past training or in a past inference to debug the model.&lt;/p&gt;
&lt;h3 id=&quot;data-health&quot; tabindex=&quot;-1&quot;&gt;Data health&lt;/h3&gt;
&lt;p&gt;One can also generate statistics from the feature store to monitor the health of the data. If the &lt;strong&gt;data drifts&lt;/strong&gt; (its health or structure changes over time), it can be automatically detected in the pipeline. Statistics can also help explain how a feature affects the predictions of each model.&lt;/p&gt;
&lt;h3 id=&quot;data-lineage&quot; tabindex=&quot;-1&quot;&gt;Data lineage&lt;/h3&gt;
&lt;p&gt;Using the catalog of features and models, you can draw a &lt;strong&gt;data lineage&lt;/strong&gt;. This data lineage shows the data source used to create each feature. It also shows the models or other feature pipelines that use the feature. This graph enables debugging problems with data. It becomes trivial to track down where a piece of data came from and how it is being used.&lt;/p&gt;
&lt;h3 id=&quot;online-store&quot; tabindex=&quot;-1&quot;&gt;Online store&lt;/h3&gt;
&lt;p&gt;In some use cases, an ML model will have a low-latency requirement. For example, if a model is being called from an API call, the user will expect a response within a few seconds. This requires very fast access to features. Instead of calculating them each time, we can access the precalculated features in the online store. We know that the online store is always going to have the up-to-date last value of the feature. The online store is also optimized for sub-second queries for a fast response.&lt;/p&gt;
&lt;p&gt;Don&#39;t use a feature store if you don&#39;t have to. But if your organization has a medium-sized ML team or several ML teams, or it has any of the needs I exposed, consider introducing a feature store. &lt;strong&gt;It will only benefit your data science teams in the long run.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;how-to-start-using-a-feature-store-now&quot; tabindex=&quot;-1&quot;&gt;How to start using a feature store now?&lt;/h3&gt;
&lt;p&gt;You can build a feature store putting together your own components like Uber did with Michelangelo. You could use Hive for the offline store, Cassandra and Redis for the online store, Kafka for streaming real-time data and a Spark cluster to run ETL processes. On the other hand, you could also trust other people that have already built feature stores and use their solutions. You can choose an open-source solution and host it yourself. Some open-source solutions are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Feast:&lt;/strong&gt; a minimal Feature Store that lacks some features like an ETL system and data lineage. Feast has integration support with tools from GCP (BigQuery as offline store and Datastore as online store) and AWS (Redshift, DynamoDB). It also has integration support for other agnostic tools like Snowflake, Redis or Kafka.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hopsworks:&lt;/strong&gt; very complete Feature store. It includes tools like a Model Registry, multi-tenant governance, data lineage and much more. It can be deployed either in GCP, AWS, Azure or in premise. This is because Hopsworks provides its own technology, instead of integrating with other sources like Feast. Hopsworks is deployed in a Kubernetes cluster. This cluster includes a RonDB database for the online store and integrates with S3/Bucket for the offline store.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can also choose a SaaS tool instead of open-source. Some examples include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Databricks Feature Store:&lt;/strong&gt; it is integrated inside the Databricks Lakehouse Platform. Therefore, it is a good fit if you are already using Databricks as your ML platform. It uses Delta Lake as an offline store and can be integrated with either AWS DynamoDB, AWS RDS or AWS Aurora as an online store.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SageMaker Feature Store:&lt;/strong&gt; fully managed feature store by AWS. It uses S3 as an offline store and DynamoDB as an online store. It integrates with all the other tools in the SageMaker environment and with data sources within AWS like Redshift, Athena and S3.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vertex AI Feature Store:&lt;/strong&gt; a feature store fully managed by Google in their cloud provider GCP. It uses BigQuery as an offline store and BigTable as an online store. It integrates with all the other tools in the Vertex AI environment and with BigQuery and GCS as data sources.&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Fri, 05 Aug 2022 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/articles/mlops/feature-stores/</guid>
    </item>
    <item>
      <title>Bun - What can I use it for?</title>
      <link>https://ruxu.dev/articles/languages-and-frameworks/bun/</link>
      <description>&lt;p&gt;In recent years, the web development landscape has discovered that, while super stylized websites and web applications with tons of very rich interactions made with Javascript might be appealing to users, the loading time of the page can be a hundred times more influential to the user&#39;s perspective of the experience. As a result, there has been a ton of effort to reduce the loading time metrics of websites. Many frameworks and patterns have (re-)emerged to give solutions to this problem, like Server-Side Rendering and Static Site Generation.&lt;/p&gt;
&lt;p&gt;Enter Jarred Sumner. Jarred noticed that an action as simple as printing to the console was extremely slow in Node.js. Here&#39;s an example of the time it takes to execute a &amp;quot;Hello world&amp;quot; program in Node.js and Rust.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;log.js&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Hello world!&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; log.js
Hello world&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; log.js  &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;,13s user &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;,02s system &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;% cpu &lt;span class=&quot;token number&quot;&gt;0,152&lt;/span&gt; total&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;log.rs&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token macro property&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello world!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ rustc log.rs
$ &lt;span class=&quot;token function&quot;&gt;time&lt;/span&gt; ./log
Hello world&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
./log  &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;,00s user &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;,00s system &lt;span class=&quot;token number&quot;&gt;86&lt;/span&gt;% cpu &lt;span class=&quot;token number&quot;&gt;0,004&lt;/span&gt; total&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Jarred said he was very bothered by this fact, as well as other realities from the Javascript world, like having to choose and harmonize multiple tools - the runtime, the bundler, the transpiler... He was sure this didn&#39;t have to be the case and he set out on a one-man journey to build Bun.&lt;/p&gt;
&lt;h3 id=&quot;what-exactly-is-bun&quot; tabindex=&quot;-1&quot;&gt;What exactly is Bun?&lt;/h3&gt;
&lt;p&gt;Bun is first and foremost a Javascript runtime like Node.js and Deno. It is designed to be &lt;strong&gt;a blazingly fast Javascript runtime&lt;/strong&gt;. But don’t worry, embracing this new runtime does not mean having to refactor all of your existing code. Bun implements most of the Node APIs and Web APIs like fs, fetch, Buffer, WebSocket, and much more. Furthermore, &lt;strong&gt;Bun is also compatible with most NPM packages&lt;/strong&gt;, even though it uses its own package manager, which is, again, built for speed.&lt;/p&gt;
&lt;p&gt;But Bun is not just a Javascript runtime, it comes with batteries included. &lt;strong&gt;It comes with all the tools that are usually needed in a Javascript project: a package manager, a bundler, and a transpiler that not only works for Javascript, it also works for Typescript and JSX out-of-the-box&lt;/strong&gt;. Moreover, it also includes a native implementation for &lt;strong&gt;dotenv configuration loading and an SQLite3 client&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Here&#39;s an example of installing a regular-sized package.json using NPM v8.15 and the Bun package manager v0.1.5:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt;

added &lt;span class=&quot;token number&quot;&gt;563&lt;/span&gt; packages, and audited &lt;span class=&quot;token number&quot;&gt;564&lt;/span&gt; packages &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; 3m

&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;166&lt;/span&gt;,14s user &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;,06s system &lt;span class=&quot;token number&quot;&gt;92&lt;/span&gt;% cpu &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;:16,08 total&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ bun &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt;
bun &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; v0.1.5

 &lt;span class=&quot;token number&quot;&gt;563&lt;/span&gt; packages installed &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt;.70s&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;but-how-is-bun-so-fast&quot; tabindex=&quot;-1&quot;&gt;But how is Bun so fast?&lt;/h3&gt;
&lt;p&gt;The speed of Bun can be explained by two main factors: The choice of Javascript engine and low-level optimization of native implementations.&lt;/p&gt;
&lt;p&gt;Both Node.js and Deno use the V8 Javascript engine. While V8 is an awesome engine that powers the Chrome web browser, Bun chose to go for the option that would yield the best performance at any cost. Jarred chose to use &lt;strong&gt;the JavascriptCore engine&lt;/strong&gt; for building Bun, which is the engine that powers Webkit and it seems that performs better in start time as well as in some specific cases.&lt;/p&gt;
&lt;p&gt;Another decision that helped optimize Bun to the extreme is the choice of &lt;strong&gt;Zig&lt;/strong&gt; as the language it is built in. Zig is a low-level programming language without a garbage collector, like C or Rust. While those two could have been great choices to build Bun in, Zig has some unique features that Jarred valued, which ultimately led him to choose Zig over other languages. First, Zig has no hidden control flow, which makes it easier to ensure that no secondary functions are unexpectedly called when running it. Also, Zig has a feature named &amp;quot;CompTime&amp;quot;. With CompTime you can mark a piece of code to be executed at compile time instead of execution time, saving any precious time that can be scratched from the final execution time.&lt;/p&gt;
&lt;h3 id=&quot;using-bun&quot; tabindex=&quot;-1&quot;&gt;Using Bun&lt;/h3&gt;
&lt;p&gt;To use Bun, first install it with the following command:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; https://bun.sh/install &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;bash&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Yes, it is a shell command. No, (at the time of writing this article) it does not work for Windows. You can now start using Bun.&lt;/p&gt;
&lt;p&gt;For this example, we will build a web server. Bun comes with an HTTP server out-of-the-box. If the file used to start bun has a default export with a fetch function, it will start the HTTP server, but you can also use &lt;code&gt;Bun.serve()&lt;/code&gt; for clarity. Here&#39;s a basic example:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;http.ts&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  port&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Response &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello world!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that for this example no library is needed. Both Typescript and the HTTP server just work. Now, let&#39;s run the code and check that the server is up and running:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ bun run http.ts&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; http://localhost:3000
Hello world&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Excellent! We can now introduce new features to the server. We could use the improved Node.js API for reading and returning the contents of a file. We can also use the built-in SQLite client to fetch records from a database. Using the tools that Bun provides, we can implement this easily:&lt;/p&gt;
&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  readFileSync
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;fs&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Database
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;bun:sqlite&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  port&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Response&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; urlParts &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;https?:&#92;/&#92;/.+&#92;/(.*)&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resource&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; urlParts&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resource &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;file&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; file&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;readFileSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/home/roger/Projects/experiments/log/file.txt&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; encoding&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;utf-8&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;file&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resource &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;db&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; db &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Database&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;db.sqlite&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; query &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;SELECT * FROM foo&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; query&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Hello world!&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;what-can-i-use-bun-for&quot; tabindex=&quot;-1&quot;&gt;What can I use Bun for?&lt;/h3&gt;
&lt;p&gt;Let&#39;s be clear: &lt;strong&gt;Bun is not ready for production applications&lt;/strong&gt;. At the time of writing this article, the last version of Bun is the beta version 0.1.5. It still has a small ecosystem and community, many missing APIs, and some bugs and performance issues in edge cases. Nevertheless, this is a temporary problem; Jarred and the community are working tirelessly to build all the missing tools and APIs and fix all bugs. When first writing this article, I described some problems like performance spikes and illegal hardware instructions. But these problems are being solved so quickly that this article would be constantly out-of-date. Also, libraries specifically built for Bun are appearing constantly. Probably, in the not-so-distant future, Bun will be a great tool to be used in production environments, so it would be wise to keep an eye on it.&lt;/p&gt;
&lt;p&gt;That doesn&#39;t mean that you shouldn&#39;t use Bun right now. If you need to build &lt;strong&gt;an application that is not production-sensitive&lt;/strong&gt; it could be the way to go. If you want to build a quick proof-of-concept app and don&#39;t want to fiddle with Typescript and transpiler libraries it could be a great solution. Another possible use could be if you need to write a script that needs to perform at it&#39;s best and you cannot be bothered to write it in Rust or C.&lt;/p&gt;
&lt;p&gt;In conclusion, keep an eye in Bun. What Jarred has built in just a year has already made a big impact in the Javascript community and it has the potential to completely revolutionize it.&lt;/p&gt;
</description>
      <pubDate>Tue, 26 Jul 2022 00:00:00 GMT</pubDate>
      <dc:creator>Roger Oriol</dc:creator>
      <guid>https://ruxu.dev/articles/languages-and-frameworks/bun/</guid>
    </item>
  </channel>
</rss>
