<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mani</title>
    <description>The latest articles on DEV Community by Mani (@manikumar).</description>
    <link>https://dev.to/manikumar</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F577099%2F0f68fd99-ed28-47a1-a109-65c9c63bc2ee.jpg</url>
      <title>DEV Community: Mani</title>
      <link>https://dev.to/manikumar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/manikumar"/>
    <language>en</language>
    <item>
      <title>Demystifying ChatGPT</title>
      <dc:creator>Mani</dc:creator>
      <pubDate>Fri, 24 Nov 2023 16:52:23 +0000</pubDate>
      <link>https://dev.to/manikumar/demystifying-chatgpt-1khp</link>
      <guid>https://dev.to/manikumar/demystifying-chatgpt-1khp</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The world is rapidly advancing with impressive technologies, with ChatGPT being a standout in modern innovation. It is astounding how a simple input box on a webpage can provide answers like a knowledgeable professor. This blog aims to demystify that process at a high level, making it easy to grasp. Let's dive in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is ChatGPT&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ChatGPT is an advanced AI program developed by OpenAI, which interacts in a conversational way. It is designed to understand and generate human-like text based on the input it receives. To unpack this, let's start from the basics and work our way through the complex architecture that powers it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI and Machine Learning Explained at a High Level&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Artificial Intelligence is a broad field of computer science focused on creating machines capable of performing tasks that typically require human intelligence. This includes things like recognizing speech, making decisions, and, in our case, understanding and generating human language.&lt;/p&gt;

&lt;p&gt;Within AI is a subset called machine learning, where machines learn from data. Think of it like teaching a child through examples. Instead of programming the AI with specific instructions for every possible situation, machine learning allows the AI to learn and adapt from examples and improve over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Neural Networks: The Brain of AI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At the heart of machine learning are neural networks, which are algorithms modeled loosely after the human brain. They are composed of layers of nodes, or "neurons" each layer designed to recognize increasingly complex features in the data it's fed. For ChatGPT, these neurons process parts of language, from simple grammar to complex dialogue context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How ChatGPT Works: Transformer Architecture&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ChatGPT is based on a specific type of neural network called the Transformer architecture. This architecture is particularly well-suited for processing sequences of data, like sentences in a conversation. It uses mechanisms called attention mechanisms that help the system focus on different parts of the input text to generate a coherent and contextually relevant response.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Training: Teaching AI with Data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To become proficient in language, ChatGPT was trained on a diverse range of internet text. Training involves showing the AI lots of examples of human language, so it learns patterns and nuances. During training, the model adjusts its internal parameters to minimize the difference between its output and the expected output. This process involves a staggering amount of computation and data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fine-Tuning: Specializing the Knowledge&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After the initial training, ChatGPT undergoes fine-tuning, where it's further trained on specific types of conversations to improve its performance on certain tasks, like answering questions or writing essays.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generative Pre-trained Transformer (GPT): The Origin&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The "GPT" in ChatGPT stands for Generative Pre-trained Transformer. "Generative" indicates that the model can generate text, "Pre-trained" signifies that it has been trained on a large dataset before it's fine-tuned for specific tasks, and "Transformer" is the type of neural network it’s based on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interacting with ChatGPT&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you type a message to ChatGPT, it processes your text, predicting what comes next in the conversation based on its training. It doesn't have understanding in the human sense but uses statistical patterns to generate a plausible response.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Limitations and Considerations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ChatGPT isn't perfect. It can make mistakes, and because it learns from data that may contain biases, it can sometimes reproduce these biases. OpenAI continuously works on improving the model to mitigate these issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ChatGPT is a culmination of several advanced AI concepts, from neural networks to transformer architecture, and represents a significant stride in natural language processing. For beginners, it's like a highly sophisticated digital parrot with a very good memory—it can mimic human-like responses by recognizing patterns in data, but it doesn't understand in the way humans do. It's a tool that reflects the current state of AI, where machines can appear remarkably smart, as long as we remember that their intelligence is a reflection of the data they've been fed.&lt;/p&gt;

</description>
      <category>chatgpt</category>
    </item>
    <item>
      <title>Building SVG Loader</title>
      <dc:creator>Mani</dc:creator>
      <pubDate>Tue, 22 Mar 2022 03:00:43 +0000</pubDate>
      <link>https://dev.to/manikumar/building-svg-loader-26o9</link>
      <guid>https://dev.to/manikumar/building-svg-loader-26o9</guid>
      <description>&lt;p&gt;In this post, I want to share how I built the Meesho loader using SVG as shown below. I have explained in a way even If you are complete beginner to SVG, you can expect to understand this implementation.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The intend of developing this loader is to leverage the inbuilt SVG APIs in HTML5 and avoiding gif usage for simple animations. &lt;/p&gt;

&lt;p&gt;SVG can be scaled up without quality loss and comparatively very small in size. SVG can also work with CSS very well in order to achieve desirable shapes with animations. Javascript is not mandatorily required for SVG unlike Canvas and WebGL. SVG can be rendered before external script download and parse delay.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let us look at the code&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1 - Set SVG dimensions&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;svg xmlns="http://www.w3.org/2000/svg" width="300" height="300"&amp;gt;
&amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above block of code creates and allocates 300 X 300 space for SVG. We can consider this as a drawing board setup. By default SVG consider the unit in pixels. So It is 300px width and 300px height square here. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2 - Draw a line&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here I have used &lt;code&gt;&amp;lt;path/&amp;gt;&lt;/code&gt; over &lt;code&gt;&amp;lt;line/&amp;gt;&lt;/code&gt; element since there is requirement of lines with circular arc. &lt;/p&gt;

&lt;p&gt;Have given two instructions to &lt;code&gt;&amp;lt;path&amp;gt;&lt;/code&gt; element to draw a line. Each instruction will work with or without comma separated. Have used comma here for better readability.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/manickumar/embed/xxpOpJm?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;M 30, 250&lt;/code&gt; - Move to 30px horizontally from left and 250px vertically from top of SVG block. &lt;br&gt;
&lt;code&gt;L 30 150&lt;/code&gt; - Draw a line from current position to 30px from left, 150px from top.  Since the starting and end position of x values are same, It will be a straight line of length 100px (250 - 150)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3 - Draw an arc&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;A 50 50 0 0 1 130 150&lt;/code&gt; - Draw an arc from current position to 130px from left and 150px from top with the radius of 50px. &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/manickumar/embed/qBpNxXd?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4 - Draw a line again to complete the half shape&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;L 130 250&lt;/code&gt; - Draw a line from end of arc to the position 130 px from left and 250 px from top. This will now show half of the shape that we are trying to draw. All we have to do now is just repeat.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/manickumar/embed/vYpKdrm?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5 - Repeat the steps to complete full shape&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We have to draw one more arc and line to complete. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;M 130 150&lt;/code&gt; - Move again to 130px, 150px position from where we are going to draw an arc.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;A 50 50 0 0 1 230 150&lt;/code&gt; - Draw another arc of same radius to the position of 230px from left and 150px from top.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;L 230 250&lt;/code&gt; - Draw a line from current position to the position of 230px from left and 250px from top.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/manickumar/embed/rNpLJrX?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6 - Adding blunt edge&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To make the edge blunt, Found &lt;code&gt;stroke-linecap: round&lt;/code&gt; style exactly fits my requirement.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/manickumar/embed/XWVKZyW?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 7 - Add another track for animation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For animation, We need another shape in SVG block with dark pink, same size and positions. It would be easy to just copy paste the path and only change the &lt;code&gt;stroke&lt;/code&gt; property (&lt;code&gt;stroke&lt;/code&gt; property helps to fill the path with given color code).&lt;/p&gt;

&lt;p&gt;But We have a problem with using &lt;code&gt;move to&lt;/code&gt; instruction more than once in the &lt;code&gt;&amp;lt;path&amp;gt;&lt;/code&gt; element. When we have multiple &lt;code&gt;move to&lt;/code&gt;, it breaks the path and When try animating it, We would see multiple tracks being animated by considering each &lt;code&gt;move to&lt;/code&gt; as origin with in single &lt;code&gt;path&lt;/code&gt; element. &lt;/p&gt;

&lt;p&gt;Since We have used Move to twice in current shape, That will cause an issue in animation If We take the same code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;path 
  class='track'
  d="M 30 250,L 30 150,A 50 50 0 0 1 130 150, L 130 250,M 130 150,A 50 50 0 0 1 230 150,L 230 250" 
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I thought of overcoming this &lt;code&gt;move to&lt;/code&gt; issue by starting the second curve right from the end of first curve. Which is 130px from left and 250px from top. So instead of Move to , We can draw a line from &lt;code&gt;130, 250 to 130, 150&lt;/code&gt; and then draw an arc. This will not break the path and animation also will work fine. But this solution has issue with blunt edge. Since we are starting from end of curve one, The middle edge becomes not an edge, So that &lt;code&gt;stroke-linecap: round&lt;/code&gt; does not apply to middle edge as shown below.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/manickumar/embed/VwyKmWv?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I ended up solving this issue by splitting the curves into two. &lt;code&gt;Move to&lt;/code&gt; also split the curve but If I split then, I will have control to animate in a way I wanted.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/manickumar/embed/ExogZZK?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 8 - Animate the path&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now it's time to animate, The requirement of animation here is to fill the colour of path gradually from left to right and undoing it in same direction.&lt;/p&gt;

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

&lt;p&gt;We can divide this animation requirement in to two for better understanding and I will be referring this term instead of mentioning whole animation in every places, &lt;/p&gt;

&lt;p&gt;My goal was to only do animation by CSS properties. Since I am building a loader and that needs to be rendered as soon as possible after the HTML and CSS being downloaded and parsed. If Javascript used then I would have make sure it is not externally loaded and parsed also it should not slow down the main thread Since the animation type we are going to implement is infinite, &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;First part&lt;/em&gt;&lt;/strong&gt; - sliding in filled path from left to right direction and change state hidden to visible&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Second part&lt;/em&gt;&lt;/strong&gt; - sliding filled path in same direction but from visible state to hidden. &lt;/p&gt;

&lt;p&gt;As much as I have explored, I found &lt;code&gt;stroke-dashoffset&lt;/code&gt; CSS property which fits my requirement. The default value of &lt;code&gt;stroke-dashoffset&lt;/code&gt; is set to 0, based on the origin where We started our &lt;code&gt;path&lt;/code&gt; element.&lt;/p&gt;

&lt;p&gt;We can set initial offset value equal to total length of path we have, And that will move the path entirely to the left side because we have increased the offset same as length of path element.And that will hide the element from the view port. &lt;/p&gt;

&lt;p&gt;For animation, We can set the final offset value as 0. Which means element which is hidden will slowly come to the view and fully visible at the end. &lt;/p&gt;

&lt;p&gt;Also please note that, To animate using &lt;code&gt;stroke-dashoffset&lt;/code&gt;, We have to use &lt;code&gt;stroke-dasharray&lt;/code&gt; which helps to divide &lt;code&gt;path&lt;/code&gt; into dashes. So we need to declare our curve here as single dash and play with the offset alone. Value of &lt;code&gt;dasharray&lt;/code&gt; will be length of the curve for single dash.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/manickumar/embed/bGawgPX?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;animation: slide 2s infinite ease-in;

@keyframes slide {
  100%{
    stroke-dashoffset: 0;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have implemented the first part of implementation here with the help of &lt;code&gt;animation&lt;/code&gt; property and &lt;code&gt;keyframes&lt;/code&gt; in CSS. &lt;code&gt;keyframes&lt;/code&gt; helps to modify &lt;code&gt;stroke-dashoffset&lt;/code&gt; value at any stage of animation duration. And &lt;code&gt;animation&lt;/code&gt; property consists&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;animation-name: slide 
animation-duration: 2s
animation-iteration-count: infinite
animation-timing-function: ease-in
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Further tasks are, Second part of animation and both the curves are animating in same time, We need to arrange in a way that it is flowing.&lt;/p&gt;

&lt;p&gt;For second part, We can use same logic . To change from hidden state to slide in visible state, We used offset value 1000 to 0. Like the way If we use 0 to -1000 then path can slide out visible to hidden state.&lt;/p&gt;

&lt;p&gt;To avoid animating both the curve same time, We can add &lt;code&gt;animation-delay&lt;/code&gt; to right cure just to align the flow so that It will look like single curve which is being animated from left to right.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/manickumar/embed/RwxGprv?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 8 - Browser compatibility&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Above code works perfectly fine for all chromium based browsers but Safari will not accept &lt;code&gt;stroke-dashoffset&lt;/code&gt; propery value in negative. Which is always annoying as a developer to change your logic or way of implementation just for one browser is not compatible with it. But It is also mandatory to fix otherwise your solution will not go production. So went looking for alternate way of animating the same.&lt;/p&gt;

&lt;p&gt;Before that, Just to add few points on why chrome supports negative offset value and safari does not. As per the W3C specifications, Negative values are not recommended for &lt;code&gt;stroke-dashoffest&lt;/code&gt; to avoid confusion in moving forward and backward direction. But Chrome team might have thought it is not a confusion, but restriction. So they have enabled it. But Safari stick to the specs which is also not questionable. &lt;/p&gt;

&lt;p&gt;Coming back to the solutioning, I straight away could not find the alternate solution for second part of animation to replace negative offset.But after playing with offset and dasharray properties a lot, Arrived to this hacky way I should call it because there is no other proper solution I found.&lt;/p&gt;

&lt;p&gt;We can achieve second part of animation by animating &lt;code&gt;stroke-dasharray&lt;/code&gt; property from &lt;code&gt;1000 0&lt;/code&gt; to &lt;code&gt;0 1000&lt;/code&gt;. Which means from dash width 1000px and gap value 0 to dash width 0 and gap value 1000px. Here since dash value gradually reduces to 0, We can achieve second part of animation. &lt;/p&gt;

&lt;p&gt;So the idea here is to combine both the ways. Animating with &lt;code&gt;dashoffset&lt;/code&gt; value for first part and with &lt;code&gt;dasharray&lt;/code&gt; for second part.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/manickumar/embed/GRyjmoZ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Here, As soon as the first part of animation is done, I am resetting the value for second part instantly at 51%. Instant from 50 to 51 to avoid animation between &lt;code&gt;dasharray&lt;/code&gt; value &lt;code&gt;1000&lt;/code&gt; to &lt;code&gt;1000 0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Also I have increased &lt;code&gt;dashoffset&lt;/code&gt; value by 100px to avoid flickering since we are animating both offset and &lt;code&gt;dasharray&lt;/code&gt; properties.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now that you know How I have built this loader. Please comment If there is any other way the same is possible. Doesn't matter whether it is better approach or not but curious to know.&lt;/p&gt;

</description>
      <category>svg</category>
      <category>strokedashoffset</category>
      <category>strokedasharray</category>
      <category>negativestrokedashoffset</category>
    </item>
  </channel>
</rss>
