<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://rag4j.org/feed.xml" rel="self" type="application/atom+xml" /><link href="https://rag4j.org/" rel="alternate" type="text/html" /><updated>2025-11-23T10:02:16+00:00</updated><id>https://rag4j.org/feed.xml</id><title type="html">RAG4j/p</title><subtitle>RAG4j/p is a java and python project that only contains what you really need to build a Retrieval Augmented  Generation system. Two projects are available. RAG4J is for Java and RAG4P is for Python.</subtitle><entry><title type="html">RAG4j gets new structure and releases v2</title><link href="https://rag4j.org/release/2025/11/23/rag4j-v2-multi-module.html" rel="alternate" type="text/html" title="RAG4j gets new structure and releases v2" /><published>2025-11-23T09:00:00+00:00</published><updated>2025-11-23T09:00:00+00:00</updated><id>https://rag4j.org/release/2025/11/23/rag4j-v2-multi-module</id><content type="html" xml:base="https://rag4j.org/release/2025/11/23/rag4j-v2-multi-module.html"><![CDATA[<p>We’re excited to announce the release of <strong>RAG4j version 2</strong>! This major update brings a complete refactoring of the project into a modern multi-module setup, making it easier than ever to integrate RAG capabilities into your applications.</p>

<h2 id="whats-new-in-v2">What’s new in v2?</h2>

<p>The entire RAG4j project has been restructured into a modular architecture. This means you can now include only the parts you need, keeping your dependencies lean and your project focused. Whether you need just the retrieval components, specific embedders, or particular content store integrations, you can pick and choose what fits your use case.</p>

<p>This modular approach also paves the way for new integrations. We’re making it simpler to add support for new LLM providers, embedders, and vector stores as the ecosystem continues to evolve.</p>

<h2 id="why-rag-matters-in-the-age-of-agents">Why RAG matters in the age of agents</h2>

<p>As AI agents become more prevalent, RAG (Retrieval Augmented Generation) is more important than ever. Agents need access to accurate, up-to-date information to perform their tasks effectively. RAG provides the bridge between Large Language Models and your organization’s knowledge base, enabling agents to:</p>

<ul>
  <li>Access current information beyond their training data</li>
  <li>Ground their responses in factual, retrievable content</li>
  <li>Reduce hallucinations by working with verified sources</li>
  <li>Operate with domain-specific knowledge</li>
</ul>

<h2 id="teaching-rag-again">Teaching RAG again</h2>

<p>With this renewed focus on RAG’s importance, we’re reactivating RAG4j as our primary teaching framework. The project was created to make learning RAG accessible, and the new modular structure makes it even better for workshops and education. You can now explore individual components in isolation, making it easier to understand how each piece contributes to the complete RAG system.</p>

<p>The three core parts of our RAG system remain:</p>
<ul>
  <li><strong>Retrieval</strong>: Finding relevant chunks from your knowledge base</li>
  <li><strong>Generation</strong>: Creating answers with context from the retriever</li>
  <li><strong>Quality</strong>: Measuring and improving your RAG system’s performance</li>
</ul>

<h2 id="get-started-with-v2">Get started with v2</h2>

<p>Ready to try RAG4j v2? Head over to the <a href="https://github.com/RAG4J/rag4j">RAG4j repository</a> to get started. The new modular structure maintains the same ease of use that made RAG4j popular for learning, while providing the flexibility needed for production applications.</p>

<p>Stay tuned for upcoming workshops and tutorials showcasing the new capabilities!</p>]]></content><author><name></name></author><category term="release" /><summary type="html"><![CDATA[We’re excited to announce the release of RAG4j version 2! This major update brings a complete refactoring of the project into a modern multi-module setup, making it easier than ever to integrate RAG capabilities into your applications.]]></summary></entry><entry><title type="html">Java Magazine Example</title><link href="https://rag4j.org/examples/2025/01/06/article-java-magazine-2025.html" rel="alternate" type="text/html" title="Java Magazine Example" /><published>2025-01-06T04:00:00+00:00</published><updated>2025-01-06T04:00:00+00:00</updated><id>https://rag4j.org/examples/2025/01/06/article-java-magazine-2025</id><content type="html" xml:base="https://rag4j.org/examples/2025/01/06/article-java-magazine-2025.html"><![CDATA[<p>Hi, this is the example accompanying the article I wrote for Java Magazine. Following this tutorial, you build your custom RAG application using the Rag4j application. First, you set up your environment; you create the application to index all the talks from the JFall 2024 conference. Next, you create a retriever to search for similar content to a question. Finally, you make the answer generator and measure the quality of your solution.</p>

<ul>
  <li><a href="#setting-up-your-environment">Setting up your environment</a>
    <ul>
      <li><a href="#using-the-maven-repository-on-github">Using the maven repository on Github</a></li>
      <li><a href="#installing-ollama">Installing Ollama</a></li>
    </ul>
  </li>
  <li><a href="#creating-the-java-application">Creating the Java Application</a>
    <ul>
      <li><a href="#ingest-data">Ingest data</a></li>
      <li><a href="#create-a-retriever">Create a retriever</a></li>
      <li><a href="#respond-with-an-answer-using-the-chatservice">Respond with an answer using the ChatService</a></li>
    </ul>
  </li>
  <li><a href="#quality-measurement">Quality measurement</a>
    <ul>
      <li><a href="#precision--quality-of-the-retriever">Precision ~ quality of the retriever</a></li>
      <li><a href="#contextual-accuracy">Contextual Accuracy</a></li>
      <li><a href="#answer-completeness">Answer Completeness</a></li>
    </ul>
  </li>
  <li><a href="#conclusion">Conclusion</a></li>
  <li><a href="#output">Output</a></li>
</ul>

<h2 id="setting-up-your-environment">Setting up your environment</h2>
<p>You have some choices to work with this example:</p>

<ol>
  <li>Check out the rag4j project and add your code as a separate class to the project. <a href="https://github.com/RAG4J/rag4j">Rag4j project</a></li>
  <li>Check out the sample application with all the code. You need to build rag4j on your local machine or have a GitHub account and use the public repo exposed by GitHub to build the project with Maven. <a href="https://github.com/RAG4J/rag4j-java-magazine">Java Magazine Example</a></li>
</ol>

<h3 id="using-the-maven-repository-on-github">Using the maven repository on Github</h3>
<p>The project uses maven to manage dependencies and for the build. You need to add Github as a repository. You can use the next settings.xml as an example.</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;settings</span> <span class="na">xmlns=</span><span class="s">"http://maven.apache.org/SETTINGS/1.0.0"</span>
  <span class="na">xmlns:xsi=</span><span class="s">"http://www.w3.org/2001/XMLSchema-instance"</span>
  <span class="na">xsi:schemaLocation=</span><span class="s">"http://maven.apache.org/SETTINGS/1.0.0
                      http://maven.apache.org/xsd/settings-1.0.0.xsd"</span><span class="nt">&gt;</span>

  <span class="nt">&lt;activeProfiles&gt;</span>
    <span class="nt">&lt;activeProfile&gt;</span>github<span class="nt">&lt;/activeProfile&gt;</span>
  <span class="nt">&lt;/activeProfiles&gt;</span>

  <span class="nt">&lt;profiles&gt;</span>
    <span class="nt">&lt;profile&gt;</span>
      <span class="nt">&lt;id&gt;</span>github<span class="nt">&lt;/id&gt;</span>
      <span class="nt">&lt;repositories&gt;</span>
        <span class="nt">&lt;repository&gt;</span>
          <span class="nt">&lt;id&gt;</span>central<span class="nt">&lt;/id&gt;</span>
          <span class="nt">&lt;url&gt;</span>https://repo1.maven.org/maven2<span class="nt">&lt;/url&gt;</span>
        <span class="nt">&lt;/repository&gt;</span>
        <span class="nt">&lt;repository&gt;</span>
          <span class="nt">&lt;id&gt;</span>github<span class="nt">&lt;/id&gt;</span>
          <span class="nt">&lt;url&gt;</span>https://maven.pkg.github.com/rag4j/*<span class="nt">&lt;/url&gt;</span>
          <span class="nt">&lt;snapshots&gt;</span>
            <span class="nt">&lt;enabled&gt;</span>false<span class="nt">&lt;/enabled&gt;</span>
          <span class="nt">&lt;/snapshots&gt;</span>
        <span class="nt">&lt;/repository&gt;</span>
      <span class="nt">&lt;/repositories&gt;</span>
    <span class="nt">&lt;/profile&gt;</span>
  <span class="nt">&lt;/profiles&gt;</span>

  <span class="nt">&lt;servers&gt;</span>
    <span class="nt">&lt;server&gt;</span>
      <span class="nt">&lt;id&gt;</span>github<span class="nt">&lt;/id&gt;</span>
      <span class="nt">&lt;username&gt;</span>YOUR_GITHUB_HANDLE<span class="nt">&lt;/username&gt;</span>
      <span class="nt">&lt;password&gt;</span>YOUR_ACCESS_KEY<span class="nt">&lt;/password&gt;</span>
    <span class="nt">&lt;/server&gt;</span>
  <span class="nt">&lt;/servers&gt;</span>
<span class="nt">&lt;/settings&gt;</span>
</code></pre></div></div>

<h3 id="installing-ollama">Installing Ollama</h3>
<p>Ollama is a tool that runs Large Language Models on your machine. First, navigate to the <a href="https://ollama.com">homepage of Ollama</a>. Download the version for your operating system and install it. Next, open the command prompt and pull the model for the example <em>llama3.2</em>.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ollama pull llama3.2
</code></pre></div></div>

<h2 id="creating-the-java-application">Creating the Java Application</h2>
<p>Time to create the application. Start by creating a java application. I prefer Maven to get the dependencies and build the project. Next step is to create a Java class that can run the application. The following code is a simple example of how to create a Java class that can run the application.</p>

<h3 id="ingest-data">Ingest data</h3>
<p>The first step is to create a content store and ingest data. The following code shows how to ingest data into the content store. You need the file with the data, an embedder and a splitter.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">String</span> <span class="n">fileName</span> <span class="o">=</span> <span class="s">"jfall/sessions-one.jsonl"</span><span class="o">;</span>
<span class="nc">ContentReader</span> <span class="n">contentReader</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">JfallContentReader</span><span class="o">(</span><span class="n">fileName</span><span class="o">);</span>
<span class="nc">Embedder</span> <span class="n">embedder</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">OllamaEmbedder</span><span class="o">(</span><span class="n">ollamaAccess</span><span class="o">);</span>
<span class="nc">Splitter</span> <span class="n">splitter</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">SentenceSplitter</span><span class="o">();</span>

<span class="nc">InternalContentStore</span> <span class="n">contentStore</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">InternalContentStore</span><span class="o">(</span><span class="n">embedder</span><span class="o">);</span>
<span class="nc">IndexingService</span> <span class="n">indexingService</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">IndexingService</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">contentStore</span><span class="o">);</span>
<span class="n">indexingService</span><span class="o">.</span><span class="na">indexDocuments</span><span class="o">(</span><span class="n">contentReader</span><span class="o">,</span> <span class="n">splitter</span><span class="o">);</span>
</code></pre></div></div>

<p>You also need the class to read the content from the file, the <em>JfallContentReader</em> class. The following code shows how to read the content from the file.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">org.rag4j.jm</span><span class="o">;</span>

<span class="kn">import</span> <span class="nn">org.rag4j.indexing.ContentReader</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">org.rag4j.indexing.InputDocument</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">org.rag4j.util.resource.JsonlReader</span><span class="o">;</span>

<span class="kn">import</span> <span class="nn">java.util.HashMap</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.List</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.stream.Stream</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">JfallContentReader</span> <span class="kd">implements</span> <span class="nc">ContentReader</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">String</span> <span class="n">fileName</span><span class="o">;</span>
    
    <span class="kd">public</span> <span class="nf">JfallContentReader</span><span class="o">(</span><span class="nc">String</span> <span class="n">fileName</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">this</span><span class="o">.</span><span class="na">fileName</span> <span class="o">=</span> <span class="n">fileName</span><span class="o">;</span>
    <span class="o">}</span>


    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">Stream</span><span class="o">&lt;</span><span class="nc">InputDocument</span><span class="o">&gt;</span> <span class="nf">read</span><span class="o">()</span> <span class="o">{</span>
        <span class="nc">Stream</span><span class="o">.</span><span class="na">Builder</span><span class="o">&lt;</span><span class="nc">InputDocument</span><span class="o">&gt;</span> <span class="n">builder</span> <span class="o">=</span> <span class="nc">Stream</span><span class="o">.</span><span class="na">builder</span><span class="o">();</span>

        <span class="nc">JsonlReader</span> <span class="n">jsonlReader</span> <span class="o">=</span> <span class="n">getJsonlReader</span><span class="o">();</span>
        <span class="n">jsonlReader</span><span class="o">.</span><span class="na">getLines</span><span class="o">().</span><span class="na">forEach</span><span class="o">(</span><span class="n">talk</span> <span class="o">-&gt;</span> <span class="o">{</span>
            <span class="nc">InputDocument</span><span class="o">.</span><span class="na">InputDocumentBuilder</span> <span class="n">documentBuilder</span> <span class="o">=</span> <span class="nc">InputDocument</span><span class="o">.</span><span class="na">builder</span><span class="o">()</span>
                    <span class="o">.</span><span class="na">documentId</span><span class="o">(</span><span class="n">talk</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="s">"title"</span><span class="o">).</span><span class="na">toLowerCase</span><span class="o">().</span><span class="na">replace</span><span class="o">(</span><span class="s">" "</span><span class="o">,</span> <span class="s">"-"</span><span class="o">))</span>
                    <span class="o">.</span><span class="na">text</span><span class="o">(</span><span class="n">talk</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="s">"description"</span><span class="o">))</span>
                    <span class="o">.</span><span class="na">properties</span><span class="o">(</span><span class="k">new</span> <span class="nc">HashMap</span><span class="o">&lt;&gt;(</span><span class="n">talk</span><span class="o">));</span>
            <span class="n">builder</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">documentBuilder</span><span class="o">.</span><span class="na">build</span><span class="o">());</span>
        <span class="o">});</span>

        <span class="k">return</span> <span class="n">builder</span><span class="o">.</span><span class="na">build</span><span class="o">();</span>
    <span class="o">}</span>

    <span class="kd">private</span> <span class="nc">JsonlReader</span> <span class="nf">getJsonlReader</span><span class="o">()</span> <span class="o">{</span>
        <span class="nc">List</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">properties</span> <span class="o">=</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span>
                <span class="s">"speakers"</span><span class="o">,</span>
                <span class="s">"title"</span><span class="o">,</span>
                <span class="s">"description"</span><span class="o">,</span>
                <span class="s">"room"</span><span class="o">,</span>
                <span class="s">"time"</span><span class="o">,</span>
                <span class="s">"tags"</span>
        <span class="o">);</span>
        <span class="k">return</span> <span class="k">new</span> <span class="nf">JsonlReader</span><span class="o">(</span><span class="n">properties</span><span class="o">,</span> <span class="k">this</span><span class="o">.</span><span class="na">fileName</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>The result of the previous code is a ContentStore with the chunks of text from the talks. The next step is to create a retriever to search for similar content to a question.
If you follow the available repository, you can run step one. Read the comments, change the splitter to see he results change.</p>

<h3 id="create-a-retriever">Create a retriever</h3>
<p>The InternalContentStore is also a retriever. You can use the <em>findRelevantChunks</em> method to search for similar content to the question. The following code shows how to search for similar content.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">List</span><span class="o">&lt;</span><span class="nc">RelevantChunk</span><span class="o">&gt;</span> <span class="n">relevantChunks</span> <span class="o">=</span> <span class="n">contentStore</span><span class="o">.</span><span class="na">findRelevantChunks</span><span class="o">(</span><span class="n">question</span><span class="o">,</span> <span class="n">maxResults</span><span class="o">);</span>
<span class="k">for</span> <span class="o">(</span><span class="nc">RelevantChunk</span> <span class="n">relevantChunk</span> <span class="o">:</span> <span class="n">relevantChunks</span><span class="o">)</span> <span class="o">{</span>
    <span class="no">LOGGER</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Document id: {}"</span><span class="o">,</span> <span class="n">relevantChunk</span><span class="o">.</span><span class="na">getDocumentId</span><span class="o">());</span>
    <span class="no">LOGGER</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Chunk id: {}"</span><span class="o">,</span> <span class="n">relevantChunk</span><span class="o">.</span><span class="na">getChunkId</span><span class="o">());</span>
    <span class="no">LOGGER</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Text: {}"</span><span class="o">,</span> <span class="n">relevantChunk</span><span class="o">.</span><span class="na">getText</span><span class="o">());</span>
    <span class="no">LOGGER</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Score: {}"</span><span class="o">,</span> <span class="n">relevantChunk</span><span class="o">.</span><span class="na">getScore</span><span class="o">());</span>
    <span class="n">logSeparator</span><span class="o">();</span>
<span class="o">}</span>
</code></pre></div></div>
<p>You have now reached step two in the sample repository.</p>

<h3 id="respond-with-an-answer-using-the-chatservice">Respond with an answer using the ChatService</h3>
<p>Getting an answer requires a few classes with different responsibilities:</p>
<ul>
  <li>The ChatService is the class that you use to get an answer to a question. There is a specific ChatService for Ollama, and one for OpenAI. The ChatService is the wrapper around the LLM.</li>
  <li>The AnswerGenerator is the class that generates the answer, making use of the ChatService.</li>
  <li>The RetrievalStrategy is the class that retrieves the relevant chunks from the content store and creates a context from them. Multiple strategies are available, like TopNRetrievalStrategy and WindowRetrievalStrategy.</li>
</ul>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">OllamaAccess</span> <span class="n">ollamaAccess</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">OllamaAccess</span><span class="o">();</span>
<span class="nc">ChatService</span> <span class="n">chatService</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">OllamaChatService</span><span class="o">(</span><span class="n">ollamaAccess</span><span class="o">);</span>
<span class="nc">AnswerGenerator</span> <span class="n">answerGenerator</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">AnswerGenerator</span><span class="o">(</span><span class="n">chatService</span><span class="o">);</span>

<span class="nc">RetrievalStrategy</span> <span class="n">retrievalStrategy</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TopNRetrievalStrategy</span><span class="o">(</span><span class="n">contentStore</span><span class="o">);</span>
<span class="nc">RetrievalOutput</span> <span class="n">retrievalOutput</span> <span class="o">=</span> <span class="k">this</span><span class="o">.</span><span class="na">retrievalStrategy</span><span class="o">.</span><span class="na">retrieve</span><span class="o">(</span><span class="n">question</span><span class="o">,</span> <span class="n">maxResults</span><span class="o">);</span>
<span class="nc">String</span> <span class="n">answer</span> <span class="o">=</span> <span class="n">answerGenerator</span><span class="o">.</span><span class="na">generateAnswer</span><span class="o">(</span><span class="n">question</span><span class="o">,</span> <span class="n">retrievalOutput</span><span class="o">.</span><span class="na">constructContext</span><span class="o">());</span>

<span class="no">LOGGER</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Question: {}"</span><span class="o">,</span> <span class="n">question</span><span class="o">);</span>
<span class="no">LOGGER</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Answer: {}"</span><span class="o">,</span> <span class="n">answer</span><span class="o">);</span>
</code></pre></div></div>
<p>This is step three in the sample repository.</p>

<h2 id="quality-measurement">Quality measurement</h2>
<p>The final step is the measure the quality of your solution. The quality of a RAG solution consists of three parts the diagram below shows the different parts of the quality measurement.</p>

<p><img src="/assets/images/quality-overview.png" alt="Quality Overview" /></p>

<p>The quality component is responsible for determining the quality of the generated text and the retrieved chunks, all related to the question from the user. There are three metrics to determine the overall quality of your RAG:</p>

<ul>
  <li>The precision: the quality of the results of the retriever in relationship to the question.</li>
  <li>Contextual Accuracy: the quality of the answer in relationship to the context.</li>
  <li>Answer Completeness: the quality of the answer in relationship to the question.</li>
</ul>

<h3 id="precision--quality-of-the-retriever">Precision ~ quality of the retriever</h3>
<p>You do not have a judgement list, but an LLM can assist you in generating one. From each chunk, you generate a question using an LLM. Next, the questions go through the retriever; they should return the chunk from which the question was generated. The precision is a score between 0 and 1, where one is perfect.</p>

<p>In the next code block, you see how to create the judgement list, and how to calculate the precision. Note the ObservedRetriever. This is a wrapper around a retriever that collects data to calculate the precision.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">QuestionGenerator</span> <span class="n">questionGenerator</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">QuestionGenerator</span><span class="o">(</span><span class="n">chatService</span><span class="o">);</span>
<span class="nc">QuestionGeneratorService</span> <span class="n">questionGeneratorService</span> <span class="o">=</span>
        <span class="k">new</span> <span class="nf">QuestionGeneratorService</span><span class="o">(</span><span class="n">contentStore</span><span class="o">,</span> <span class="n">questionGenerator</span><span class="o">);</span>
<span class="nc">Path</span> <span class="n">savedFilePath</span> <span class="o">=</span> <span class="n">questionGeneratorService</span><span class="o">.</span><span class="na">generateQuestionAnswerPairsAndSaveToTempFile</span><span class="o">(</span><span class="n">fileName</span><span class="o">);</span>
<span class="no">LOGGER</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Saved file: {}"</span><span class="o">,</span> <span class="n">savedFilePath</span><span class="o">);</span>

<span class="nc">ObservedRetriever</span> <span class="n">observedRetriever</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ObservedRetriever</span><span class="o">(</span><span class="n">contentStore</span><span class="o">);</span>
<span class="nc">RetrievalQualityService</span> <span class="n">retrievalQualityService</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">RetrievalQualityService</span><span class="o">(</span><span class="n">observedRetriever</span><span class="o">);</span>
<span class="nc">List</span><span class="o">&lt;</span><span class="nc">QuestionAnswerRecord</span><span class="o">&gt;</span> <span class="n">questionAnswerRecords</span> <span class="o">=</span>
        <span class="n">retrievalQualityService</span><span class="o">.</span><span class="na">readQuestionAnswersFromFilePath</span><span class="o">(</span><span class="n">savedFilePath</span><span class="o">,</span> <span class="kc">false</span><span class="o">);</span>
<span class="nc">RetrievalQuality</span> <span class="n">retrievalQuality</span> <span class="o">=</span>
        <span class="n">retrievalQualityService</span><span class="o">.</span><span class="na">obtainRetrievalQuality</span><span class="o">(</span><span class="n">questionAnswerRecords</span><span class="o">,</span> <span class="n">embedder</span><span class="o">);</span>

<span class="no">LOGGER</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Correct: {}"</span><span class="o">,</span> <span class="n">retrievalQuality</span><span class="o">.</span><span class="na">getCorrect</span><span class="o">());</span>
<span class="no">LOGGER</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Incorrect: {}"</span><span class="o">,</span> <span class="n">retrievalQuality</span><span class="o">.</span><span class="na">getIncorrect</span><span class="o">());</span>
<span class="no">LOGGER</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Quality using precision: {}"</span><span class="o">,</span> <span class="n">retrievalQuality</span><span class="o">.</span><span class="na">getPrecision</span><span class="o">());</span>
<span class="no">LOGGER</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Total questions: {}"</span><span class="o">,</span> <span class="n">retrievalQuality</span><span class="o">.</span><span class="na">totalItems</span><span class="o">());</span>
</code></pre></div></div>

<h3 id="contextual-accuracy">Contextual Accuracy</h3>
<p>The context is constructed from the chunks retrieved by the retriever. The generator generates the answer. The answer should be deduced from the context. The contextual accuracy is between 1 and 5, where five is perfect. This score is obtained through the LLM by asking the LLM about the quality of the answer concerning the context.</p>

<p>Similar to the ObservedRetriever, the framework comes with an ObservedAnswerGenerator. This class is a wrapper around the answer generator that collects data to calculate the contextual accuracy. The RAGObserverPersistor is an interface that you can implement to store the data. The next code block shows how to calculate the contextual accuracy. It uses the LoggingRAGObserverPersistor to log the observed data.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">ObservedAnswerGenerator</span> <span class="n">answerGenerator</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ObservedAnswerGenerator</span><span class="o">(</span><span class="n">chatService</span><span class="o">);</span>
<span class="n">retrieveAnswer</span><span class="o">(</span><span class="n">answerGenerator</span><span class="o">,</span> <span class="n">question</span><span class="o">,</span> <span class="n">maxResults</span><span class="o">);</span>
<span class="nc">RAGObserver</span> <span class="n">observer</span> <span class="o">=</span> <span class="nc">RAGTracker</span><span class="o">.</span><span class="na">getRAGObserver</span><span class="o">();</span>
<span class="nc">RAGTracker</span><span class="o">.</span><span class="na">cleanup</span><span class="o">();</span>

<span class="nc">RAGObserverPersistor</span> <span class="n">persistor</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">LoggingRAGObserverPersistor</span><span class="o">();</span>
<span class="n">persistor</span><span class="o">.</span><span class="na">persist</span><span class="o">(</span><span class="n">observer</span><span class="o">);</span>

<span class="nc">AnswerQualityService</span> <span class="n">answerQuality</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">AnswerQualityService</span><span class="o">(</span><span class="n">chatService</span><span class="o">);</span>
<span class="nc">AnswerQuality</span> <span class="n">quality</span> <span class="o">=</span> <span class="n">answerQuality</span><span class="o">.</span><span class="na">determineQualityOfAnswer</span><span class="o">(</span><span class="n">observer</span><span class="o">);</span>
<span class="no">LOGGER</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Quality of answer coming from the context: {}, Reason {}}"</span><span class="o">,</span>
        <span class="n">quality</span><span class="o">.</span><span class="na">getAnswerFromContextQuality</span><span class="o">().</span><span class="na">getQuality</span><span class="o">(),</span> <span class="n">quality</span><span class="o">.</span><span class="na">getAnswerFromContextQuality</span><span class="o">().</span><span class="na">getReason</span><span class="o">());</span>
</code></pre></div></div>

<h3 id="answer-completeness">Answer Completeness</h3>
<p>The generator generates the answer. The answer should answer all aspects of the question. The answer accuracy is a score between 1 and 5, where five is perfect. The score is obtained through the LLM by asking the LLM about the quality of the answer concerning the question.</p>

<p>The next code block shows how to calculate the answer completeness. It can be added to the previous code block to calculate the overall quality of the answer.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="no">LOGGER</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Quality of answer compared to the question: {}, Reason: {}}"</span><span class="o">,</span>
        <span class="n">quality</span><span class="o">.</span><span class="na">getAnswerToQuestionQuality</span><span class="o">().</span><span class="na">getQuality</span><span class="o">(),</span> <span class="n">quality</span><span class="o">.</span><span class="na">getAnswerToQuestionQuality</span><span class="o">().</span><span class="na">getReason</span><span class="o">());</span>
</code></pre></div></div>

<p>Change the strategy to a DocumentRetrievalStrategy to retrieve the whole document instead of a chunk. Watch the difference in results</p>

<h2 id="conclusion">Conclusion</h2>
<p>This example shows how to create a simple RAG application. The quality of the RAG solution is determined by the precision, the contextual accuracy, and the answer completeness. The precision is the quality of the retriever in relationship to the question. The contextual accuracy is the quality of the answer in relationship to the context. The answer completeness is the quality of the answer in relationship to the question. The quality of the RAG solution is determined by these three metrics.</p>

<p>Want to try this yourself? Checkout the <a href="https://github.com/RAG4J/rag4j-java-magazine">GitHUb project: Java Magazine Example</a></p>

<h2 id="output">Output</h2>
<p>If you do not want to try this yourself, you can check the output of the code in the next code block</p>

<pre><code class="language-log">/opt/homebrew/Cellar/openjdk@21/21.0.5/libexec/openjdk.jdk/Contents/Home/bin/java -javaagent:/Users/jettrocoenradie/Applications/IntelliJ IDEA Ultimate.app/Contents/lib/idea_rt.jar=54716:/Users/jettrocoenradie/Applications/IntelliJ IDEA Ultimate.app/Contents/bin -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath /Users/jettrocoenradie/Development/personal/rag4j-java-magazine/target/classes:/Users/jettrocoenradie/.m2/repository/org/rag4j/rag4j/1.5.0/rag4j-1.5.0.jar:/Users/jettrocoenradie/.m2/repository/org/apache/opennlp/opennlp-tools/2.5.0/opennlp-tools-2.5.0.jar:/Users/jettrocoenradie/.m2/repository/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar:/Users/jettrocoenradie/.m2/repository/org/slf4j/slf4j-api/2.0.7/slf4j-api-2.0.7.jar:/Users/jettrocoenradie/.m2/repository/org/slf4j/slf4j-simple/2.0.7/slf4j-simple-2.0.7.jar:/Users/jettrocoenradie/.m2/repository/org/json/json/20240303/json-20240303.jar:/Users/jettrocoenradie/.m2/repository/org/apache/commons/commons-csv/1.12.0/commons-csv-1.12.0.jar:/Users/jettrocoenradie/.m2/repository/commons-io/commons-io/2.17.0/commons-io-2.17.0.jar:/Users/jettrocoenradie/.m2/repository/commons-codec/commons-codec/1.17.1/commons-codec-1.17.1.jar:/Users/jettrocoenradie/.m2/repository/ai/djl/api/0.30.0/api-0.30.0.jar:/Users/jettrocoenradie/.m2/repository/com/google/code/gson/gson/2.11.0/gson-2.11.0.jar:/Users/jettrocoenradie/.m2/repository/com/google/errorprone/error_prone_annotations/2.27.0/error_prone_annotations-2.27.0.jar:/Users/jettrocoenradie/.m2/repository/net/java/dev/jna/jna/5.14.0/jna-5.14.0.jar:/Users/jettrocoenradie/.m2/repository/org/apache/commons/commons-compress/1.27.1/commons-compress-1.27.1.jar:/Users/jettrocoenradie/.m2/repository/com/knuddels/jtokkit/1.1.0/jtokkit-1.1.0.jar org.rag4j.jm.AppRAG
[main] INFO org.rag4j.jm.AppRAG - Document id: build-the-best-knowledge-retriever-for-your-large-language-model.
[main] INFO org.rag4j.jm.AppRAG - Chunk id: 4
[main] INFO org.rag4j.jm.AppRAG - Text: An essential part of RAG is the retrieval part.
[main] INFO org.rag4j.jm.AppRAG - Score: 15.23797700427602
[main] INFO org.rag4j.jm.AppRAG - ---------------------------------------
[main] INFO org.rag4j.jm.AppRAG - Document id: build-the-best-knowledge-retriever-for-your-large-language-model.
[main] INFO org.rag4j.jm.AppRAG - Chunk id: 3
[main] INFO org.rag4j.jm.AppRAG - Text: To overcome the knowledge problem, the Retrieval Augmented Generation (RAG) pattern arose.
[main] INFO org.rag4j.jm.AppRAG - Score: 19.02969381348981
[main] INFO org.rag4j.jm.AppRAG - ---------------------------------------
[main] INFO org.rag4j.jm.AppRAG - Document id: build-the-best-knowledge-retriever-for-your-large-language-model.
[main] INFO org.rag4j.jm.AppRAG - Chunk id: 4
[main] INFO org.rag4j.jm.AppRAG - Text: An essential part of RAG is the retrieval part.
[main] INFO org.rag4j.jm.AppRAG - Score: 16.872212193426076
[main] INFO org.rag4j.jm.AppRAG - ---------------------------------------
[main] INFO org.rag4j.jm.AppRAG - Document id: build-the-best-knowledge-retriever-for-your-large-language-model.
[main] INFO org.rag4j.jm.AppRAG - Chunk id: 3
[main] INFO org.rag4j.jm.AppRAG - Text: To overcome the knowledge problem, the Retrieval Augmented Generation (RAG) pattern arose.
[main] INFO org.rag4j.jm.AppRAG - Score: 18.941479184476453
[main] INFO org.rag4j.jm.AppRAG - ---------------------------------------
[main] INFO org.rag4j.jm.AppRAG - Question: What is RAG?
[main] INFO org.rag4j.jm.AppRAG - Answer: Retrieval Augmented Generation (RAG) is a pattern that aims to overcome the knowledge problem in text generation models by using retrieval mechanisms to retrieve relevant information from a database or knowledge base before generating new text.
[main] INFO org.rag4j.jm.AppRAG - ---------------------------------------
[main] INFO org.rag4j.jm.AppRAG - Question: Who talked about RAG?
[main] INFO org.rag4j.jm.AppRAG - Answer: I couldn't find any information about who specifically talked about RAG in the provided context. The context only mentions that RAG was developed as a solution to overcome the knowledge problem, but it doesn't mention who specifically discussed or proposed this concept.
[main] INFO org.rag4j.jm.AppRAG - ---------------------------------------
[main] INFO org.rag4j.rag.generation.QuestionGeneratorService - Generated question: Is it a common requirement for participants in a hands-on learning experience?
[main] INFO org.rag4j.rag.generation.QuestionGeneratorService - Generated question: Is it possible for a user to utilize a computer system located outside of their usual environment?
[main] INFO org.rag4j.rag.generation.QuestionGeneratorService - Generated question: What programming languages are commonly used in a retrieval algorithm optimization workshop?
[main] INFO org.rag4j.rag.generation.QuestionGeneratorService - Generated question: How do these strategies help create a more comprehensive understanding of the model's capabilities?
[main] INFO org.rag4j.rag.generation.QuestionGeneratorService - Generated question: Is the primary goal of chunking mechanisms to improve understanding and representation of complex data structures?
[main] INFO org.rag4j.rag.generation.QuestionGeneratorService - Generated question: Will a conference dedicated to a specific type of research be held?
[main] INFO org.rag4j.rag.generation.QuestionGeneratorService - Generated question: Will a technology that can create new content be limited by its reliance on existing data?
[main] INFO org.rag4j.rag.generation.QuestionGeneratorService - Generated question: Is it possible for a participant to benefit from prior preparation before attending an event?
[main] INFO org.rag4j.rag.generation.QuestionGeneratorService - Generated question: Can one set up an open-source large language model directly from their own computer?
[main] INFO org.rag4j.rag.generation.QuestionGeneratorService - Generated question: Does a Large Language model's understanding of its own limitations ever change?
[main] INFO org.rag4j.rag.generation.QuestionGeneratorService - Generated question: Are these tools considered ordinary goods due to their widespread availability?
[main] INFO org.rag4j.rag.generation.QuestionGeneratorService - Generated question: Is the retrieval process a crucial component of this organization's activities?
[main] INFO org.rag4j.rag.generation.QuestionGeneratorService - Generated question: Can a specific method of training artificial intelligence models be employed to resolve the issue of incomplete information in AI systems?
[main] INFO org.rag4j.rag.generation.QuestionGeneratorService - Generated question: Is there an optimal method for evaluating the effectiveness of information search strategies?
[main] INFO org.rag4j.rag.generation.QuestionGeneratorService - Generated question: Is the concept of retrieving information from existing sources a common practice among researchers?
[main] INFO org.rag4j.rag.generation.QuestionGeneratorService - Generated question: Will a newly integrated retriever improve the performance of an existing Large Language Model?
[main] INFO org.rag4j.rag.generation.QuestionGeneratorService - Generated question: Is this technology based solely on the analysis of user behavior?
[main] INFO org.rag4j.jm.AppRAG - Saved file: /var/folders/50/ds20b4252qjb6_nk6v84t5mh0000gn/T/questionAnswerPairs2650460898584228046/jfall_questions_answers_sample.csv
[main] INFO org.rag4j.jm.AppRAG - Correct: [build-the-best-knowledge-retriever-for-your-large-language-model._9, build-the-best-knowledge-retriever-for-your-large-language-model._12, build-the-best-knowledge-retriever-for-your-large-language-model._10, build-the-best-knowledge-retriever-for-your-large-language-model._16, build-the-best-knowledge-retriever-for-your-large-language-model._15, build-the-best-knowledge-retriever-for-your-large-language-model._14, build-the-best-knowledge-retriever-for-your-large-language-model._2, build-the-best-knowledge-retriever-for-your-large-language-model._1, build-the-best-knowledge-retriever-for-your-large-language-model._4, build-the-best-knowledge-retriever-for-your-large-language-model._8]
[main] INFO org.rag4j.jm.AppRAG - Incorrect: [build-the-best-knowledge-retriever-for-your-large-language-model._13, build-the-best-knowledge-retriever-for-your-large-language-model._11, build-the-best-knowledge-retriever-for-your-large-language-model._0, build-the-best-knowledge-retriever-for-your-large-language-model._3, build-the-best-knowledge-retriever-for-your-large-language-model._6, build-the-best-knowledge-retriever-for-your-large-language-model._5, build-the-best-knowledge-retriever-for-your-large-language-model._7]
[main] INFO org.rag4j.jm.AppRAG - Quality using precision: 0.5882352941176471
[main] INFO org.rag4j.jm.AppRAG - Total questions: 17
[main] INFO org.rag4j.jm.AppRAG - ---------------------------------------
[main] INFO org.rag4j.jm.AppRAG - Question: What is RAG?
[main] INFO org.rag4j.jm.AppRAG - Answer: Retrieval Augmented Generation (RAG) is a pattern that was developed to address the knowledge problem in natural language generation. The purpose of RAG is to retrieve relevant information from an external knowledge source before generating text. This allows models to draw upon existing knowledge and avoid relying solely on their own internal state, thereby improving the accuracy and coherence of generated text.
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor - Question: What is RAG?
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor - Context: An essential part of RAG is the retrieval part. To overcome the knowledge problem, the Retrieval Augmented Generation (RAG) pattern arose. 
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor - Answer: Retrieval Augmented Generation (RAG) is a pattern that was developed to address the knowledge problem in natural language generation. The purpose of RAG is to retrieve relevant information from an external knowledge source before generating text. This allows models to draw upon existing knowledge and avoid relying solely on their own internal state, thereby improving the accuracy and coherence of generated text.
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor - Relevant chunks:
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor -   build-the-best-knowledge-retriever-for-your-large-language-model._9: It is easy to learn, so you can focus on understanding and building the details of the components during the workshop.
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor -   build-the-best-knowledge-retriever-for-your-large-language-model._12: To find the optimum combination, you'll use quality metrics for the retriever as well as the other components of the RAG system.You can do the workshop using Python or Java.
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor -   build-the-best-knowledge-retriever-for-your-large-language-model._10: You experiment with different chunking mechanisms (sentence, max tokens, semantic).
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor -   build-the-best-knowledge-retriever-for-your-large-language-model._16: Check out the web page and gear up for a great session!https://rag4j.org/conference/2024/09/27/workshop-jfall-2024.html
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor -   build-the-best-knowledge-retriever-for-your-large-language-model._15: Dive into pre-workshop materials and come ready to make the most of this experience.
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor -   build-the-best-knowledge-retriever-for-your-large-language-model._14: You can also run an open-source LLM on Ollama on your local machine.We’ve created a dedicated web page to help you prepare, with all the resources you need at your fingertips.
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor -   build-the-best-knowledge-retriever-for-your-large-language-model._2: Large Language models (LLMs) only have the knowledge they acquired through learning, and even that knowledge does not include all the details.
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor -   build-the-best-knowledge-retriever-for-your-large-language-model._1: Tools to generate text, images, or data are now common goods.
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor -   build-the-best-knowledge-retriever-for-your-large-language-model._4: An essential part of RAG is the retrieval part.
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor -   build-the-best-knowledge-retriever-for-your-large-language-model._3: To overcome the knowledge problem, the Retrieval Augmented Generation (RAG) pattern arose.
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor -   build-the-best-knowledge-retriever-for-your-large-language-model._8: Vector search got a jump start with the rise of LLMs and RAG.This workshop aims to build a high-quality retriever, integrate the retriever into your LLM solution and measure the overall quality of your RAG system.The workshop uses our Rag4j/Rag4p framework, which we created especially for workshops.
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor - Window to chunkIds:
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor - Window texts:
[main] INFO org.rag4j.jm.AppRAG - Quality of answer compared to the question: 4, Reason: The answer is partially correct as it mentions Retrieval Augmented Generation (RAG) but lacks specific details about its implementation or how it addresses the knowledge problem.}
[main] INFO org.rag4j.jm.AppRAG - Quality of answer coming from the context: 4, Reason The answer partially captures the essence of RAG but lacks specificity about the external knowledge source and its role in improving generated text accuracy and coherence. It does not mention the internal state or avoid reliance on it, which are crucial aspects of the RAG mechanism.}
[main] INFO org.rag4j.jm.AppRAG - ---------------------------------------
[main] INFO org.rag4j.jm.AppRAG - Question: Who talked about RAG?
[main] INFO org.rag4j.jm.AppRAG - Answer: Unfortunately, I couldn't find any information on who specifically talked about RAG in the provided context. The context mentions that RAG is a part of RAG but does not mention anyone discussing or mentioning it. Therefore, I cannot provide an answer to your question.
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor - Question: Who talked about RAG?
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor - Context: An essential part of RAG is the retrieval part. To overcome the knowledge problem, the Retrieval Augmented Generation (RAG) pattern arose. 
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor - Answer: Unfortunately, I couldn't find any information on who specifically talked about RAG in the provided context. The context mentions that RAG is a part of RAG but does not mention anyone discussing or mentioning it. Therefore, I cannot provide an answer to your question.
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor - Relevant chunks:
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor -   build-the-best-knowledge-retriever-for-your-large-language-model._4: An essential part of RAG is the retrieval part.
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor -   build-the-best-knowledge-retriever-for-your-large-language-model._3: To overcome the knowledge problem, the Retrieval Augmented Generation (RAG) pattern arose.
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor - Window to chunkIds:
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor - Window texts:
[main] INFO org.rag4j.jm.AppRAG - Quality of answer compared to the question: 4, Reason: The answer provides some information related to RAG, such as being "a part of RAG", which suggests some level of understanding about the term. However, it fails to provide a specific person or entity that talked about RAG, leaving the answer incomplete.}
[main] INFO org.rag4j.jm.AppRAG - Quality of answer coming from the context: 2, Reason The answer is partially correct but does not contain exact information from the context. It mentions "who specifically talked about RAG", which is not present in the provided context.}
[main] INFO org.rag4j.jm.AppRAG - ---------------------------------------

Process finished with exit code 0
</code></pre>

<p>And part of the output after changing the retrieval strategy to a DocumentRetrievalStrategy</p>

<pre><code class="language-log">[main] INFO org.rag4j.jm.AppRAG - Question: Who talked about RAG?
[main] INFO org.rag4j.jm.AppRAG - Answer: Jettro Coenradie and Daniël Spee.
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor - Question: Who talked about RAG?
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor - Context: Generative AI is here to stay. Tools to generate text, images, or data are now common goods. Large Language models (LLMs) only have the knowledge they acquired through learning, and even that knowledge does not include all the details. To overcome the knowledge problem, the Retrieval Augmented Generation (RAG) pattern arose. An essential part of RAG is the retrieval part. Retrieval is not new. The search or retrieval domain is rich with tools, metrics and research. The new kid on the block is semantic search using vectors. Vector search got a jump start with the rise of LLMs and RAG.This workshop aims to build a high-quality retriever, integrate the retriever into your LLM solution and measure the overall quality of your RAG system.The workshop uses our Rag4j/Rag4p framework, which we created especially for workshops. It is easy to learn, so you can focus on understanding and building the details of the components during the workshop. You experiment with different chunking mechanisms (sentence, max tokens, semantic). After that, you use various strategies to construct the context for the LLM (TopN, Window, Document, Hierarchical). To find the optimum combination, you'll use quality metrics for the retriever as well as the other components of the RAG system.You can do the workshop using Python or Java. We provide access to a remote LLM. You can also run an open-source LLM on Ollama on your local machine.We’ve created a dedicated web page to help you prepare, with all the resources you need at your fingertips. Dive into pre-workshop materials and come ready to make the most of this experience. Check out the web page and gear up for a great session!https://rag4j.org/conference/2024/09/27/workshop-jfall-2024.html
description: Generative AI is here to stay. Tools to generate text, images, or data are now common goods. Large Language models (LLMs) only have the knowledge they acquired through learning, and even that knowledge does not include all the details. To overcome the knowledge problem, the Retrieval Augmented Generation (RAG) pattern arose. An essential part of RAG is the retrieval part. Retrieval is not new. The search or retrieval domain is rich with tools, metrics and research. The new kid on the block is semantic search using vectors. Vector search got a jump start with the rise of LLMs and RAG.This workshop aims to build a high-quality retriever, integrate the retriever into your LLM solution and measure the overall quality of your RAG system.The workshop uses our Rag4j/Rag4p framework, which we created especially for workshops. It is easy to learn, so you can focus on understanding and building the details of the components during the workshop. You experiment with different chunking mechanisms (sentence, max tokens, semantic). After that, you use various strategies to construct the context for the LLM (TopN, Window, Document, Hierarchical). To find the optimum combination, you'll use quality metrics for the retriever as well as the other components of the RAG system.You can do the workshop using Python or Java. We provide access to a remote LLM. You can also run an open-source LLM on Ollama on your local machine.We’ve created a dedicated web page to help you prepare, with all the resources you need at your fingertips. Dive into pre-workshop materials and come ready to make the most of this experience. Check out the web page and gear up for a great session!https://rag4j.org/conference/2024/09/27/workshop-jfall-2024.html 
time: Thu 10:35 am - 12:30 pm 
title: Build the best knowledge retriever for your Large Language Model. 
room: Hands-on labs 
speakers: Jettro Coenradie, Daniël Spee 
tags: Hands-on Lab, Big Data &amp; Machine Learning, Intermediate 
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor - Answer: Jettro Coenradie and Daniël Spee.
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor - Relevant chunks:
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor -   build-the-best-knowledge-retriever-for-your-large-language-model._4: An essential part of RAG is the retrieval part.
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor -   build-the-best-knowledge-retriever-for-your-large-language-model._3: To overcome the knowledge problem, the Retrieval Augmented Generation (RAG) pattern arose.
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor - Window to chunkIds:
[main] INFO org.rag4j.rag.tracker.LoggingRAGObserverPersistor - Window texts:
[main] INFO org.rag4j.jm.AppRAG - Quality of answer compared to the question: 4, Reason: The answer matches the proposed question, mentioning both individuals who worked on RAG, but it doesn't provide a clear connection or context between them. More information would strengthen the answer.}
[main] INFO org.rag4j.jm.AppRAG - Quality of answer coming from the context: 4, Reason The answer partially matches the context as it contains the names of two speakers, but lacks details such as their roles or specific contributions to the workshop. The context does not explicitly mention the names Jettro Coenradie and Daniël Spee in relation to the Retrieval Augmented Generation (RAG) pattern.}
[main] INFO org.rag4j.jm.AppRAG - ---------------------------------------
</code></pre>]]></content><author><name></name></author><category term="examples" /><summary type="html"><![CDATA[Hi, this is the example accompanying the article I wrote for Java Magazine. Following this tutorial, you build your custom RAG application using the Rag4j application. First, you set up your environment; you create the application to index all the talks from the JFall 2024 conference. Next, you create a retriever to search for similar content to a question. Finally, you make the answer generator and measure the quality of your solution.]]></summary></entry><entry><title type="html">Internal content store backup now available in RAG4j</title><link href="https://rag4j.org/examples/2024/12/03/contentstore-backup.html" rel="alternate" type="text/html" title="Internal content store backup now available in RAG4j" /><published>2024-12-03T04:00:00+00:00</published><updated>2024-12-03T04:00:00+00:00</updated><id>https://rag4j.org/examples/2024/12/03/contentstore-backup</id><content type="html" xml:base="https://rag4j.org/examples/2024/12/03/contentstore-backup.html"><![CDATA[<p>In the Python version of this project, creating a backup of the <em>InternalContentStore</em> was already possible. With the latest release of RAG4j, you can now also create a backup of the <em>InternalContentStore</em> in Java. You can choose the location of the backup. The backup contains two parts, the data and the metadata. Both use a serialized format. Below are two examples for creating the backup and restoring the backup.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">AppRAG</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="c1">// Setup the content store</span>
        <span class="nc">OllamaAccess</span> <span class="n">ollamaAccess</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">OllamaAccess</span><span class="o">();</span>
        <span class="nc">Embedder</span> <span class="n">embedder</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">OllamaEmbedder</span><span class="o">(</span><span class="n">ollamaAccess</span><span class="o">);</span>
        <span class="nc">InternalContentStore</span> <span class="n">contentStore</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">InternalContentStore</span><span class="o">(</span><span class="n">embedder</span><span class="o">);</span>

        <span class="nc">ContentReader</span> <span class="n">contentReader</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">JfallContentReader</span><span class="o">(</span><span class="s">"jfall/sessions.jsonl"</span><span class="o">);</span>
        <span class="nc">IndexingService</span> <span class="n">indexingService</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">IndexingService</span><span class="o">(</span><span class="n">contentStore</span><span class="o">);</span>
        <span class="nc">Splitter</span> <span class="n">splitter</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">SentenceSplitter</span><span class="o">();</span>
        <span class="n">indexingService</span><span class="o">.</span><span class="na">indexDocuments</span><span class="o">(</span><span class="n">contentReader</span><span class="o">,</span> <span class="n">splitter</span><span class="o">);</span>

        <span class="nc">Path</span> <span class="n">backUpPath</span> <span class="o">=</span> <span class="nc">Path</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="nc">System</span><span class="o">.</span><span class="na">getProperty</span><span class="o">(</span><span class="s">"user.dir"</span><span class="o">),</span> <span class="s">"/backups"</span><span class="o">);</span>
        <span class="n">contentStore</span><span class="o">.</span><span class="na">backupToDisk</span><span class="o">(</span><span class="n">backUpPath</span><span class="o">,</span> <span class="s">"jfall-ollama-sentence"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>In the next run, you want to restore the backup. You can do this with the following code:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">AppRAG</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="c1">// Setup the content store</span>
        <span class="nc">OllamaAccess</span> <span class="n">ollamaAccess</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">OllamaAccess</span><span class="o">();</span>
        <span class="nc">Embedder</span> <span class="n">embedder</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">OllamaEmbedder</span><span class="o">(</span><span class="n">ollamaAccess</span><span class="o">);</span>
        <span class="nc">InternalContentStore</span> <span class="n">contentStore</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">InternalContentStore</span><span class="o">(</span><span class="n">embedder</span><span class="o">);</span>
        
        <span class="nc">Path</span> <span class="n">backUpPath</span> <span class="o">=</span> <span class="nc">Path</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="nc">System</span><span class="o">.</span><span class="na">getProperty</span><span class="o">(</span><span class="s">"user.dir"</span><span class="o">),</span> <span class="s">"/backups"</span><span class="o">);</span>
        <span class="n">contentStore</span><span class="o">.</span><span class="na">loadFromDisk</span><span class="o">(</span><span class="n">backUpPath</span><span class="o">,</span> <span class="s">"jfall-ollama-sentence"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Not having to create the chunks and embeddings is the biggest advantage of using the backup.</p>]]></content><author><name></name></author><category term="examples" /><summary type="html"><![CDATA[In the Python version of this project, creating a backup of the InternalContentStore was already possible. With the latest release of RAG4j, you can now also create a backup of the InternalContentStore in Java. You can choose the location of the backup. The backup contains two parts, the data and the metadata. Both use a serialized format. Below are two examples for creating the backup and restoring the backup.]]></summary></entry><entry><title type="html">Workshop JFall 2024</title><link href="https://rag4j.org/conference/2024/09/27/workshop-jfall-2024.html" rel="alternate" type="text/html" title="Workshop JFall 2024" /><published>2024-09-27T04:00:00+00:00</published><updated>2024-09-27T04:00:00+00:00</updated><id>https://rag4j.org/conference/2024/09/27/workshop-jfall-2024</id><content type="html" xml:base="https://rag4j.org/conference/2024/09/27/workshop-jfall-2024.html"><![CDATA[<p>The <em>7th of November 2024</em>, Daniel and Jettro will visit Pathe in Ede for the annual JFall conference. In the morning, we will deliver
our workshop <a href="https://jfall.nl/timetable/">Build the best knowledge retriever for your Large Language Model.</a>.
Generative AI is here to stay. Tools to generate text, images, or data are now common goods. Large Language models (LLMs) only have the knowledge they acquired through learning, and even that knowledge does not include all the details. To overcome the knowledge problem, the Retrieval Augmented Generation (RAG) pattern arose. An essential part of RAG is the retrieval part. Retrieval is not new. The search or retrieval domain is rich with tools, metrics and research. The new kid on the block is semantic search using vectors. Vector search got a jump start with the rise of LLMs and RAG.
This workshop aims to build a high-quality retriever, integrate the retriever into your LLM solution and measure the overall quality of your RAG system.</p>

<p>The workshop uses our Rag4j/Rag4p framework, which we created especially for workshops. It is easy to learn, so you can focus on understanding and building the details of the components during the workshop. You experiment with different chunking mechanisms (sentence, max tokens, semantic). After that, you use various strategies to construct the context for the LLM (TopN, Window, Document, Hierarchical). To find the optimum combination, you’ll use quality metrics for the retriever as well as the other components of the RAG system.
You can do the workshop using Python or Java (21). We provide access to a remote LLM (OpenAI). You can also run an open-source LLM on Ollama on your local machine.</p>

<p>We hope to see you in Pathe Ede and that you will enjoy the workshop. If you have any questions, feel free to contact us.</p>

<p><em>7th of November 2024 10:35 - 12:30 Space for Hands-on labs</em></p>

<hr />

<h2 id="preparing-for-the-workshop">Preparing for the workshop</h2>
<blockquote>
  <p>First, choose your programming language (Java or Python). Then follow the instructions below:</p>

  <p>Java: <a href="https://github.com/RAG4J/rag4j-jfall">RAG4j</a></p>

  <p>Python: <a href="https://github.com/RAG4J/rag4p-jfall">RAG4p</a></p>

  <p>The repositories contain a README.md file with instructions on setting up your environment.</p>
</blockquote>

<hr />

<p><a href="/assets/preso/presentation-jfall-2024.pdf">The presentation used during the workshop is available here</a>.</p>

<hr />

<p> </p>

<p><img src="/assets/images/jfall-2024.png" alt="Workshop Image" /></p>]]></content><author><name></name></author><category term="conference" /><summary type="html"><![CDATA[The 7th of November 2024, Daniel and Jettro will visit Pathe in Ede for the annual JFall conference. In the morning, we will deliver our workshop Build the best knowledge retriever for your Large Language Model.. Generative AI is here to stay. Tools to generate text, images, or data are now common goods. Large Language models (LLMs) only have the knowledge they acquired through learning, and even that knowledge does not include all the details. To overcome the knowledge problem, the Retrieval Augmented Generation (RAG) pattern arose. An essential part of RAG is the retrieval part. Retrieval is not new. The search or retrieval domain is rich with tools, metrics and research. The new kid on the block is semantic search using vectors. Vector search got a jump start with the rise of LLMs and RAG. This workshop aims to build a high-quality retriever, integrate the retriever into your LLM solution and measure the overall quality of your RAG system.]]></summary></entry><entry><title type="html">Introducing Rag4p GUI</title><link href="https://rag4j.org/news/2024/07/04/introducing-rag4p-gui.html" rel="alternate" type="text/html" title="Introducing Rag4p GUI" /><published>2024-07-04T04:00:00+00:00</published><updated>2024-07-04T04:00:00+00:00</updated><id>https://rag4j.org/news/2024/07/04/introducing-rag4p-gui</id><content type="html" xml:base="https://rag4j.org/news/2024/07/04/introducing-rag4p-gui.html"><![CDATA[<p>Yesterday was the first public appearance of my latest project, Rag4p-GUI. This project is a graphical interface for the Rag4p library. The goal for that project is to create a basic library or framework that we can use during workshops. You can understand the complete framework in an hour, essential for our workshops. The problem with the project is that it needed a GUI. So, I always used the command line during presentations, distracting me from the information I wanted to share. Therefore, I started working on a GUI. It could get a bit out of hand. In this post, I want to share the first version of the GUI. I’ll discuss the features that it has right now.</p>

<p>The GUI consists of three parts. The first part is indexing the content into a store. Rag4p provides access to Weaviate, OpenSearch and a custom in-memory database. The second part deals with retrieving the context for the Large Language Model. Again, you can use Weaviate, OpenSearch, or a custom in-memory database. The third part is the generation of the answer. Currently, the Rag4p project provides access to OpenAI, Amazon Bedrock and Ollama for LLMs.</p>

<h2 id="indexing">Indexing</h2>
<p>The project’s adaptability shines through in its ability to handle different datasets. With three different datasets, often in a small and larger variant, and a reader class for each dataset due to their non-uniform layout, the project ensures flexibility. Another essential component is the splitter, with the project offering three options: the sentence splitter, the max token splitter, and the single chunk splitter. You can test drive the different splitters using the Chunking tab, found after choosing the Indexing tab.</p>

<p><img src="/assets/images/rag4pgui/rag4pgui-chunking.png" alt="Rag4p GUI ~ Chunking" /></p>

<p>With the proper chunks, it is time to talk about embeddings. When working with semantic search and vectors to capture the semantics of your chunk, you have to choose the right embedder. The Rag4p project offers four embedding providers: OpenAI, Bedrock, Ollama and Onnx. Some providers offer different models. You can select the model you want to use. The Embedding tab allows you to test the different embedders. By selecting one of the backups of the internal data stores, you can visualise the embeddings and enter your query to locate the query embedding next to the embeddings in your store. The following image shows a sample of the screen.</p>

<p><img src="/assets/images/rag4pgui/rag4pgui-embeddings.png" alt="Rag4p GUI ~ Embeddings" /></p>

<p>Creating embeddings using services like OpenAI and Bedrock costs money and time. Therefore, the GUI provides an interface to store embeddings in a vector store and back up the in-memory store. You can manage the collections in Weaviate and OpenSearch through the interface. The following table presents an overview of the different collections and how they were realised, including what splitter, embedding, and dataset were used.</p>

<p><img src="/assets/images/rag4pgui/rag4pgui-indexing.png" alt="Rag4p GUI ~ Indexing" /></p>

<h2 id="retrieving">Retrieving</h2>

<p>The retrieval part of the GUI is the most straightforward part. You choose the store to use. THe internal store, Weaviate or OpenSearch. For each store you select the collection to use. For Weaviate and OpenSearch you can choose hybrid search. Finally you select the retrieval strategy together with the amount of relevant chunks to retrieve. The following image shows the retrieval screen.</p>

<p><img src="/assets/images/rag4pgui/rag4pgui-retrieving.png" alt="Rag4p GUI ~ Retrieving" /></p>

<p>At the moment, Rag4p supports three retrieval strategies. The first strategy is the TopN strategy. This strategy retrieves the top N chunks based on the similarity between the query and the chunks. The second strategy is the Window strategy. This strategy retrieves the top N chunks based on the similarity between the query and the chunks and the chunks before and after the relevant chunk. The third strategy is the document strategy. This strategy retrieves the complete document of the appropriate chunk. The document retrieval includes the metadata of the document. This way, you can return information about the document’s title and author. The following image shows the retrieval screen.</p>

<p><img src="/assets/images/rag4pgui/rag4pgui-retrieving-result.png" alt="Rag4p GUI ~ Retrieving results" /></p>

<h2 id="generating">Generating</h2>

<p>Here we combine everything we have done so far. You select the content store to use with the collection. Select the retrieval strategy and the amount of relevant chunks to retrieve. Finally, you select the generator to use. The generator can be OpenAI, Bedrock or Ollama. The following image shows the generation screen. We used the document retrieval strategy in combination with hybrid search. With hybrid search, the speakers field is also searched. Therefore our talk at TeqNation is found.</p>

<p><img src="/assets/images/rag4pgui/rag4pgui-generating.png" alt="Rag4p GUI ~ Generating" /></p>

<p>The GUI is available on <a href="https://github.com/RAG4J/rag4p-gui">Github</a>. The project is still in its early stages.</p>]]></content><author><name></name></author><category term="news" /><summary type="html"><![CDATA[Yesterday was the first public appearance of my latest project, Rag4p-GUI. This project is a graphical interface for the Rag4p library. The goal for that project is to create a basic library or framework that we can use during workshops. You can understand the complete framework in an hour, essential for our workshops. The problem with the project is that it needed a GUI. So, I always used the command line during presentations, distracting me from the information I wanted to share. Therefore, I started working on a GUI. It could get a bit out of hand. In this post, I want to share the first version of the GUI. I’ll discuss the features that it has right now.]]></summary></entry><entry><title type="html">Workshop Teqnation 2024</title><link href="https://rag4j.org/conference/2024/04/04/workshop-teqnation-2024.html" rel="alternate" type="text/html" title="Workshop Teqnation 2024" /><published>2024-04-04T04:00:00+00:00</published><updated>2024-04-04T04:00:00+00:00</updated><id>https://rag4j.org/conference/2024/04/04/workshop-teqnation-2024</id><content type="html" xml:base="https://rag4j.org/conference/2024/04/04/workshop-teqnation-2024.html"><![CDATA[<p>The <em>22nd of May 2024</em>, Daniel and Jettro will visit DeFabrique in Utrecht for the annual Teqnation conference. In the morning, we will deliver
our workshop <a href="https://conference.teqnation.com/timetable/">The Art of Questions: Creating a Semantic Search-Based Question-Answering System with LLMs</a>.
This workshop makes use of our RAG4j/p project to teach a group of enthusiasts about the different aspects of
Retrieval Augmented Generation. We will use the project to show the different parts of a RAG system. Time is short, still we want participants to experience the essential parts of a RAG system. As the project is small, little time is lost learning it.</p>

<p>People attending the workshop will start from the beginning and perform all the different steps needed to build and evaluate a RAG system. To give you an idea of the different steps, here is a list of the different steps:</p>
<ul>
  <li>Work with text; use a splitter to split the text into sentences or other chunks.</li>
  <li>Use an embedder to create vectors from the chunks</li>
  <li>Use a retriever to find the most relevant chunks for a given question</li>
  <li>Use a generator to generate an answer based on the chunks and the question</li>
  <li>Use a quality component to determine the quality of the generated text and the relevance of the retrieved chunks</li>
</ul>

<p>We hope to see you in DeFabrique and that you will enjoy the workshop. If you have any questions, feel free to contact us.</p>

<p><em>22nd of May 2024 11:00 - 12:45 Room KALVERMELK 2C</em></p>

<hr />

<h2 id="preparing-for-the-workshop">Preparing for the workshop</h2>
<blockquote>
  <p>First choose your programming language (Java or Python). Then follow the instructions below:</p>

  <p>Java: <a href="https://github.com/RAG4J/rag4j-teqnation">RAG4j</a></p>

  <p>Python: <a href="https://github.com/RAG4J/rag4p-teqnation">RAG4p</a></p>

  <p>The repositories contain a README.md file with instructions on how to setup your environment.</p>
</blockquote>

<hr />

<p> </p>

<p><img src="/assets/images/teqnation-session.jpg" alt="Workshop Image" /></p>]]></content><author><name></name></author><category term="conference" /><summary type="html"><![CDATA[The 22nd of May 2024, Daniel and Jettro will visit DeFabrique in Utrecht for the annual Teqnation conference. In the morning, we will deliver our workshop The Art of Questions: Creating a Semantic Search-Based Question-Answering System with LLMs. This workshop makes use of our RAG4j/p project to teach a group of enthusiasts about the different aspects of Retrieval Augmented Generation. We will use the project to show the different parts of a RAG system. Time is short, still we want participants to experience the essential parts of a RAG system. As the project is small, little time is lost learning it.]]></summary></entry><entry><title type="html">Workshop jFokus 2024</title><link href="https://rag4j.org/conference/2024/01/24/workshop-jfokus-2024.html" rel="alternate" type="text/html" title="Workshop jFokus 2024" /><published>2024-01-24T04:00:00+00:00</published><updated>2024-01-24T04:00:00+00:00</updated><id>https://rag4j.org/conference/2024/01/24/workshop-jfokus-2024</id><content type="html" xml:base="https://rag4j.org/conference/2024/01/24/workshop-jfokus-2024.html"><![CDATA[<p>From 5 to 7 February 2024, Daniel and Jettro will visit Stockholm for the annual jFokus conference. On Monday, we will perform
our workshop <a href="https://www.jfokus.se/talks/1642">Creating a Semantic Search-Based Question-Answering System with LLMs</a>.
This session is the first occasion where we use our RAG4j/p project to teach a group of enthusiasts about the different aspects of
Retrieval Augmented Generation. We will use the project to show the different parts of a RAG system. There is plenty of
time to experiment with the different parts. As the project is small, little time is lost learning it.</p>

<p>People attending the workshop will start from the beginning and perform all the different steps needed to build and evaluate a RAG system. To give you an idea of the different steps, here is a list of the different steps:</p>
<ul>
  <li>Work with text; use a splitter to split the text into sentences or other chunks.</li>
  <li>Use an embedder to create vectors from the chunks</li>
  <li>Use a retriever to find the most relevant chunks for a given question</li>
  <li>Use a generator to generate an answer based on the chunks and the question</li>
  <li>Use a quality component to determine the quality of the generated text and the relevance of the retrieved chunks</li>
</ul>

<p>We hope to see you in Stockholm and that you will enjoy the workshop. If you have any questions, feel free to contact us.</p>

<p><em>5 February 09:00 - 12:30 Room 26</em></p>

<h2 id="starting-the-workshop">Starting the workshop</h2>
<p>First choose your programming language (Java or Python). Then follow the instructions below:</p>

<p><em>(Repositories become available on the day of the workshop)</em></p>

<p>Java: <a href="https://github.com/RAG4J/rag4j-jfokus">RAG4j</a></p>

<p>Python: <a href="https://github.com/RAG4J/rag4p-jfokus">RAG4p</a></p>

<p>The repositories contain a README.md file with instructions on how to setup your environment.</p>

<p><a href="/assets/preso/presentation-jfokus-2024.pdf">The presentation used during the workshop is available here</a>.</p>]]></content><author><name></name></author><category term="conference" /><summary type="html"><![CDATA[From 5 to 7 February 2024, Daniel and Jettro will visit Stockholm for the annual jFokus conference. On Monday, we will perform our workshop Creating a Semantic Search-Based Question-Answering System with LLMs. This session is the first occasion where we use our RAG4j/p project to teach a group of enthusiasts about the different aspects of Retrieval Augmented Generation. We will use the project to show the different parts of a RAG system. There is plenty of time to experiment with the different parts. As the project is small, little time is lost learning it.]]></summary></entry><entry><title type="html">Rag4p now available on PyPi</title><link href="https://rag4j.org/news/2024/01/24/rag4p-now-available-on-pypi.html" rel="alternate" type="text/html" title="Rag4p now available on PyPi" /><published>2024-01-24T04:00:00+00:00</published><updated>2024-01-24T04:00:00+00:00</updated><id>https://rag4j.org/news/2024/01/24/rag4p-now-available-on-pypi</id><content type="html" xml:base="https://rag4j.org/news/2024/01/24/rag4p-now-available-on-pypi.html"><![CDATA[<p>The Rag4p project is started to facilitate workshops. When working on other projects, I was copying the code from the 
Rag4p project to the project I was working on. This was not very efficient. Therefore I decided to make the project 
available on PyPi. This way I can use the project as a dependency in other projects.</p>

<p><a href="https://pypi.org/project/rag4p/">The project is available on PyPi</a></p>

<p>The source code of the project is available on <a href="https://github.com/RAG4J/rag4p">Github</a></p>

<h2 id="dspy---programming-language-models-using-python">DSPy - Programming Language Models using Python</h2>
<p>This is a sample application to learn about DSPy. DSPy separates the flow of your program in modules from the 
parameters like prompts and weights optimisation. It is a nice framework to create RAG, ReAct, and ChainOfThought
programs. The framework is available on <a href="https://github.com/stanfordnlp/dspy">Github</a></p>

<p>You can find the <a href="https://dspy-docs.vercel.app">Documentation</a> here.</p>

<p>The project is available on <a href="https://github.com/jettro/dspy-wordpress">Github</a>. At the moment this project is under
development. The project demonstrates how to import content from a wordpress blog into Weaviate and use DSPy to 
create a RAG and a multi step RAG solution.</p>]]></content><author><name></name></author><category term="news" /><summary type="html"><![CDATA[The Rag4p project is started to facilitate workshops. When working on other projects, I was copying the code from the Rag4p project to the project I was working on. This was not very efficient. Therefore I decided to make the project available on PyPi. This way I can use the project as a dependency in other projects.]]></summary></entry><entry><title type="html">Welcome to Rag4j!</title><link href="https://rag4j.org/general/2024/01/14/welcome-to-rag4j.html" rel="alternate" type="text/html" title="Welcome to Rag4j!" /><published>2024-01-14T12:35:54+00:00</published><updated>2024-01-14T12:35:54+00:00</updated><id>https://rag4j.org/general/2024/01/14/welcome-to-rag4j</id><content type="html" xml:base="https://rag4j.org/general/2024/01/14/welcome-to-rag4j.html"><![CDATA[<p>And we are live! This website is the homepage of RAG4j. A small Java framework to use RAG. Initially, it is for people to
learn the different parts of a RAG system. If you are not familiar with RAG, head over to the <a href="/documentation">Documentation</a>
section. Here, we will explain the basic concepts.</p>

<p>The main project will be available at <a href="https://github.com/RAG4J/rag4j">rag4j</a>. We are still working on JavaDoc, testing, and preparing the code for the public. The project will first appear at <a href="https://www.jfokus.se/talks/1642">jFokus 2024</a>.
We might make small changes based on the conference or the customer for whom we do the workshop. We will always add a blog post for each conference, to highlight what we will do at that specific event.</p>]]></content><author><name></name></author><category term="general" /><summary type="html"><![CDATA[And we are live! This website is the homepage of RAG4j. A small Java framework to use RAG. Initially, it is for people to learn the different parts of a RAG system. If you are not familiar with RAG, head over to the Documentation section. Here, we will explain the basic concepts.]]></summary></entry><entry><title type="html">Welcome to Rag4p!</title><link href="https://rag4j.org/general/2024/01/14/welcome-to-rag4p.html" rel="alternate" type="text/html" title="Welcome to Rag4p!" /><published>2024-01-14T12:35:54+00:00</published><updated>2024-01-14T12:35:54+00:00</updated><id>https://rag4j.org/general/2024/01/14/welcome-to-rag4p</id><content type="html" xml:base="https://rag4j.org/general/2024/01/14/welcome-to-rag4p.html"><![CDATA[<p>When we started with this project, we wanted to create an easy way to learn building RAG systems on the jvm. However, we did promise to give people a choice. Therefore we decided to create RAG4p next to RAG4j. RAG4p is a small Python framework to use RAG. Initially, it is for people to learn the different parts of a RAG system. If you are not familiar with RAG, head over to the <a href="/documentation">Documentation</a> section. Here, we will explain the basic concepts.</p>

<p>The main project is available at <a href="https://github.com/RAG4J/rag4p">rag4p</a>. We are still working on documentation, testing, and preparing the code for the public. The project will first appear at <a href="https://www.jfokus.se/talks/1642">jFokus 2024</a>. We might make small changes based on the conference or the customer for whom we do the workshop. We will always add a blog post for each conference, to highlight what we will do at that specific event.</p>]]></content><author><name></name></author><category term="general" /><summary type="html"><![CDATA[When we started with this project, we wanted to create an easy way to learn building RAG systems on the jvm. However, we did promise to give people a choice. Therefore we decided to create RAG4p next to RAG4j. RAG4p is a small Python framework to use RAG. Initially, it is for people to learn the different parts of a RAG system. If you are not familiar with RAG, head over to the Documentation section. Here, we will explain the basic concepts.]]></summary></entry></feed>